diff --git a/news/9180.bugfix.rst b/news/9180.bugfix.rst new file mode 100644 index 00000000000..e597c1ad90a --- /dev/null +++ b/news/9180.bugfix.rst @@ -0,0 +1 @@ +Fix error when an existing incompatibility is unable to be applied to a backtracked state. diff --git a/news/resolvelib.vendor.rst b/news/resolvelib.vendor.rst new file mode 100644 index 00000000000..680da3be1e7 --- /dev/null +++ b/news/resolvelib.vendor.rst @@ -0,0 +1 @@ +Upgrade resolvelib to 0.5.4. diff --git a/src/pip/_vendor/resolvelib/__init__.py b/src/pip/_vendor/resolvelib/__init__.py index 5a400f23ed1..f023ad63154 100644 --- a/src/pip/_vendor/resolvelib/__init__.py +++ b/src/pip/_vendor/resolvelib/__init__.py @@ -11,7 +11,7 @@ "ResolutionTooDeep", ] -__version__ = "0.5.3" +__version__ = "0.5.4" from .providers import AbstractProvider, AbstractResolver diff --git a/src/pip/_vendor/resolvelib/resolvers.py b/src/pip/_vendor/resolvelib/resolvers.py index acf0f8a6b43..bb88d8c2c75 100644 --- a/src/pip/_vendor/resolvelib/resolvers.py +++ b/src/pip/_vendor/resolvelib/resolvers.py @@ -257,7 +257,7 @@ def _backtrack(self): information from Y to Y'. 4a. If this causes Y' to conflict, we need to backtrack again. Make Y' the new Z and go back to step 2. - 4b. If the incompatibilites apply cleanly, end backtracking. + 4b. If the incompatibilities apply cleanly, end backtracking. """ while len(self._states) >= 3: # Remove the state that triggered backtracking. @@ -271,28 +271,36 @@ def _backtrack(self): for k, v in broken_state.criteria.items() ] + # Also mark the newly known incompatibility. + incompatibilities_from_broken.append((name, [candidate])) + self._r.backtracking(candidate) # Create a new state from the last known-to-work one, and apply # the previously gathered incompatibility information. - self._push_new_state() - for k, incompatibilities in incompatibilities_from_broken: - try: - crit = self.state.criteria[k] - except KeyError: - continue - self.state.criteria[k] = crit.excluded_of(incompatibilities) + def _patch_criteria(): + for k, incompatibilities in incompatibilities_from_broken: + if not incompatibilities: + continue + try: + criterion = self.state.criteria[k] + except KeyError: + continue + criterion = criterion.excluded_of(incompatibilities) + if criterion is None: + return False + self.state.criteria[k] = criterion + return True - # Mark the newly known incompatibility. - criterion = self.state.criteria[name].excluded_of([candidate]) + self._push_new_state() + success = _patch_criteria() # It works! Let's work on this new state. - if criterion: - self.state.criteria[name] = criterion + if success: return True - # State does not work after adding the new incompatibility - # information. Try the still previous state. + # State does not work after applying known incompatibilities. + # Try the still previous state. # No way to backtrack anymore. return False diff --git a/src/pip/_vendor/vendor.txt b/src/pip/_vendor/vendor.txt index 4f7042cc127..1db32f396ae 100644 --- a/src/pip/_vendor/vendor.txt +++ b/src/pip/_vendor/vendor.txt @@ -15,7 +15,7 @@ requests==2.25.0 chardet==3.0.4 idna==2.10 urllib3==1.26.2 -resolvelib==0.5.3 +resolvelib==0.5.4 retrying==1.3.3 setuptools==44.0.0 six==1.15.0