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:
def resolve_version(
root: ProjectPackage,
provider: Provider,
locked: dict[str, DependencyPackage] = None,
locked: dict[str, list[DependencyPackage]] = None,
use_latest: list[str] = None,
) -> SolverResult:
solver = VersionSolver(root, provider, locked=locked, use_latest=use_latest)
......
......@@ -18,13 +18,13 @@ from poetry.mixology.partial_solution import PartialSolution
from poetry.mixology.result import SolverResult
from poetry.mixology.set_relation import SetRelation
from poetry.mixology.term import Term
from poetry.packages import DependencyPackage
if TYPE_CHECKING:
from poetry.core.packages.package import Package
from poetry.core.packages.project_package import ProjectPackage
from poetry.packages import DependencyPackage
from poetry.puzzle.provider import Provider
......@@ -74,7 +74,7 @@ class VersionSolver:
self,
root: ProjectPackage,
provider: Provider,
locked: dict[str, Package] = None,
locked: dict[str, list[Package]] = None,
use_latest: list[str] = None,
):
self._root = root
......@@ -485,25 +485,19 @@ class VersionSolver:
def _get_locked(
self, dependency: Dependency, *, allow_similar: bool = False
) -> Package | None:
) -> DependencyPackage | None:
if dependency.name in self._use_latest:
return None
locked = self._locked.get(dependency.name)
if not locked:
return None
if not allow_similar and not dependency.is_same_package_as(locked):
return None
if not (
dependency.constraint.allows(locked.version)
or locked.is_prerelease()
and dependency.constraint.allows(locked.version.next_patch())
locked = self._locked.get(dependency.name, [])
for package in locked:
if (allow_similar or dependency.is_same_package_as(package)) and (
dependency.constraint.allows(package.version)
or package.is_prerelease()
and dependency.constraint.allows(package.version.next_patch())
):
return DependencyPackage(dependency, package.package)
return None
return locked
def _log(self, text: str) -> None:
self._provider.debug(text, self._solution.attempted_solutions)
......@@ -123,10 +123,13 @@ class Solver:
if self._provider._overrides:
self._overrides.append(self._provider._overrides)
locked = {
package.name: DependencyPackage(package.to_dependency(), package)
for package in self._locked.packages
}
locked = defaultdict(list)
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:
result = resolve_version(
......
......@@ -44,7 +44,9 @@ def check_solver_result(
use_latest: list[str] | None = None,
) -> 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)
try:
......
......@@ -3148,3 +3148,57 @@ def test_solver_should_not_raise_errors_for_irrelevant_transitive_python_constra
{"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