Commit d1dbdefc by David Hotham Committed by GitHub

Fix an infinite loop in the solver (#6178)

parent 77003f15
......@@ -513,11 +513,9 @@ class VersionSolver:
locked = self._locked.get(dependency.name, [])
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)
or package.is_prerelease()
and dependency.constraint.allows(package.version.next_patch())
):
if (
allow_similar or dependency.is_same_package_as(package)
) and dependency.constraint.allows(package.version):
return DependencyPackage(dependency, package)
return None
......
......@@ -46,7 +46,6 @@ if TYPE_CHECKING:
from poetry.core.packages.directory_dependency import DirectoryDependency
from poetry.core.packages.file_dependency import FileDependency
from poetry.core.packages.package import Package
from poetry.core.packages.specification import PackageSpecification
from poetry.core.packages.url_dependency import URLDependency
from poetry.core.packages.vcs_dependency import VCSDependency
from poetry.core.semver.version_constraint import VersionConstraint
......@@ -193,11 +192,11 @@ class Provider:
def search_for_installed_packages(
self,
specification: PackageSpecification,
dependency: Dependency,
) -> list[Package]:
"""
Search for installed packages, when available, that provides the given
specification.
Search for installed packages, when available, that satisfy the given
dependency.
This is useful when dealing with packages that are under development, not
published on package sources and/or only available via system installations.
......@@ -207,17 +206,17 @@ class Provider:
logger.debug(
"Falling back to installed packages to discover metadata for <c2>%s</>",
specification.complete_name,
dependency.complete_name,
)
packages = [
package
for package in self._installed_packages
if package.provides(specification)
if package.satisfies(dependency, ignore_source_type=True)
]
logger.debug(
"Found <c2>%d</> compatible packages for <c2>%s</>",
len(packages),
specification.complete_name,
dependency.complete_name,
)
return packages
......
......@@ -3648,3 +3648,36 @@ def test_solver_incompatible_dependency_with_and_without_extras(
{"job": "install", "package": foo},
],
)
def test_update_with_prerelease_and_no_solution(
solver: Solver,
repo: Repository,
installed: InstalledRepository,
package: ProjectPackage,
locked: Repository,
):
# Locked and installed: cleo which depends on an old version of crashtest.
cleo = get_package("cleo", "1.0.0a5")
crashtest = get_package("crashtest", "0.3.0")
cleo.add_dependency(Factory.create_dependency("crashtest", {"version": "<0.4.0"}))
locked.add_package(cleo)
locked.add_package(crashtest)
installed.add_package(cleo)
installed.add_package(crashtest)
# Try to upgrade to a new version of crashtest, this will be disallowed by the
# dependency from cleo.
package.add_dependency(Factory.create_dependency("cleo", "^1.0.0a5"))
package.add_dependency(Factory.create_dependency("crashtest", "^0.4.0"))
newer_crashtest = get_package("crashtest", "0.4.0")
even_newer_crashtest = get_package("crashtest", "0.4.1")
repo.add_package(cleo)
repo.add_package(crashtest)
repo.add_package(newer_crashtest)
repo.add_package(even_newer_crashtest)
with pytest.raises(SolverProblemError):
solver.solve()
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