From 0c609704d45fdaa5161846bcbc4248e3b31250b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Randy=20D=C3=B6ring?= <30527984+radoering@users.noreply.github.com> Date: Fri, 19 Aug 2022 19:44:27 +0200 Subject: [PATCH] installer: use locked version of vcs dependency with extras instead of latest (#6185) --- src/poetry/mixology/version_solver.py | 18 ++++--- .../with-vcs-dependency-with-extras.test | 47 +++++++++++++++++++ tests/installation/test_installer.py | 42 +++++++++++++++++ 3 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 tests/installation/fixtures/with-vcs-dependency-with-extras.test diff --git a/src/poetry/mixology/version_solver.py b/src/poetry/mixology/version_solver.py index a5b3961147a..7ff1d13ba80 100644 --- a/src/poetry/mixology/version_solver.py +++ b/src/poetry/mixology/version_solver.py @@ -418,11 +418,6 @@ def _get_min(dependency: Dependency) -> tuple[bool, int]: return complete_name package = None - if dependency.name not in self._use_latest: - # prefer locked version of compatible (not exact same) dependency; - # required in order to not unnecessarily update dependencies with - # extras, e.g. "coverage" vs. "coverage[toml]" - locked = self._get_locked(dependency, allow_similar=True) if locked is not None: package = next( ( @@ -504,9 +499,7 @@ def _add_incompatibility(self, incompatibility: Incompatibility) -> None: incompatibility ) - def _get_locked( - self, dependency: Dependency, *, allow_similar: bool = False - ) -> DependencyPackage | None: + def _get_locked(self, dependency: Dependency) -> DependencyPackage | None: if dependency.name in self._use_latest: return None @@ -514,8 +507,13 @@ def _get_locked( for dependency_package in locked: package = dependency_package.package if ( - allow_similar or dependency.is_same_package_as(package) - ) and dependency.constraint.allows(package.version): + # Locked dependencies are always without features. + # Thus, we can't use is_same_package_as() here because it compares + # the complete_name (including features). + dependency.name == package.name + and dependency.is_same_source_as(package) + and dependency.constraint.allows(package.version) + ): return DependencyPackage(dependency, package) return None diff --git a/tests/installation/fixtures/with-vcs-dependency-with-extras.test b/tests/installation/fixtures/with-vcs-dependency-with-extras.test new file mode 100644 index 00000000000..f64ba8e867e --- /dev/null +++ b/tests/installation/fixtures/with-vcs-dependency-with-extras.test @@ -0,0 +1,47 @@ +[[package]] +name = "demo" +version = "0.1.2" +description = "" +category = "main" +optional = false +python-versions = "*" +develop = false + +[package.dependencies] +cleo = {version = "*", optional = true, markers = "extra == \"foo\""} +pendulum = ">=1.4.4" + +[package.extras] +foo = ["cleo"] + +[package.source] +type = "git" +url = "https://github.com/demo/demo.git" +reference = "master" +resolved_reference = "123456" + +[[package]] +name = "pendulum" +version = "1.4.4" +description = "" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "cleo" +version = "1.0.0" +description = "" +category = "main" +optional = false +python-versions = "*" + +[metadata] +python-versions = "*" +lock-version = "1.1" +content-hash = "123456789" + +[metadata.files] +demo = [] +pendulum = [] +cleo = [] diff --git a/tests/installation/test_installer.py b/tests/installation/test_installer.py index 452ff425da9..96ff1306685 100644 --- a/tests/installation/test_installer.py +++ b/tests/installation/test_installer.py @@ -2473,3 +2473,45 @@ def test_installer_should_use_the_locked_version_of_git_dependencies( source_reference="master", source_resolved_reference="123456", ) + + +@pytest.mark.parametrize("is_locked", [False, True]) +def test_installer_should_use_the_locked_version_of_git_dependencies_with_extras( + installer: Installer, + locker: Locker, + package: ProjectPackage, + repo: Repository, + is_locked: bool, +): + if is_locked: + locker.locked(True) + locker.mock_lock_data(fixture("with-vcs-dependency-with-extras")) + expected_reference = "123456" + else: + expected_reference = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24" + + package.add_dependency( + Factory.create_dependency( + "demo", + { + "git": "https://github.com/demo/demo.git", + "branch": "master", + "extras": ["foo"], + }, + ) + ) + + repo.add_package(get_package("pendulum", "1.4.4")) + repo.add_package(get_package("cleo", "1.0.0")) + + installer.run() + + assert len(installer.executor.installations) == 3 + assert installer.executor.installations[-1] == Package( + "demo", + "0.1.2", + source_type="git", + source_url="https://github.com/demo/demo.git", + source_reference="master", + source_resolved_reference=expected_reference, + )