Skip to content

Commit 52ebb03

Browse files
committed
discard unusable dependencies
1 parent 405730c commit 52ebb03

File tree

2 files changed

+36
-27
lines changed

2 files changed

+36
-27
lines changed

src/poetry/mixology/version_solver.py

+36-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import functools
34
import time
45

56
from contextlib import suppress
@@ -17,6 +18,7 @@
1718
from poetry.mixology.result import SolverResult
1819
from poetry.mixology.set_relation import SetRelation
1920
from poetry.mixology.term import Term
21+
from poetry.packages import DependencyPackage
2022

2123

2224
if TYPE_CHECKING:
@@ -29,6 +31,36 @@
2931
_conflict = object()
3032

3133

34+
class DependencyCache:
35+
"""
36+
A cache of the valid dependencies.
37+
38+
The key observation here is that during the search - except at backtracking
39+
- once we have decided that a dependency is invalid, we never need check it
40+
again.
41+
"""
42+
43+
def __init__(self, provider: Provider):
44+
self.provider = provider
45+
self.cache: dict[str, list[Package]] = {}
46+
47+
@functools.lru_cache(maxsize=128)
48+
def search_for(self, dependency: Dependency) -> list[DependencyPackage]:
49+
complete_name = dependency.complete_name
50+
packages = self.cache.get(complete_name)
51+
if packages is None:
52+
packages = self.provider.search_for(dependency)
53+
else:
54+
packages = [p for p in packages if dependency.constraint.allows(p.version)]
55+
56+
self.cache[complete_name] = packages
57+
58+
return packages
59+
60+
def clear(self):
61+
self.cache.clear()
62+
63+
3264
class VersionSolver:
3365
"""
3466
The version solver that finds a set of package versions that satisfy the
@@ -47,6 +79,7 @@ def __init__(
4779
):
4880
self._root = root
4981
self._provider = provider
82+
self._dependency_cache = DependencyCache(provider)
5083
self._locked = locked or {}
5184

5285
if use_latest is None:
@@ -263,6 +296,7 @@ def _resolve_conflict(self, incompatibility: Incompatibility) -> Incompatibility
263296
):
264297
self._solution.backtrack(previous_satisfier_level)
265298
self._contradicted_incompatibilities.clear()
299+
self._dependency_cache.clear()
266300
if new_incompatibility:
267301
self._add_incompatibility(incompatibility)
268302

@@ -354,7 +388,7 @@ def _get_min(dependency: Dependency) -> tuple[bool, int]:
354388
try:
355389
return (
356390
not dependency.marker.is_any(),
357-
len(self._provider.search_for(dependency)),
391+
len(self._dependency_cache.search_for(dependency)),
358392
)
359393
except ValueError:
360394
return not dependency.marker.is_any(), 0
@@ -367,7 +401,7 @@ def _get_min(dependency: Dependency) -> tuple[bool, int]:
367401
locked = self._get_locked(dependency)
368402
if locked is None or not dependency.constraint.allows(locked.version):
369403
try:
370-
packages = self._provider.search_for(dependency)
404+
packages = self._dependency_cache.search_for(dependency)
371405
except ValueError as e:
372406
self._add_incompatibility(
373407
Incompatibility([Term(dependency, True)], PackageNotFoundCause(e))

src/poetry/puzzle/provider.py

-25
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ def __init__(
6767
self._io = io
6868
self._env = env
6969
self._python_constraint = package.python_constraint
70-
self._search_for: dict[Dependency, list[Package]] = {}
7170
self._is_debugging = self._io.is_debug() or self._io.is_very_verbose()
7271
self._in_progress = False
7372
self._overrides: dict = {}
@@ -119,28 +118,6 @@ def search_for(
119118
if dependency.is_root:
120119
return PackageCollection(dependency, [self._package])
121120

122-
for constraint in self._search_for:
123-
if (
124-
constraint.is_same_package_as(dependency)
125-
and constraint.constraint.intersect(dependency.constraint)
126-
== dependency.constraint
127-
):
128-
packages = [
129-
p
130-
for p in self._search_for[constraint]
131-
if dependency.constraint.allows(p.version)
132-
]
133-
134-
packages.sort(
135-
key=lambda p: (
136-
not p.is_prerelease() and not dependency.allows_prereleases(),
137-
p.version,
138-
),
139-
reverse=True,
140-
)
141-
142-
return PackageCollection(dependency, packages)
143-
144121
if dependency.is_vcs():
145122
packages = self.search_for_vcs(dependency)
146123
elif dependency.is_file():
@@ -160,8 +137,6 @@ def search_for(
160137
reverse=True,
161138
)
162139

163-
self._search_for[dependency] = packages
164-
165140
return PackageCollection(dependency, packages)
166141

167142
def search_for_vcs(self, dependency: VCSDependency) -> list[Package]:

0 commit comments

Comments
 (0)