From 9dcae01056b87d4f8bf9e8793a4f66206032728c Mon Sep 17 00:00:00 2001 From: Arun Babu Neelicattu Date: Fri, 29 Apr 2022 02:39:47 +0200 Subject: [PATCH] add initial support for single page repositories This change allows users to make use of find-links style single page sources that do not present a PEP 503 simple API repository. --- src/poetry/factory.py | 10 ++- .../repositories/single_page_repository.py | 15 +++++ .../fixtures/single-page/jax_releases.html | 27 ++++++++ .../test_single_page_repository.py | 61 +++++++++++++++++++ 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 src/poetry/repositories/single_page_repository.py create mode 100644 tests/repositories/fixtures/single-page/jax_releases.html create mode 100644 tests/repositories/test_single_page_repository.py diff --git a/src/poetry/factory.py b/src/poetry/factory.py index 5ff5be0b632..9657efa907a 100644 --- a/src/poetry/factory.py +++ b/src/poetry/factory.py @@ -1,5 +1,7 @@ from __future__ import annotations +import re + from pathlib import Path from typing import TYPE_CHECKING @@ -157,6 +159,7 @@ def create_legacy_repository( cls, source: dict[str, str], auth_config: Config ) -> LegacyRepository: from poetry.repositories.legacy_repository import LegacyRepository + from poetry.repositories.single_page_repository import SinglePageRepository from poetry.utils.helpers import get_cert from poetry.utils.helpers import get_client_cert @@ -169,7 +172,12 @@ def create_legacy_repository( name = source["name"] url = source["url"] - return LegacyRepository( + repository_class = LegacyRepository + + if re.match(r".*\.(htm|html)$", url): + repository_class = SinglePageRepository + + return repository_class( name, url, config=auth_config, diff --git a/src/poetry/repositories/single_page_repository.py b/src/poetry/repositories/single_page_repository.py new file mode 100644 index 00000000000..216254de6ee --- /dev/null +++ b/src/poetry/repositories/single_page_repository.py @@ -0,0 +1,15 @@ +from __future__ import annotations + +from poetry.repositories.legacy_repository import LegacyRepository +from poetry.repositories.link_sources.html import SimpleRepositoryPage + + +class SinglePageRepository(LegacyRepository): + def _get_page(self, endpoint: str = None) -> SimpleRepositoryPage | None: + """ + Single page repositories only have one page irrespective of endpoint. + """ + response = self._get_response("") + if not response: + return None + return SimpleRepositoryPage(response.url, response.text) diff --git a/tests/repositories/fixtures/single-page/jax_releases.html b/tests/repositories/fixtures/single-page/jax_releases.html new file mode 100644 index 00000000000..ce3232a9548 --- /dev/null +++ b/tests/repositories/fixtures/single-page/jax_releases.html @@ -0,0 +1,27 @@ + + + + +nocuda/jaxlib-0.3.0-cp310-none-manylinux2010_x86_64.whl
+nocuda/jaxlib-0.3.0-cp37-none-manylinux2010_x86_64.whl
+nocuda/jaxlib-0.3.0-cp38-none-manylinux2010_x86_64.whl
+nocuda/jaxlib-0.3.0-cp39-none-manylinux2010_x86_64.whl
+nocuda/jaxlib-0.3.2-cp310-none-manylinux2010_x86_64.whl
+nocuda/jaxlib-0.3.2-cp37-none-manylinux2010_x86_64.whl
+nocuda/jaxlib-0.3.2-cp38-none-manylinux2010_x86_64.whl
+nocuda/jaxlib-0.3.2-cp39-none-manylinux2010_x86_64.whl
+nocuda/jaxlib-0.3.5-cp310-none-manylinux2010_x86_64.whl
+nocuda/jaxlib-0.3.5-cp37-none-manylinux2010_x86_64.whl
+nocuda/jaxlib-0.3.5-cp38-none-manylinux2010_x86_64.whl
+nocuda/jaxlib-0.3.5-cp39-none-manylinux2010_x86_64.whl
+nocuda/jaxlib-0.3.7-cp310-none-manylinux2014_x86_64.whl
+nocuda/jaxlib-0.3.7-cp37-none-manylinux2014_x86_64.whl
+nocuda/jaxlib-0.3.7-cp38-none-manylinux2014_x86_64.whl
+nocuda/jaxlib-0.3.7-cp39-none-manylinux2014_x86_64.whl
+jax/jax-0.3.0.tar.gz
+jax/jax-0.3.2.tar.gz
+jax/jax-0.3.5.tar.gz
+jax/jax-0.3.6.tar.gz
+jax/jax-0.3.7.tar.gz
+ + diff --git a/tests/repositories/test_single_page_repository.py b/tests/repositories/test_single_page_repository.py new file mode 100644 index 00000000000..9ea409426a2 --- /dev/null +++ b/tests/repositories/test_single_page_repository.py @@ -0,0 +1,61 @@ +from __future__ import annotations + +import re + +from pathlib import Path + +from poetry.core.packages.dependency import Dependency + +from poetry.repositories.link_sources.html import SimpleRepositoryPage +from poetry.repositories.single_page_repository import SinglePageRepository + + +class MockSinglePageRepository(SinglePageRepository): + + FIXTURES = Path(__file__).parent / "fixtures" / "single-page" + + def __init__(self, page: str) -> None: + super().__init__( + "single-page", + url=f"http://single-page.foo.bar/{page}.html", + disable_cache=True, + ) + + def _get_page(self, endpoint: str = None) -> SimpleRepositoryPage | None: + fixture = self.FIXTURES / self.url.rsplit("/", 1)[-1] + if not fixture.exists(): + return + + with fixture.open(encoding="utf-8") as f: + return SimpleRepositoryPage(self._url, f.read()) + + def _download(self, url: str, dest: Path) -> None: + raise RuntimeError("Tests are not configured for downloads") + + +def test_single_page_repository_get_page(): + repo = MockSinglePageRepository("jax_releases") + + page = repo._get_page("/ignored") + links = list(page.links) + + assert len(links) == 21 + + for link in links: + assert re.match(r"^(jax|jaxlib)-0\.3\.\d.*\.(whl|tar\.gz)$", link.filename) + assert link.netloc == "storage.googleapis.com" + assert link.path.startswith("/jax-releases/") + + +def test_single_page_repository_find_packages(): + repo = MockSinglePageRepository("jax_releases") + + dep = Dependency("jaxlib", "0.3.7") + + packages = repo.find_packages(dep) + + assert len(packages) == 1 + + package = packages[0] + assert package.name == dep.name + assert package.to_dependency().to_pep_508() == dep.to_pep_508()