-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Allow external package repositories to be configured as non-legacy? #5337
Description
- 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:
- Legacy repositories using the traditional PEP503 repository layout, which involves parsing package metadata from HTML files like
/simple/mypackage. - "PyPi repositories" which use the pypi.org JSON api for fetching metadata.
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:
Lines 123 to 128 in 15f6ec1
| @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).