Skip to content

Commit 351da10

Browse files
Prefer backtracking on dependencies involved in the most recent conflict
This can significantly reduce the amount of backtracking required, by avoiding backtracking on unrelated packages in the dependency graph. Co-authored-by: Pradyun Gedam <[email protected]>
1 parent 04b9ece commit 351da10

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

news/10479.feature.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
When backtracking during dependency resolution, prefer the dependencies which are involved in the most recent conflict. This can significantly reduce the amount of backtracking required.

src/pip/_internal/resolution/resolvelib/provider.py

+19-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ def get_preference(
7171
identifier: str,
7272
resolutions: Mapping[str, Candidate],
7373
candidates: Mapping[str, Iterator[Candidate]],
74-
information: Mapping[str, Iterable["PreferenceInformation"]],
74+
information: Mapping[str, Iterator["PreferenceInformation"]],
75+
backtrack_causes: Sequence["RequirementInformation"],
7576
) -> "Preference":
7677
"""Produce a sort key for given requirement based on preference.
7778
@@ -132,11 +133,17 @@ def get_preference(
132133
# while we work on "proper" branch pruning techniques.
133134
delay_this = identifier == "setuptools"
134135

136+
# Prefer the causes of backtracking on the assumption that the problem
137+
# resolving the dependency tree is related to the failures that caused
138+
# the backtracking
139+
backtrack_cause = self.is_backtrack_cause(identifier, backtrack_causes)
140+
135141
return (
136142
not requires_python,
137143
delay_this,
138144
not direct,
139145
not pinned,
146+
not backtrack_cause,
140147
inferred_depth,
141148
requested_order,
142149
not unfree,
@@ -195,3 +202,14 @@ def is_satisfied_by(self, requirement: Requirement, candidate: Candidate) -> boo
195202
def get_dependencies(self, candidate: Candidate) -> Sequence[Requirement]:
196203
with_requires = not self._ignore_dependencies
197204
return [r for r in candidate.iter_dependencies(with_requires) if r is not None]
205+
206+
@staticmethod
207+
def is_backtrack_cause(
208+
identifier: str, backtrack_causes: Sequence["RequirementInformation"]
209+
) -> bool:
210+
for backtrack_cause in backtrack_causes:
211+
if identifier == backtrack_cause.requirement.name:
212+
return True
213+
if backtrack_cause.parent and identifier == backtrack_cause.parent.name:
214+
return True
215+
return False

0 commit comments

Comments
 (0)