From 426f0a3e72fdc3490447b7f327a1b05af3b64741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Eustace?= Date: Fri, 26 Mar 2021 11:29:08 +0100 Subject: [PATCH 1/2] Write PEP-610-compliant files when installing --- poetry/installation/executor.py | 135 +++++++++++++++++- tests/fixtures/simple_project/pyproject.toml | 5 + tests/installation/test_executor.py | 141 +++++++++++++++++++ 3 files changed, 277 insertions(+), 4 deletions(-) diff --git a/poetry/installation/executor.py b/poetry/installation/executor.py index 5e2daa012eb..84176431640 100644 --- a/poetry/installation/executor.py +++ b/poetry/installation/executor.py @@ -1,4 +1,5 @@ import itertools +import json import os import threading @@ -8,6 +9,7 @@ from subprocess import CalledProcessError from typing import TYPE_CHECKING from typing import Any +from typing import Dict from typing import List from typing import Union @@ -35,6 +37,7 @@ from cleo.io.io import IO # noqa from poetry.config.config import Config + from poetry.core.packages.package import Package from poetry.repositories import Pool from poetry.utils.env import Env @@ -82,6 +85,7 @@ def __init__( self._sections = dict() self._lock = threading.Lock() self._shutdown = False + self._hashes: Dict[str, str] = {} @property def installations_count(self) -> int: @@ -434,10 +438,18 @@ def _display_summary(self, operations: List["OperationTypes"]) -> None: self._io.write_line("") def _execute_install(self, operation: Union[Install, Update]) -> int: - return self._install(operation) + status_code = self._install(operation) + + self._save_url_reference(operation) + + return status_code def _execute_update(self, operation: Union[Install, Update]) -> int: - return self._update(operation) + status_code = self._update(operation) + + self._save_url_reference(operation) + + return status_code def _execute_uninstall(self, operation: Uninstall) -> int: message = ( @@ -594,12 +606,17 @@ def _install_git(self, operation: Union[Install, Update]) -> int: git = Git() git.clone(package.source_url, src_dir) - git.checkout(package.source_reference, src_dir) + git.checkout(package.source_resolved_reference, src_dir) # Now we just need to install from the source directory + original_url = package.source_url package._source_url = str(src_dir) - return self._install_directory(operation) + status_code = self._install_directory(operation) + + package._source_url = original_url + + return status_code def _download(self, operation: Union[Install, Update]) -> Link: link = self._chooser.choose_for(operation.package) @@ -636,6 +653,8 @@ def _download_link(self, operation: Union[Install, Update], link: Link) -> Link: f"Invalid hash for {package} using archive {archive.name}" ) + self._hashes[package.name] = archive_hash + return archive def _download_archive(self, operation: Union[Install, Update], link: Link) -> Path: @@ -689,3 +708,111 @@ def _download_archive(self, operation: Union[Install, Update], link: Link) -> Pa def _should_write_operation(self, operation: Operation) -> bool: return not operation.skipped or self._dry_run or self._verbose + + def _save_url_reference(self, operation: "OperationTypes") -> None: + """ + Create and store a PEP-610 `direct_url.json` file, if needed. + """ + if operation.job_type not in {"install", "update"}: + return + + from poetry.core.masonry.utils.helpers import escape_name + from poetry.core.masonry.utils.helpers import escape_version + + package = operation.package + + if not package.source_url: + # Since we are installing from our own distribution cache + # pip will write a `direct_url.json` file pointing to the cache + # distribution. + # That's not what we want so we remove the direct_url.json file, + # if it exists. + dist_info = self._env.site_packages.path.joinpath( + "{}-{}.dist-info".format( + escape_name(package.pretty_name), + escape_version(package.version.text), + ) + ) + if dist_info.exists() and dist_info.joinpath("direct_url.json").exists(): + dist_info.joinpath("direct_url.json").unlink() + + return + + url_reference = None + + if package.source_type == "git": + url_reference = self._create_git_url_reference(package) + elif package.source_type == "url": + url_reference = self._create_url_url_reference(package) + elif package.source_type == "directory": + url_reference = self._create_directory_url_reference(package) + elif package.source_type == "file": + url_reference = self._create_file_url_reference(package) + + if url_reference: + dist_info = self._env.site_packages.path.joinpath( + "{}-{}.dist-info".format( + escape_name(package.name), escape_version(package.version.text) + ) + ) + + if dist_info.exists(): + dist_info.joinpath("direct_url.json").write_text( + json.dumps(url_reference), encoding="utf-8" + ) + + def _create_git_url_reference( + self, package: "Package" + ) -> Dict[str, Union[str, Dict[str, str]]]: + reference = { + "url": package.source_url, + "vcs_info": { + "vcs": "git", + "requested_revision": package.source_reference, + "commit_id": package.source_resolved_reference, + }, + } + + return reference + + def _create_url_url_reference( + self, package: "Package" + ) -> Dict[str, Union[str, Dict[str, str]]]: + archive_info = {} + + if package.name in self._hashes: + archive_info["hash"] = self._hashes[package.name] + + reference = {"url": package.source_url, "archive_info": archive_info} + + return reference + + def _create_file_url_reference( + self, package: "Package" + ) -> Dict[str, Union[str, Dict[str, str]]]: + archive_info = {} + + if package.name in self._hashes: + archive_info["hash"] = self._hashes[package.name] + + reference = { + "url": Path(package.source_url).as_uri(), + "archive_info": archive_info, + } + + return reference + + def _create_directory_url_reference( + self, package: "Package" + ) -> Dict[str, Union[str, Dict[str, str]]]: + dir_info = {} + + if package.develop: + dir_info["editable"] = True + + reference = { + "url": Path(package.source_url).as_uri(), + "dir_info": dir_info, + } + + return reference diff --git a/tests/fixtures/simple_project/pyproject.toml b/tests/fixtures/simple_project/pyproject.toml index 0fd938e41a0..41a062fc09a 100644 --- a/tests/fixtures/simple_project/pyproject.toml +++ b/tests/fixtures/simple_project/pyproject.toml @@ -28,3 +28,8 @@ python = "~2.7 || ^3.4" foo = "foo:bar" baz = "bar:baz.boom.bim" fox = "fuz.foo:bar.baz" + + +[build-system] +requires = ["poetry-core>=1.0.2"] +build-backend = "poetry.core.masonry.api" diff --git a/tests/installation/test_executor.py b/tests/installation/test_executor.py index 4511e770a9d..f074078638d 100644 --- a/tests/installation/test_executor.py +++ b/tests/installation/test_executor.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +import json import re import shutil @@ -27,6 +28,7 @@ def env(tmp_dir): path = Path(tmp_dir) / ".venv" path.mkdir(parents=True) + return MockEnv(path=path, is_venv=True) @@ -261,3 +263,142 @@ def test_executor_should_delete_incomplete_downloads( executor._download(Install(Package("tomlkit", "0.5.3"))) assert not destination_fixture.exists() + + +def test_executor_should_write_pep610_url_references_for_files( + tmp_venv, pool, config, io +): + url = ( + Path(__file__) + .parent.parent.joinpath( + "fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl" + ) + .resolve() + ) + package = Package("demo", "0.1.0", source_type="file", source_url=url.as_posix()) + + executor = Executor(tmp_venv, pool, config, io) + executor.execute([Install(package)]) + + dist_info = tmp_venv.site_packages.path.joinpath("demo-0.1.0.dist-info") + assert dist_info.exists() + + direct_url_file = dist_info.joinpath("direct_url.json") + + assert direct_url_file.exists() + + url_reference = json.loads(direct_url_file.read_text(encoding="utf-8")) + + assert url_reference == {"archive_info": {}, "url": url.as_uri()} + + +def test_executor_should_write_pep610_url_references_for_directories( + tmp_venv, pool, config, io +): + url = Path(__file__).parent.parent.joinpath("fixtures/simple_project").resolve() + package = Package( + "simple-project", "1.2.3", source_type="directory", source_url=url.as_posix() + ) + + executor = Executor(tmp_venv, pool, config, io) + executor.execute([Install(package)]) + + dist_info = tmp_venv.site_packages.path.joinpath("simple_project-1.2.3.dist-info") + assert dist_info.exists() + + direct_url_file = dist_info.joinpath("direct_url.json") + + assert direct_url_file.exists() + + url_reference = json.loads(direct_url_file.read_text(encoding="utf-8")) + + assert url_reference == {"dir_info": {}, "url": url.as_uri()} + + +def test_executor_should_write_pep610_url_references_for_editable_directories( + tmp_venv, pool, config, io +): + url = Path(__file__).parent.parent.joinpath("fixtures/simple_project").resolve() + package = Package( + "simple-project", + "1.2.3", + source_type="directory", + source_url=url.as_posix(), + develop=True, + ) + + executor = Executor(tmp_venv, pool, config, io) + executor.execute([Install(package)]) + + dist_info = tmp_venv.site_packages.path.joinpath("simple_project-1.2.3.dist-info") + assert dist_info.exists() + + direct_url_file = dist_info.joinpath("direct_url.json") + + assert direct_url_file.exists() + + url_reference = json.loads(direct_url_file.read_text(encoding="utf-8")) + + assert url_reference == {"dir_info": {"editable": True}, "url": url.as_uri()} + + +def test_executor_should_write_pep610_url_references_for_urls( + tmp_venv, pool, config, io, mock_file_downloads +): + package = Package( + "demo", + "0.1.0", + source_type="url", + source_url="https://files.pythonhosted.org/demo-0.1.0-py2.py3-none-any.whl", + ) + + executor = Executor(tmp_venv, pool, config, io) + executor.execute([Install(package)]) + + dist_info = tmp_venv.site_packages.path.joinpath("demo-0.1.0.dist-info") + assert dist_info.exists() + + direct_url_file = dist_info.joinpath("direct_url.json") + + assert direct_url_file.exists() + + url_reference = json.loads(direct_url_file.read_text(encoding="utf-8")) + + assert url_reference == { + "archive_info": {}, + "url": "https://files.pythonhosted.org/demo-0.1.0-py2.py3-none-any.whl", + } + + +def test_executor_should_write_pep610_url_references_for_git( + tmp_venv, pool, config, io, mock_file_downloads +): + package = Package( + "demo", + "0.1.2", + source_type="git", + source_reference="master", + source_resolved_reference="123456", + source_url="https://github.com/demo/demo.git", + ) + + executor = Executor(tmp_venv, pool, config, io) + executor.execute([Install(package)]) + + dist_info = tmp_venv.site_packages.path.joinpath("demo-0.1.2.dist-info") + assert dist_info.exists() + + direct_url_file = dist_info.joinpath("direct_url.json") + + assert direct_url_file.exists() + + url_reference = json.loads(direct_url_file.read_text(encoding="utf-8")) + + assert url_reference == { + "vcs_info": { + "vcs": "git", + "requested_revision": "master", + "commit_id": "123456", + }, + "url": "https://github.com/demo/demo.git", + } From 3fa3b429351c7f3c71cb272e52a68b89e5f1b926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Eustace?= Date: Thu, 1 Apr 2021 18:39:28 +0200 Subject: [PATCH 2/2] Read PEP-610-compliant files when loading installed packages --- poetry/repositories/installed_repository.py | 192 +++++++++++++----- .../METADATA | 6 + .../direct_url.json | 4 + .../METADATA | 6 + .../direct_url.json | 6 + .../file_pep_610-1.2.3.dist-info/METADATA | 6 + .../direct_url.json | 6 + .../git_pep_610-1.2.3.dist-info/METADATA | 6 + .../direct_url.json | 8 + .../url_pep_610-1.2.3.dist-info/METADATA | 6 + .../direct_url.json | 4 + .../repositories/test_installed_repository.py | 64 ++++++ 12 files changed, 262 insertions(+), 52 deletions(-) create mode 100644 tests/repositories/fixtures/installed/lib/python3.7/site-packages/directory_pep_610-1.2.3.dist-info/METADATA create mode 100644 tests/repositories/fixtures/installed/lib/python3.7/site-packages/directory_pep_610-1.2.3.dist-info/direct_url.json create mode 100644 tests/repositories/fixtures/installed/lib/python3.7/site-packages/editable_directory_pep_610-1.2.3.dist-info/METADATA create mode 100644 tests/repositories/fixtures/installed/lib/python3.7/site-packages/editable_directory_pep_610-1.2.3.dist-info/direct_url.json create mode 100644 tests/repositories/fixtures/installed/lib/python3.7/site-packages/file_pep_610-1.2.3.dist-info/METADATA create mode 100644 tests/repositories/fixtures/installed/lib/python3.7/site-packages/file_pep_610-1.2.3.dist-info/direct_url.json create mode 100644 tests/repositories/fixtures/installed/lib/python3.7/site-packages/git_pep_610-1.2.3.dist-info/METADATA create mode 100644 tests/repositories/fixtures/installed/lib/python3.7/site-packages/git_pep_610-1.2.3.dist-info/direct_url.json create mode 100644 tests/repositories/fixtures/installed/lib/python3.7/site-packages/url_pep_610-1.2.3.dist-info/METADATA create mode 100644 tests/repositories/fixtures/installed/lib/python3.7/site-packages/url_pep_610-1.2.3.dist-info/direct_url.json diff --git a/poetry/repositories/installed_repository.py b/poetry/repositories/installed_repository.py index f33bbd9b99f..d89c9837c98 100644 --- a/poetry/repositories/installed_repository.py +++ b/poetry/repositories/installed_repository.py @@ -1,10 +1,15 @@ import itertools +import json from pathlib import Path +from typing import TYPE_CHECKING from typing import Set +from typing import Tuple from typing import Union from poetry.core.packages.package import Package +from poetry.core.packages.utils.utils import url_to_path +from poetry.core.utils.helpers import canonicalize_name from poetry.core.utils.helpers import module_name from poetry.utils._compat import metadata from poetry.utils.env import Env @@ -14,6 +19,9 @@ _VENDORS = Path(__file__).parent.parent.joinpath("_vendor") +if TYPE_CHECKING: + from importlib.metadata import Distribution + try: FileNotFoundError @@ -68,21 +76,14 @@ def get_package_paths(cls, env: Env, name: str) -> Set[Path]: return paths @classmethod - def set_package_vcs_properties_from_path(cls, src: Path, package: Package) -> None: + def get_package_vcs_properties_from_path(cls, src: Path) -> Tuple[str, str, str]: from poetry.core.vcs.git import Git git = Git() revision = git.rev_parse("HEAD", src).strip() url = git.remote_url(src) - package._source_type = "git" - package._source_url = url - package._source_reference = revision - - @classmethod - def set_package_vcs_properties(cls, package: Package, env: Env) -> None: - src = env.path / "src" / package.name - cls.set_package_vcs_properties_from_path(src, package) + return "git", url, revision @classmethod def is_vcs_package(cls, package: Union[Path, Package], env: Env) -> bool: @@ -99,6 +100,125 @@ def is_vcs_package(cls, package: Union[Path, Package], env: Env) -> bool: else: return True + @classmethod + def create_package_from_distribution( + cls, distribution: "Distribution", env: "Env" + ) -> Package: + # We first check for a direct_url.json file to determine + # the type of package. + path = Path(str(distribution._path)) + + if ( + path.name.endswith(".dist-info") + and path.joinpath("direct_url.json").exists() + ): + return cls.create_package_from_pep610(distribution) + + is_standard_package = env.is_path_relative_to_lib(path) + + source_type = None + source_url = None + source_reference = None + source_resolved_reference = None + if is_standard_package: + if path.name.endswith(".dist-info"): + paths = cls.get_package_paths( + env=env, name=distribution.metadata["name"] + ) + if paths: + is_editable_package = False + for src in paths: + if cls.is_vcs_package(src, env): + ( + source_type, + source_url, + source_reference, + ) = cls.get_package_vcs_properties_from_path(src) + break + + if not ( + is_editable_package or env.is_path_relative_to_lib(src) + ): + is_editable_package = True + else: + # TODO: handle multiple source directories? + if is_editable_package: + source_type = "directory" + source_url = paths.pop().as_posix() + else: + if cls.is_vcs_package(path, env): + ( + source_type, + source_url, + source_reference, + ) = cls.get_package_vcs_properties_from_path( + env.path / "src" / canonicalize_name(distribution.metadata["name"]) + ) + else: + # If not, it's a path dependency + source_type = "directory" + source_url = str(path.parent) + + package = Package( + distribution.metadata["name"], + distribution.metadata["version"], + source_type=source_type, + source_url=source_url, + source_reference=source_reference, + source_resolved_reference=source_resolved_reference, + ) + package.description = distribution.metadata.get("summary", "") + + return package + + @classmethod + def create_package_from_pep610(cls, distribution: "Distribution") -> Package: + path = Path(str(distribution._path)) + source_type = None + source_url = None + source_reference = None + source_resolved_reference = None + develop = False + + url_reference = json.loads( + path.joinpath("direct_url.json").read_text(encoding="utf-8") + ) + if "archive_info" in url_reference: + # File or URL distribution + if url_reference["url"].startswith("file:"): + # File distribution + source_type = "file" + source_url = url_to_path(url_reference["url"]).as_posix() + else: + # URL distribution + source_type = "url" + source_url = url_reference["url"] + elif "dir_info" in url_reference: + # Directory distribution + source_type = "directory" + source_url = url_to_path(url_reference["url"]).as_posix() + develop = url_reference["dir_info"].get("editable", False) + elif "vcs_info" in url_reference: + # VCS distribution + source_type = url_reference["vcs_info"]["vcs"] + source_url = url_reference["url"] + source_reference = url_reference["vcs_info"]["requested_revision"] + source_resolved_reference = url_reference["vcs_info"]["commit_id"] + + package = Package( + distribution.metadata["name"], + distribution.metadata["version"], + source_type=source_type, + source_url=source_url, + source_reference=source_reference, + source_resolved_reference=source_resolved_reference, + develop=develop, + ) + + package.description = distribution.metadata.get("summary", "") + + return package + @classmethod def load(cls, env: Env, with_dependencies: bool = False) -> "InstalledRepository": """ @@ -114,20 +234,13 @@ def load(cls, env: Env, with_dependencies: bool = False) -> "InstalledRepository metadata.distributions(path=[entry]), key=lambda d: str(d._path), ): - name = distribution.metadata["name"] - path = Path(str(distribution._path)) - version = distribution.metadata["version"] - package = Package(name, version, version) - package.description = distribution.metadata.get("summary", "") + name = canonicalize_name(distribution.metadata["name"]) - if with_dependencies: - for require in distribution.metadata.get_all("requires-dist", []): - dep = Dependency.create_from_pep_508(require) - package.add_dependency(dep) - - if package.name in seen: + if name in seen: continue + path = Path(str(distribution._path)) + try: path.relative_to(_VENDORS) except ValueError: @@ -135,39 +248,14 @@ def load(cls, env: Env, with_dependencies: bool = False) -> "InstalledRepository else: continue - seen.add(package.name) - - repo.add_package(package) + package = cls.create_package_from_distribution(distribution, env) - is_standard_package = env.is_path_relative_to_lib(path) - - if is_standard_package: - if path.name.endswith(".dist-info"): - paths = cls.get_package_paths(env=env, name=package.pretty_name) - if paths: - is_editable_package = False - for src in paths: - if cls.is_vcs_package(src, env): - cls.set_package_vcs_properties(package, env) - break - - if not ( - is_editable_package - or env.is_path_relative_to_lib(src) - ): - is_editable_package = True - else: - # TODO: handle multiple source directories? - if is_editable_package: - package._source_type = "directory" - package._source_url = paths.pop().as_posix() - continue + if with_dependencies: + for require in distribution.metadata.get_all("requires-dist", []): + dep = Dependency.create_from_pep_508(require) + package.add_dependency(dep) - if cls.is_vcs_package(path, env): - cls.set_package_vcs_properties(package, env) - else: - # If not, it's a path dependency - package._source_type = "directory" - package._source_url = str(path.parent) + seen.add(package.name) + repo.add_package(package) return repo diff --git a/tests/repositories/fixtures/installed/lib/python3.7/site-packages/directory_pep_610-1.2.3.dist-info/METADATA b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/directory_pep_610-1.2.3.dist-info/METADATA new file mode 100644 index 00000000000..30928a39f0c --- /dev/null +++ b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/directory_pep_610-1.2.3.dist-info/METADATA @@ -0,0 +1,6 @@ +Metadata-Version: 2.1 +Name: directory-pep-610 +Version: 1.2.3 +Summary: Foo +License: MIT +Requires-Python: >=3.6 diff --git a/tests/repositories/fixtures/installed/lib/python3.7/site-packages/directory_pep_610-1.2.3.dist-info/direct_url.json b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/directory_pep_610-1.2.3.dist-info/direct_url.json new file mode 100644 index 00000000000..3385611ce74 --- /dev/null +++ b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/directory_pep_610-1.2.3.dist-info/direct_url.json @@ -0,0 +1,4 @@ +{ + "url": "file:///path/to/distributions/directory-pep-610", + "dir_info": {} +} diff --git a/tests/repositories/fixtures/installed/lib/python3.7/site-packages/editable_directory_pep_610-1.2.3.dist-info/METADATA b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/editable_directory_pep_610-1.2.3.dist-info/METADATA new file mode 100644 index 00000000000..337c6fc4301 --- /dev/null +++ b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/editable_directory_pep_610-1.2.3.dist-info/METADATA @@ -0,0 +1,6 @@ +Metadata-Version: 2.1 +Name: editable-directory-pep-610 +Version: 1.2.3 +Summary: Foo +License: MIT +Requires-Python: >=3.6 diff --git a/tests/repositories/fixtures/installed/lib/python3.7/site-packages/editable_directory_pep_610-1.2.3.dist-info/direct_url.json b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/editable_directory_pep_610-1.2.3.dist-info/direct_url.json new file mode 100644 index 00000000000..e45f7c31a35 --- /dev/null +++ b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/editable_directory_pep_610-1.2.3.dist-info/direct_url.json @@ -0,0 +1,6 @@ +{ + "url": "file:///path/to/distributions/directory-pep-610", + "dir_info": { + "editable": true + } +} diff --git a/tests/repositories/fixtures/installed/lib/python3.7/site-packages/file_pep_610-1.2.3.dist-info/METADATA b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/file_pep_610-1.2.3.dist-info/METADATA new file mode 100644 index 00000000000..9478ca1f064 --- /dev/null +++ b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/file_pep_610-1.2.3.dist-info/METADATA @@ -0,0 +1,6 @@ +Metadata-Version: 2.1 +Name: file-pep-610 +Version: 1.2.3 +Summary: Foo +License: MIT +Requires-Python: >=3.6 diff --git a/tests/repositories/fixtures/installed/lib/python3.7/site-packages/file_pep_610-1.2.3.dist-info/direct_url.json b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/file_pep_610-1.2.3.dist-info/direct_url.json new file mode 100644 index 00000000000..d481649fa32 --- /dev/null +++ b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/file_pep_610-1.2.3.dist-info/direct_url.json @@ -0,0 +1,6 @@ +{ + "url": "file:///path/to/distributions/file-pep-610-1.2.3.tar.gz", + "archive_info": { + "hash": "sha256=2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae" + } +} diff --git a/tests/repositories/fixtures/installed/lib/python3.7/site-packages/git_pep_610-1.2.3.dist-info/METADATA b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/git_pep_610-1.2.3.dist-info/METADATA new file mode 100644 index 00000000000..bfc73cf720c --- /dev/null +++ b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/git_pep_610-1.2.3.dist-info/METADATA @@ -0,0 +1,6 @@ +Metadata-Version: 2.1 +Name: git-pep-610 +Version: 1.2.3 +Summary: Foo +License: MIT +Requires-Python: >=3.6 diff --git a/tests/repositories/fixtures/installed/lib/python3.7/site-packages/git_pep_610-1.2.3.dist-info/direct_url.json b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/git_pep_610-1.2.3.dist-info/direct_url.json new file mode 100644 index 00000000000..a3115254845 --- /dev/null +++ b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/git_pep_610-1.2.3.dist-info/direct_url.json @@ -0,0 +1,8 @@ +{ + "url": "https://github.com/demo/git-pep-610.git", + "vcs_info": { + "vcs": "git", + "requested_revision": "my-branch", + "commit_id": "123456" + } +} diff --git a/tests/repositories/fixtures/installed/lib/python3.7/site-packages/url_pep_610-1.2.3.dist-info/METADATA b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/url_pep_610-1.2.3.dist-info/METADATA new file mode 100644 index 00000000000..7b2afd3189b --- /dev/null +++ b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/url_pep_610-1.2.3.dist-info/METADATA @@ -0,0 +1,6 @@ +Metadata-Version: 2.1 +Name: url-pep-610 +Version: 1.2.3 +Summary: Foo +License: MIT +Requires-Python: >=3.6 diff --git a/tests/repositories/fixtures/installed/lib/python3.7/site-packages/url_pep_610-1.2.3.dist-info/direct_url.json b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/url_pep_610-1.2.3.dist-info/direct_url.json new file mode 100644 index 00000000000..b36e4055294 --- /dev/null +++ b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/url_pep_610-1.2.3.dist-info/direct_url.json @@ -0,0 +1,4 @@ +{ + "url": "https://python-poetry.org/distributions/url-pep-610-1.2.3.tar.gz", + "archive_info": {} +} diff --git a/tests/repositories/test_installed_repository.py b/tests/repositories/test_installed_repository.py index d10ab37af1d..5342181588d 100644 --- a/tests/repositories/test_installed_repository.py +++ b/tests/repositories/test_installed_repository.py @@ -30,6 +30,13 @@ metadata.PathDistribution(SITE_PURELIB / "editable-with-import-2.3.4.dist-info"), metadata.PathDistribution(SITE_PLATLIB / "lib64-2.3.4.dist-info"), metadata.PathDistribution(SITE_PLATLIB / "bender-2.0.5.dist-info"), + metadata.PathDistribution(SITE_PURELIB / "git_pep_610-1.2.3.dist-info"), + metadata.PathDistribution(SITE_PURELIB / "url_pep_610-1.2.3.dist-info"), + metadata.PathDistribution(SITE_PURELIB / "file_pep_610-1.2.3.dist-info"), + metadata.PathDistribution(SITE_PURELIB / "directory_pep_610-1.2.3.dist-info"), + metadata.PathDistribution( + SITE_PURELIB / "editable_directory_pep_610-1.2.3.dist-info" + ), ] @@ -165,3 +172,60 @@ def test_load_standard_package_with_pth_file(repository): assert standard.version.text == "1.2.3" assert standard.source_type is None assert standard.source_url is None + + +def test_load_pep_610_compliant_git_packages(repository): + package = get_package_from_repository("git-pep-610", repository) + + assert package is not None + assert package.name == "git-pep-610" + assert package.version.text == "1.2.3" + assert package.source_type == "git" + assert package.source_url == "https://github.com/demo/git-pep-610.git" + assert package.source_reference == "my-branch" + assert package.source_resolved_reference == "123456" + + +def test_load_pep_610_compliant_url_packages(repository): + package = get_package_from_repository("url-pep-610", repository) + + assert package is not None + assert package.name == "url-pep-610" + assert package.version.text == "1.2.3" + assert package.source_type == "url" + assert ( + package.source_url + == "https://python-poetry.org/distributions/url-pep-610-1.2.3.tar.gz" + ) + + +def test_load_pep_610_compliant_file_packages(repository): + package = get_package_from_repository("file-pep-610", repository) + + assert package is not None + assert package.name == "file-pep-610" + assert package.version.text == "1.2.3" + assert package.source_type == "file" + assert package.source_url == "/path/to/distributions/file-pep-610-1.2.3.tar.gz" + + +def test_load_pep_610_compliant_directory_packages(repository): + package = get_package_from_repository("directory-pep-610", repository) + + assert package is not None + assert package.name == "directory-pep-610" + assert package.version.text == "1.2.3" + assert package.source_type == "directory" + assert package.source_url == "/path/to/distributions/directory-pep-610" + assert not package.develop + + +def test_load_pep_610_compliant_editable_directory_packages(repository): + package = get_package_from_repository("editable-directory-pep-610", repository) + + assert package is not None + assert package.name == "editable-directory-pep-610" + assert package.version.text == "1.2.3" + assert package.source_type == "directory" + assert package.source_url == "/path/to/distributions/directory-pep-610" + assert package.develop