Skip to content

Allow external package repositories to be configured as non-legacy? #5337

@chriskuehl

Description

@chriskuehl
  • I have searched the issues of this repo and believe that this is not a duplicate.
  • I have searched the documentation and believe that my question is not covered.

Feature Request

My understanding is that currently Poetry supports two different types of package repositories:

The benefit of the JSON API is that it can include the requires_dist key to indicate the requirements of a package. This improves performance during version resolution because Poetry does not need to download each package from PyPI in order to check its dependencies.

From reading the code, it doesn't appear possible to tell Poetry to use the JSON API for private registries; instead, it always uses the legacy registry:

@classmethod
def configure_sources(
cls, poetry: Poetry, sources: list[dict[str, str]], config: Config, io: IO
) -> None:
for source in sources:
repository = cls.create_legacy_repository(source, config)

If Poetry supported an option to configure an internal registry as pypi.org-compatible, we could speed up certain version resolutions significantly. To give an example, on one internal project my company is testing out, this saves ~2.5 minutes and ~10 GB of downloaded files when resolving a particularly tricky dependency situation.

Would Poetry be willing to entertain this change? We would be happy to submit pull requests to implement this change if so.

Simple proof-of-concept patch

For reference, here is the patch I'm using to test this change currently:

diff --git a/src/poetry/factory.py b/src/poetry/factory.py
index 2a0b0b69..27895442 100644
--- a/src/poetry/factory.py
+++ b/src/poetry/factory.py
@@ -125,7 +125,12 @@ class Factory(BaseFactory):
         cls, poetry: Poetry, sources: list[dict[str, str]], config: Config, io: IO
     ) -> None:
         for source in sources:
-            repository = cls.create_legacy_repository(source, config)
+            if not bool(source.get("use_json_api", False)):
+                repository = cls.create_legacy_repository(source, config)
+            else:
+                from poetry.repositories.pypi_repository import PyPiRepository
+                repository = PyPiRepository(source["url"])
+
             is_default = bool(source.get("default", False))
             is_secondary = bool(source.get("secondary", False))
             if io.is_debug():
diff --git a/src/poetry/json/schemas/poetry-schema.json b/src/poetry/json/schemas/poetry-schema.json
index fe916f1e..3d6281e0 100644
--- a/src/poetry/json/schemas/poetry-schema.json
+++ b/src/poetry/json/schemas/poetry-schema.json
@@ -527,6 +527,10 @@
           "type": "boolean",
           "description": "Make this repository the default (disable PyPI)"
         },
+        "use_json_api": {
+          "type": "boolean",
+          "description": "Use the PyPI JSON API for fetching package metadata (faster if supported by your registry)."
+        },
         "secondary": {
           "type": "boolean",
           "description": "Declare this repository as secondary, i.e. it will only be looked up last for packages."

The actual solution would probably need to be a little bit more involved in order to support authentication (like is supported for legacy registries currently).

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/featureFeature requests/implementationsstatus/triageThis issue needs to be triaged

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions