Skip to content

Commit

Permalink
Fix for "poetry lock --no-update" so that dependencies with extras ar…
Browse files Browse the repository at this point in the history
…e not updated unnecessarily (#4618)

* Fix for "poetry lock --no-update" so that dependencies with extras are not updated unnecessarily

* None check instead of "or"

* Simplified logic (giving up possibility of early return when no matching version is found)

* Rename local variable for clarity
  • Loading branch information
radoering committed Mar 8, 2022
1 parent 70e38a1 commit b06658f
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 10 deletions.
30 changes: 20 additions & 10 deletions src/poetry/mixology/version_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import time

from contextlib import suppress
from typing import TYPE_CHECKING

from poetry.core.packages.dependency import Dependency
Expand Down Expand Up @@ -365,12 +366,21 @@ def _get_min(dependency: Dependency) -> tuple[bool, int]:
)
return dependency.complete_name

try:
version = packages[0]
except IndexError:
version = None
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._locked.get(dependency.name, None)
if locked is not None:
package = next(
(p for p in packages if p.version == locked.version), None
)
if package is None:
with suppress(IndexError):
package = packages[0]

if version is None:
if package is None:
# If there are no versions that satisfy the constraint,
# add an incompatibility that indicates that.
self._add_incompatibility(
Expand All @@ -379,12 +389,12 @@ def _get_min(dependency: Dependency) -> tuple[bool, int]:

return dependency.complete_name
else:
version = locked
package = locked

version = self._provider.complete_package(version)
package = self._provider.complete_package(package)

conflict = False
for incompatibility in self._provider.incompatibilities_for(version):
for incompatibility in self._provider.incompatibilities_for(package):
self._add_incompatibility(incompatibility)

# If an incompatibility is already satisfied, then selecting version
Expand All @@ -399,9 +409,9 @@ def _get_min(dependency: Dependency) -> tuple[bool, int]:
)

if not conflict:
self._solution.decide(version)
self._solution.decide(package)
self._log(
f"selecting {version.complete_name} ({version.full_pretty_version})"
f"selecting {package.complete_name} ({package.full_pretty_version})"
)

return dependency.complete_name
Expand Down
32 changes: 32 additions & 0 deletions tests/mixology/version_solver/test_with_lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,35 @@ def test_with_compatible_locked_dependencies_use_latest(
},
use_latest=["foo"],
)


def test_with_compatible_locked_dependencies_with_extras(
root: ProjectPackage, provider: Provider, repo: Repository
):
root.add_dependency(Factory.create_dependency("foo", "^1.0"))

package_foo_0 = get_package("foo", "1.0.0")
package_foo_1 = get_package("foo", "1.0.1")
bar_extra_dep = Factory.create_dependency(
"bar", {"version": "^1.0", "extras": "extra"}
)
for package_foo in (package_foo_0, package_foo_1):
package_foo.add_dependency(bar_extra_dep)
repo.add_package(package_foo)

bar_deps = {"baz": {"version": "^1.0", "extras": ["extra"]}}
add_to_repo(repo, "bar", "1.0.0", bar_deps)
add_to_repo(repo, "bar", "1.0.1", bar_deps)
add_to_repo(repo, "baz", "1.0.0")
add_to_repo(repo, "baz", "1.0.1")

check_solver_result(
root,
provider,
result={"foo": "1.0.0", "bar": "1.0.0", "baz": "1.0.0"},
locked={
"foo": get_package("foo", "1.0.0"),
"bar": get_package("bar", "1.0.0"),
"baz": get_package("baz", "1.0.0"),
},
)

0 comments on commit b06658f

Please sign in to comment.