diff --git a/poetry/puzzle/solver.py b/poetry/puzzle/solver.py index bc787508636..35b6bd86bb5 100644 --- a/poetry/puzzle/solver.py +++ b/poetry/puzzle/solver.py @@ -260,9 +260,10 @@ def _solve(self, use_latest: List[str] = None) -> Tuple[List[Package], List[int] except SolveFailure as e: raise SolverProblemError(e) + # NOTE passing explicit empty array for seen to reset between invocations during update + install cycle results = dict( depth_first_search( - PackageNode(self._package, packages), aggregate_package_nodes + PackageNode(self._package, packages, seen=[]), aggregate_package_nodes ) ) @@ -373,6 +374,7 @@ def __init__( self, package: Package, packages: List[Package], + seen: List[Package], previous: Optional["PackageNode"] = None, previous_dep: Optional[ Union[ @@ -395,6 +397,7 @@ def __init__( ) -> None: self.package = package self.packages = packages + self.seen = seen self.previous = previous self.previous_dep = previous_dep @@ -417,6 +420,12 @@ def __init__( def reachable(self) -> List["PackageNode"]: children: List[PackageNode] = [] + # skip already traversed packages + if self.package in self.seen: + return [] + else: + self.seen.append(self.package) + if ( self.previous_dep and self.previous_dep is not self.dep @@ -453,6 +462,7 @@ def reachable(self) -> List["PackageNode"]: PackageNode( pkg, self.packages, + self.seen, self, dependency, self.dep or dependency, diff --git a/tests/puzzle/test_solver.py b/tests/puzzle/test_solver.py index 37693b6333e..29e9689cf69 100644 --- a/tests/puzzle/test_solver.py +++ b/tests/puzzle/test_solver.py @@ -822,14 +822,14 @@ def test_solver_with_dependency_in_both_main_and_dev_dependencies( ], ) + d = ops[0].package b = ops[1].package c = ops[2].package - d = ops[0].package a = ops[3].package assert d.category == "dev" - assert c.category == "dev" assert b.category == "main" + assert c.category == "dev" assert a.category == "main" @@ -881,15 +881,15 @@ def test_solver_with_dependency_in_both_main_and_dev_dependencies_with_one_more_ ) b = ops[0].package - c = ops[3].package d = ops[1].package a = ops[2].package + c = ops[3].package e = ops[4].package - assert d.category == "dev" - assert c.category == "dev" assert b.category == "main" + assert d.category == "dev" assert a.category == "main" + assert c.category == "dev" assert e.category == "main"