summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPradyun Gedam <pradyunsg@users.noreply.github.com>2023-02-06 17:29:08 +0000
committerPradyun Gedam <pradyunsg@users.noreply.github.com>2023-02-06 17:45:51 +0000
commit8dbc2db274b0724d7b86eb1c2fbac6b0b4a4c4f6 (patch)
treef5ad726384622c1cf1dab59de055c0f6fa38fec4
parent6245fedc9d2bc6a5a6b332080ad34ad8f2f87e23 (diff)
downloadpip-8dbc2db274b0724d7b86eb1c2fbac6b0b4a4c4f6.tar.gz
Upgrade resolvelib to 0.9.0
-rw-r--r--news/resolvelib.vendor.rst1
-rw-r--r--src/pip/_vendor/resolvelib/__init__.py2
-rw-r--r--src/pip/_vendor/resolvelib/compat/collections_abc.pyi1
-rw-r--r--src/pip/_vendor/resolvelib/providers.py14
-rw-r--r--src/pip/_vendor/resolvelib/providers.pyi4
-rw-r--r--src/pip/_vendor/resolvelib/reporters.py2
-rw-r--r--src/pip/_vendor/resolvelib/reporters.pyi2
-rw-r--r--src/pip/_vendor/resolvelib/resolvers.py44
-rw-r--r--src/pip/_vendor/resolvelib/resolvers.pyi12
-rw-r--r--src/pip/_vendor/resolvelib/structs.py11
-rw-r--r--src/pip/_vendor/resolvelib/structs.pyi2
-rw-r--r--src/pip/_vendor/vendor.txt2
12 files changed, 78 insertions, 19 deletions
diff --git a/news/resolvelib.vendor.rst b/news/resolvelib.vendor.rst
new file mode 100644
index 000000000..c8b5c928d
--- /dev/null
+++ b/news/resolvelib.vendor.rst
@@ -0,0 +1 @@
+Upgrade resolvelib to 0.9.0
diff --git a/src/pip/_vendor/resolvelib/__init__.py b/src/pip/_vendor/resolvelib/__init__.py
index ce05fd302..fa6995e32 100644
--- a/src/pip/_vendor/resolvelib/__init__.py
+++ b/src/pip/_vendor/resolvelib/__init__.py
@@ -11,7 +11,7 @@ __all__ = [
"ResolutionTooDeep",
]
-__version__ = "0.8.1"
+__version__ = "0.9.0"
from .providers import AbstractProvider, AbstractResolver
diff --git a/src/pip/_vendor/resolvelib/compat/collections_abc.pyi b/src/pip/_vendor/resolvelib/compat/collections_abc.pyi
new file mode 100644
index 000000000..2a088b19a
--- /dev/null
+++ b/src/pip/_vendor/resolvelib/compat/collections_abc.pyi
@@ -0,0 +1 @@
+from collections.abc import Mapping, Sequence
diff --git a/src/pip/_vendor/resolvelib/providers.py b/src/pip/_vendor/resolvelib/providers.py
index 7d0a9c22a..e99d87ee7 100644
--- a/src/pip/_vendor/resolvelib/providers.py
+++ b/src/pip/_vendor/resolvelib/providers.py
@@ -1,5 +1,5 @@
class AbstractProvider(object):
- """Delegate class to provide requirement interface for the resolver."""
+ """Delegate class to provide the required interface for the resolver."""
def identify(self, requirement_or_candidate):
"""Given a requirement, return an identifier for it.
@@ -24,9 +24,9 @@ class AbstractProvider(object):
this group of arguments is.
:param identifier: An identifier as returned by ``identify()``. This
- identifies the dependency matches of which should be returned.
+ identifies the dependency matches which should be returned.
:param resolutions: Mapping of candidates currently pinned by the
- resolver. Each key is an identifier, and the value a candidate.
+ resolver. Each key is an identifier, and the value is a candidate.
The candidate may conflict with requirements from ``information``.
:param candidates: Mapping of each dependency's possible candidates.
Each value is an iterator of candidates.
@@ -39,10 +39,10 @@ class AbstractProvider(object):
* ``requirement`` specifies a requirement contributing to the current
list of candidates.
- * ``parent`` specifies the candidate that provides (dependend on) the
+ * ``parent`` specifies the candidate that provides (depended on) the
requirement, or ``None`` to indicate a root requirement.
- The preference could depend on a various of issues, including (not
+ The preference could depend on various issues, including (not
necessarily in this order):
* Is this package pinned in the current resolution result?
@@ -61,7 +61,7 @@ class AbstractProvider(object):
raise NotImplementedError
def find_matches(self, identifier, requirements, incompatibilities):
- """Find all possible candidates that satisfy given constraints.
+ """Find all possible candidates that satisfy the given constraints.
:param identifier: An identifier as returned by ``identify()``. This
identifies the dependency matches of which should be returned.
@@ -92,7 +92,7 @@ class AbstractProvider(object):
def is_satisfied_by(self, requirement, candidate):
"""Whether the given requirement can be satisfied by a candidate.
- The candidate is guarenteed to have been generated from the
+ The candidate is guaranteed to have been generated from the
requirement.
A boolean should be returned to indicate whether ``candidate`` is a
diff --git a/src/pip/_vendor/resolvelib/providers.pyi b/src/pip/_vendor/resolvelib/providers.pyi
index 47d6f8aba..ec054194e 100644
--- a/src/pip/_vendor/resolvelib/providers.pyi
+++ b/src/pip/_vendor/resolvelib/providers.pyi
@@ -1,12 +1,11 @@
from typing import (
Any,
- Collection,
Generic,
Iterable,
Iterator,
Mapping,
- Optional,
Protocol,
+ Sequence,
Union,
)
@@ -25,6 +24,7 @@ class AbstractProvider(Generic[RT, CT, KT]):
resolutions: Mapping[KT, CT],
candidates: Mapping[KT, Iterator[CT]],
information: Mapping[KT, Iterator[RequirementInformation[RT, CT]]],
+ backtrack_causes: Sequence[RequirementInformation[RT, CT]],
) -> Preference: ...
def find_matches(
self,
diff --git a/src/pip/_vendor/resolvelib/reporters.py b/src/pip/_vendor/resolvelib/reporters.py
index 6695480ff..688b5e10d 100644
--- a/src/pip/_vendor/resolvelib/reporters.py
+++ b/src/pip/_vendor/resolvelib/reporters.py
@@ -36,7 +36,7 @@ class BaseReporter(object):
:param causes: The information on the collision that caused the backtracking.
"""
- def backtracking(self, candidate):
+ def rejecting_candidate(self, criterion, candidate):
"""Called when rejecting a candidate during backtracking."""
def pinning(self, candidate):
diff --git a/src/pip/_vendor/resolvelib/reporters.pyi b/src/pip/_vendor/resolvelib/reporters.pyi
index 03d4f09a3..b2ad286ba 100644
--- a/src/pip/_vendor/resolvelib/reporters.pyi
+++ b/src/pip/_vendor/resolvelib/reporters.pyi
@@ -6,6 +6,6 @@ class BaseReporter:
def ending_round(self, index: int, state: Any) -> Any: ...
def ending(self, state: Any) -> Any: ...
def adding_requirement(self, requirement: Any, parent: Any) -> Any: ...
- def backtracking(self, candidate: Any) -> Any: ...
+ def rejecting_candidate(self, criterion: Any, candidate: Any) -> Any: ...
def resolving_conflicts(self, causes: Any) -> Any: ...
def pinning(self, candidate: Any) -> Any: ...
diff --git a/src/pip/_vendor/resolvelib/resolvers.py b/src/pip/_vendor/resolvelib/resolvers.py
index 787681b03..49e30c7f5 100644
--- a/src/pip/_vendor/resolvelib/resolvers.py
+++ b/src/pip/_vendor/resolvelib/resolvers.py
@@ -173,6 +173,31 @@ class Resolution(object):
raise RequirementsConflicted(criterion)
criteria[identifier] = criterion
+ def _remove_information_from_criteria(self, criteria, parents):
+ """Remove information from parents of criteria.
+
+ Concretely, removes all values from each criterion's ``information``
+ field that have one of ``parents`` as provider of the requirement.
+
+ :param criteria: The criteria to update.
+ :param parents: Identifiers for which to remove information from all criteria.
+ """
+ if not parents:
+ return
+ for key, criterion in criteria.items():
+ criteria[key] = Criterion(
+ criterion.candidates,
+ [
+ information
+ for information in criterion.information
+ if (
+ information[1] is None
+ or self._p.identify(information[1]) not in parents
+ )
+ ],
+ criterion.incompatibilities,
+ )
+
def _get_preference(self, name):
return self._p.get_preference(
identifier=name,
@@ -212,6 +237,7 @@ class Resolution(object):
try:
criteria = self._get_updated_criteria(candidate)
except RequirementsConflicted as e:
+ self._r.rejecting_candidate(e.criterion, candidate)
causes.append(e.criterion)
continue
@@ -281,8 +307,6 @@ class Resolution(object):
# Also mark the newly known incompatibility.
incompatibilities_from_broken.append((name, [candidate]))
- self._r.backtracking(candidate=candidate)
-
# Create a new state from the last known-to-work one, and apply
# the previously gathered incompatibility information.
def _patch_criteria():
@@ -368,6 +392,11 @@ class Resolution(object):
self._r.ending(state=self.state)
return self.state
+ # keep track of satisfied names to calculate diff after pinning
+ satisfied_names = set(self.state.criteria.keys()) - set(
+ unsatisfied_names
+ )
+
# Choose the most preferred unpinned criterion to try.
name = min(unsatisfied_names, key=self._get_preference)
failure_causes = self._attempt_to_pin_criterion(name)
@@ -384,6 +413,17 @@ class Resolution(object):
if not success:
raise ResolutionImpossible(self.state.backtrack_causes)
else:
+ # discard as information sources any invalidated names
+ # (unsatisfied names that were previously satisfied)
+ newly_unsatisfied_names = {
+ key
+ for key, criterion in self.state.criteria.items()
+ if key in satisfied_names
+ and not self._is_current_pin_satisfying(key, criterion)
+ }
+ self._remove_information_from_criteria(
+ self.state.criteria, newly_unsatisfied_names
+ )
# Pinning was successful. Push a new state to do another pin.
self._push_new_state()
diff --git a/src/pip/_vendor/resolvelib/resolvers.pyi b/src/pip/_vendor/resolvelib/resolvers.pyi
index 0eb5b2162..528a1a259 100644
--- a/src/pip/_vendor/resolvelib/resolvers.pyi
+++ b/src/pip/_vendor/resolvelib/resolvers.pyi
@@ -55,6 +55,18 @@ class ResolutionImpossible(ResolutionError, Generic[RT, CT]):
class ResolutionTooDeep(ResolutionError):
round_count: int
+# This should be a NamedTuple, but Python 3.6 has a bug that prevents it.
+# https://stackoverflow.com/a/50531189/1376863
+class State(tuple, Generic[RT, CT, KT]):
+ mapping: Mapping[KT, CT]
+ criteria: Mapping[KT, Criterion[RT, CT, KT]]
+ backtrack_causes: Collection[RequirementInformation[RT, CT]]
+
+class Resolution(Generic[RT, CT, KT]):
+ def resolve(
+ self, requirements: Iterable[RT], max_rounds: int
+ ) -> State[RT, CT, KT]: ...
+
class Result(Generic[RT, CT, KT]):
mapping: Mapping[KT, CT]
graph: DirectedGraph[Optional[KT]]
diff --git a/src/pip/_vendor/resolvelib/structs.py b/src/pip/_vendor/resolvelib/structs.py
index 93d1568bd..359a34f60 100644
--- a/src/pip/_vendor/resolvelib/structs.py
+++ b/src/pip/_vendor/resolvelib/structs.py
@@ -117,13 +117,14 @@ class _FactoryIterableView(object):
def __init__(self, factory):
self._factory = factory
+ self._iterable = None
def __repr__(self):
- return "{}({})".format(type(self).__name__, list(self._factory()))
+ return "{}({})".format(type(self).__name__, list(self))
def __bool__(self):
try:
- next(self._factory())
+ next(iter(self))
except StopIteration:
return False
return True
@@ -131,7 +132,11 @@ class _FactoryIterableView(object):
__nonzero__ = __bool__ # XXX: Python 2.
def __iter__(self):
- return self._factory()
+ iterable = (
+ self._factory() if self._iterable is None else self._iterable
+ )
+ self._iterable, current = itertools.tee(iterable)
+ return current
class _SequenceIterableView(object):
diff --git a/src/pip/_vendor/resolvelib/structs.pyi b/src/pip/_vendor/resolvelib/structs.pyi
index fae2a2fce..0ac59f0f0 100644
--- a/src/pip/_vendor/resolvelib/structs.pyi
+++ b/src/pip/_vendor/resolvelib/structs.pyi
@@ -16,7 +16,7 @@ RT = TypeVar("RT") # Requirement.
CT = TypeVar("CT") # Candidate.
_T = TypeVar("_T")
-Matches = Union[Iterable[CT], Callable[[], Iterator[CT]]]
+Matches = Union[Iterable[CT], Callable[[], Iterable[CT]]]
class IteratorMapping(Mapping[KT, _T], metaclass=ABCMeta):
pass
diff --git a/src/pip/_vendor/vendor.txt b/src/pip/_vendor/vendor.txt
index 67452d89f..703daf196 100644
--- a/src/pip/_vendor/vendor.txt
+++ b/src/pip/_vendor/vendor.txt
@@ -15,7 +15,7 @@ requests==2.28.2
rich==12.6.0
pygments==2.13.0
typing_extensions==4.4.0
-resolvelib==0.8.1
+resolvelib==0.9.0
setuptools==44.0.0
six==1.16.0
tenacity==8.1.0