From 41fd0b882513083acfa2c86d0355bcd0fdd2512d Mon Sep 17 00:00:00 2001 From: Ali <320322+ali5h@users.noreply.github.com> Date: Thu, 3 Feb 2022 21:43:22 -0800 Subject: [PATCH] sort package name in extras to make it reproducible (#280) this fixes python-poetry/poetry#5125 --- src/poetry/core/packages/dependency.py | 2 +- src/poetry/core/packages/directory_dependency.py | 2 +- src/poetry/core/packages/file_dependency.py | 2 +- src/poetry/core/packages/url_dependency.py | 2 +- src/poetry/core/packages/vcs_dependency.py | 2 +- tests/packages/test_dependency.py | 6 +++--- tests/packages/test_directory_dependency.py | 11 +++++++++++ tests/packages/test_file_dependency.py | 14 ++++++++++++++ tests/packages/test_url_dependency.py | 14 ++++++++++++++ tests/packages/test_vcs_dependency.py | 7 +++++-- 10 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/poetry/core/packages/dependency.py b/src/poetry/core/packages/dependency.py index c01ede94f..a539d59b6 100644 --- a/src/poetry/core/packages/dependency.py +++ b/src/poetry/core/packages/dependency.py @@ -253,7 +253,7 @@ def base_pep_508_name(self) -> str: requirement = self.pretty_name if self.extras: - extras = ",".join(self.extras) + extras = ",".join(sorted(self.extras)) requirement += f"[{extras}]" if isinstance(self.constraint, VersionUnion): diff --git a/src/poetry/core/packages/directory_dependency.py b/src/poetry/core/packages/directory_dependency.py index 4c51b39cc..75512bd43 100644 --- a/src/poetry/core/packages/directory_dependency.py +++ b/src/poetry/core/packages/directory_dependency.py @@ -119,7 +119,7 @@ def base_pep_508_name(self) -> str: requirement = self.pretty_name if self.extras: - extras = ",".join(self.extras) + extras = ",".join(sorted(self.extras)) requirement += f"[{extras}]" path = path_to_url(self.path) if self.path.is_absolute() else self.path diff --git a/src/poetry/core/packages/file_dependency.py b/src/poetry/core/packages/file_dependency.py index a1ecdcd30..a599f58e6 100644 --- a/src/poetry/core/packages/file_dependency.py +++ b/src/poetry/core/packages/file_dependency.py @@ -105,7 +105,7 @@ def base_pep_508_name(self) -> str: requirement = self.pretty_name if self.extras: - extras = ",".join(self.extras) + extras = ",".join(sorted(self.extras)) requirement += f"[{extras}]" path = path_to_url(self.path) if self.path.is_absolute() else self.path diff --git a/src/poetry/core/packages/url_dependency.py b/src/poetry/core/packages/url_dependency.py index 69d34500a..8a8c0c7e6 100644 --- a/src/poetry/core/packages/url_dependency.py +++ b/src/poetry/core/packages/url_dependency.py @@ -46,7 +46,7 @@ def base_pep_508_name(self) -> str: requirement = self.pretty_name if self.extras: - extras = ",".join(self.extras) + extras = ",".join(sorted(self.extras)) requirement += f"[{extras}]" requirement += f" @ {self._url}" diff --git a/src/poetry/core/packages/vcs_dependency.py b/src/poetry/core/packages/vcs_dependency.py index 241d5e798..6228d5fe4 100644 --- a/src/poetry/core/packages/vcs_dependency.py +++ b/src/poetry/core/packages/vcs_dependency.py @@ -110,7 +110,7 @@ def base_pep_508_name(self) -> str: parsed_url = git.ParsedUrl.parse(self._source) if self.extras: - extras = ",".join(self.extras) + extras = ",".join(sorted(self.extras)) requirement += f"[{extras}]" if parsed_url.protocol is not None: diff --git a/tests/packages/test_dependency.py b/tests/packages/test_dependency.py index a0b4beb5c..cbcc7d484 100644 --- a/tests/packages/test_dependency.py +++ b/tests/packages/test_dependency.py @@ -142,14 +142,14 @@ def test_to_pep_508_in_extras(): def test_to_pep_508_in_extras_parsed(): dependency = Dependency.create_from_pep_508( - 'foo[bar] (>=1.23,<2.0) ; extra == "baz"' + 'foo[baz,bar] (>=1.23,<2.0) ; extra == "baz"' ) result = dependency.to_pep_508() - assert result == 'foo[bar] (>=1.23,<2.0); extra == "baz"' + assert result == 'foo[bar,baz] (>=1.23,<2.0); extra == "baz"' result = dependency.to_pep_508(with_extras=False) - assert result == "foo[bar] (>=1.23,<2.0)" + assert result == "foo[bar,baz] (>=1.23,<2.0)" def test_to_pep_508_with_single_version_excluded(): diff --git a/tests/packages/test_directory_dependency.py b/tests/packages/test_directory_dependency.py index 83dc40b01..c64a17b78 100644 --- a/tests/packages/test_directory_dependency.py +++ b/tests/packages/test_directory_dependency.py @@ -61,3 +61,14 @@ def test_directory_dependency_pep_508_local_relative(): requirement = f"demo @ {path}" _test_directory_dependency_pep_508("demo", path, requirement) + + +def test_directory_dependency_pep_508_extras(): + path = ( + Path(__file__).parent.parent + / "fixtures" + / "project_with_multi_constraints_dependency" + ) + requirement = f"demo[foo,bar] @ file://{path.as_posix()}" + requirement_expected = f"demo[bar,foo] @ file://{path.as_posix()}" + _test_directory_dependency_pep_508("demo", path, requirement, requirement_expected) diff --git a/tests/packages/test_file_dependency.py b/tests/packages/test_file_dependency.py index 2ecbfcc29..bdf5f1e64 100644 --- a/tests/packages/test_file_dependency.py +++ b/tests/packages/test_file_dependency.py @@ -169,3 +169,17 @@ def test_relative_file_dependency_to_pep_508_with_marker(mocker: "MockerFixture" requirement, marker=SingleMarker("sys.platform", "linux"), ) + + +def test_file_dependency_pep_508_extras(mocker: "MockerFixture"): + wheel = "demo-0.1.0-py2.py3-none-any.whl" + + rel_path = Path("..") / "fixtures" / "distributions" / wheel + requirement = f'demo[foo,bar] @ {rel_path.as_posix()} ; sys_platform == "linux"' + _test_file_dependency_pep_508( + mocker, + "demo", + rel_path, + requirement, + f'demo[bar,foo] @ {rel_path.as_posix()} ; sys_platform == "linux"', + ) diff --git a/tests/packages/test_url_dependency.py b/tests/packages/test_url_dependency.py index 71b43f5e0..c265e5364 100644 --- a/tests/packages/test_url_dependency.py +++ b/tests/packages/test_url_dependency.py @@ -15,6 +15,20 @@ def test_to_pep_508(): assert dependency.to_pep_508() == expected +def test_to_pep_508_with_extras(): + dependency = URLDependency( + "pytorch", + "https://download.pytorch.org/whl/cpu/torch-1.5.1%2Bcpu-cp38-cp38-linux_x86_64.whl", + extras=["foo", "bar"], + ) + + expected = ( + "pytorch[bar,foo] @" + " https://download.pytorch.org/whl/cpu/torch-1.5.1%2Bcpu-cp38-cp38-linux_x86_64.whl" + ) + assert expected == dependency.to_pep_508() + + def test_to_pep_508_with_marker(): dependency = URLDependency( "pytorch", diff --git a/tests/packages/test_vcs_dependency.py b/tests/packages/test_vcs_dependency.py index 9c494f667..8e453c18f 100644 --- a/tests/packages/test_vcs_dependency.py +++ b/tests/packages/test_vcs_dependency.py @@ -25,10 +25,13 @@ def test_to_pep_508_ssh(): def test_to_pep_508_with_extras(): dependency = VCSDependency( - "poetry", "git", "https://github.com/python-poetry/poetry.git", extras=["foo"] + "poetry", + "git", + "https://github.com/python-poetry/poetry.git", + extras=["foo", "bar"], ) - expected = "poetry[foo] @ git+https://github.com/python-poetry/poetry.git" + expected = "poetry[bar,foo] @ git+https://github.com/python-poetry/poetry.git" assert dependency.to_pep_508() == expected