Commit b91531eb by Randy Döring Committed by Arun Babu Neelicattu

solver: do not drop required locked dependencies when locking with --no-update option

parent d34dba71
...@@ -16,7 +16,7 @@ if TYPE_CHECKING: ...@@ -16,7 +16,7 @@ if TYPE_CHECKING:
def resolve_version( def resolve_version(
root: ProjectPackage, root: ProjectPackage,
provider: Provider, provider: Provider,
locked: dict[str, DependencyPackage] = None, locked: dict[str, list[DependencyPackage]] = None,
use_latest: list[str] = None, use_latest: list[str] = None,
) -> SolverResult: ) -> SolverResult:
solver = VersionSolver(root, provider, locked=locked, use_latest=use_latest) solver = VersionSolver(root, provider, locked=locked, use_latest=use_latest)
......
...@@ -18,13 +18,13 @@ from poetry.mixology.partial_solution import PartialSolution ...@@ -18,13 +18,13 @@ from poetry.mixology.partial_solution import PartialSolution
from poetry.mixology.result import SolverResult from poetry.mixology.result import SolverResult
from poetry.mixology.set_relation import SetRelation from poetry.mixology.set_relation import SetRelation
from poetry.mixology.term import Term from poetry.mixology.term import Term
from poetry.packages import DependencyPackage
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages.package import Package from poetry.core.packages.package import Package
from poetry.core.packages.project_package import ProjectPackage from poetry.core.packages.project_package import ProjectPackage
from poetry.packages import DependencyPackage
from poetry.puzzle.provider import Provider from poetry.puzzle.provider import Provider
...@@ -74,7 +74,7 @@ class VersionSolver: ...@@ -74,7 +74,7 @@ class VersionSolver:
self, self,
root: ProjectPackage, root: ProjectPackage,
provider: Provider, provider: Provider,
locked: dict[str, Package] = None, locked: dict[str, list[Package]] = None,
use_latest: list[str] = None, use_latest: list[str] = None,
): ):
self._root = root self._root = root
...@@ -485,25 +485,19 @@ class VersionSolver: ...@@ -485,25 +485,19 @@ class VersionSolver:
def _get_locked( def _get_locked(
self, dependency: Dependency, *, allow_similar: bool = False self, dependency: Dependency, *, allow_similar: bool = False
) -> Package | None: ) -> DependencyPackage | None:
if dependency.name in self._use_latest: if dependency.name in self._use_latest:
return None return None
locked = self._locked.get(dependency.name) locked = self._locked.get(dependency.name, [])
if not locked: for package in locked:
return None if (allow_similar or dependency.is_same_package_as(package)) and (
dependency.constraint.allows(package.version)
if not allow_similar and not dependency.is_same_package_as(locked): or package.is_prerelease()
return None and dependency.constraint.allows(package.version.next_patch())
):
if not ( return DependencyPackage(dependency, package.package)
dependency.constraint.allows(locked.version) return None
or locked.is_prerelease()
and dependency.constraint.allows(locked.version.next_patch())
):
return None
return locked
def _log(self, text: str) -> None: def _log(self, text: str) -> None:
self._provider.debug(text, self._solution.attempted_solutions) self._provider.debug(text, self._solution.attempted_solutions)
...@@ -123,10 +123,13 @@ class Solver: ...@@ -123,10 +123,13 @@ class Solver:
if self._provider._overrides: if self._provider._overrides:
self._overrides.append(self._provider._overrides) self._overrides.append(self._provider._overrides)
locked = { locked = defaultdict(list)
package.name: DependencyPackage(package.to_dependency(), package) for package in self._locked.packages:
for package in self._locked.packages locked[package.name].append(
} DependencyPackage(package.to_dependency(), package)
)
for packages in locked.values():
packages.sort(key=lambda package: package.version, reverse=True)
try: try:
result = resolve_version( result = resolve_version(
......
...@@ -44,7 +44,9 @@ def check_solver_result( ...@@ -44,7 +44,9 @@ def check_solver_result(
use_latest: list[str] | None = None, use_latest: list[str] | None = None,
) -> None: ) -> None:
if locked is not None: if locked is not None:
locked = {k: DependencyPackage(l.to_dependency(), l) for k, l in locked.items()} locked = {
k: [DependencyPackage(l.to_dependency(), l)] for k, l in locked.items()
}
solver = VersionSolver(root, provider, locked=locked, use_latest=use_latest) solver = VersionSolver(root, provider, locked=locked, use_latest=use_latest)
try: try:
......
...@@ -3148,3 +3148,57 @@ def test_solver_should_not_raise_errors_for_irrelevant_transitive_python_constra ...@@ -3148,3 +3148,57 @@ def test_solver_should_not_raise_errors_for_irrelevant_transitive_python_constra
{"job": "install", "package": virtualenv}, {"job": "install", "package": virtualenv},
], ],
) )
@pytest.mark.parametrize("is_locked", [False, True])
def test_solver_keeps_multiple_locked_dependencies_for_same_package(
solver: Solver,
repo: Repository,
package: Package,
locked: Repository,
is_locked: bool,
):
solver.provider.set_package_python_versions("^3.6")
package.add_dependency(
Factory.create_dependency("A", {"version": "~1.1", "python": "<3.7"})
)
package.add_dependency(
Factory.create_dependency("A", {"version": "~1.2", "python": ">=3.7"})
)
a11 = Package("A", "1.1")
a12 = Package("A", "1.2")
a11.add_dependency(Factory.create_dependency("B", {"version": ">=0.3"}))
a12.add_dependency(Factory.create_dependency("B", {"version": ">=0.3"}))
b03 = Package("B", "0.3")
b04 = Package("B", "0.4")
b04.python_versions = ">=3.6.2,<4.0.0"
repo.add_package(a11)
repo.add_package(a12)
repo.add_package(b03)
repo.add_package(b04)
if is_locked:
a11_locked = a11.clone()
a11_locked.python_versions = "<3.7"
locked.add_package(a11_locked)
a12_locked = a12.clone()
a12_locked.python_versions = ">=3.7"
locked.add_package(a12_locked)
locked.add_package(b03.clone())
locked.add_package(b04.clone())
transaction = solver.solve()
check_solver_result(
transaction,
[
{"job": "install", "package": b03},
{"job": "install", "package": b04},
{"job": "install", "package": a11},
{"job": "install", "package": a12},
],
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment