mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
Upgrade resolvelib to 0.5.2
This commit is contained in:
parent
e76b1ddeaa
commit
910b304a97
1
news/resolvelib.vendor.rst
Normal file
1
news/resolvelib.vendor.rst
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Upgrade resolvelib to 0.5.2
|
|
@ -11,7 +11,7 @@ __all__ = [
|
||||||
"ResolutionTooDeep",
|
"ResolutionTooDeep",
|
||||||
]
|
]
|
||||||
|
|
||||||
__version__ = "0.4.0"
|
__version__ = "0.5.2"
|
||||||
|
|
||||||
|
|
||||||
from .providers import AbstractProvider, AbstractResolver
|
from .providers import AbstractProvider, AbstractResolver
|
||||||
|
|
|
@ -1,32 +1,36 @@
|
||||||
class AbstractProvider(object):
|
class AbstractProvider(object):
|
||||||
"""Delegate class to provide requirement interface for the resolver.
|
"""Delegate class to provide requirement interface for the resolver."""
|
||||||
"""
|
|
||||||
|
|
||||||
def identify(self, dependency):
|
def identify(self, requirement_or_candidate):
|
||||||
"""Given a dependency, return an identifier for it.
|
"""Given a requirement or candidate, return an identifier for it.
|
||||||
|
|
||||||
This is used in many places to identify the dependency, e.g. whether
|
This is used in many places to identify a requirement or candidate,
|
||||||
two requirements should have their specifier parts merged, whether
|
e.g. whether two requirements should have their specifier parts merged,
|
||||||
two specifications would conflict with each other (because they the
|
whether two candidates would conflict with each other (because they
|
||||||
same name but different versions).
|
have same name but different versions).
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def get_preference(self, resolution, candidates, information):
|
def get_preference(self, resolution, candidates, information):
|
||||||
"""Produce a sort key for given specification based on preference.
|
"""Produce a sort key for given requirement based on preference.
|
||||||
|
|
||||||
The preference is defined as "I think this requirement should be
|
The preference is defined as "I think this requirement should be
|
||||||
resolved first". The lower the return value is, the more preferred
|
resolved first". The lower the return value is, the more preferred
|
||||||
this group of arguments is.
|
this group of arguments is.
|
||||||
|
|
||||||
:param resolution: Currently pinned candidate, or `None`.
|
:param resolution: Currently pinned candidate, or `None`.
|
||||||
:param candidates: A list of possible candidates.
|
:param candidates: An iterable of possible candidates.
|
||||||
:param information: A list of requirement information.
|
:param information: A list of requirement information.
|
||||||
|
|
||||||
Each information instance is a named tuple with two entries:
|
The `candidates` iterable's exact type depends on the return type of
|
||||||
|
`find_matches()`. A sequence is passed-in as-is if possible. If it
|
||||||
|
returns a callble, the iterator returned by that callable is passed
|
||||||
|
in here.
|
||||||
|
|
||||||
|
Each element in `information` is a named tuple with two entries:
|
||||||
|
|
||||||
* `requirement` specifies a requirement contributing to the current
|
* `requirement` specifies a requirement contributing to the current
|
||||||
candidate list
|
candidate list.
|
||||||
* `parent` specifies the candidate that provides (dependend on) the
|
* `parent` specifies the candidate that provides (dependend on) the
|
||||||
requirement, or `None` to indicate a root requirement.
|
requirement, or `None` to indicate a root requirement.
|
||||||
|
|
||||||
|
@ -43,7 +47,7 @@ class AbstractProvider(object):
|
||||||
|
|
||||||
A sortable value should be returned (this will be used as the `key`
|
A sortable value should be returned (this will be used as the `key`
|
||||||
parameter of the built-in sorting function). The smaller the value is,
|
parameter of the built-in sorting function). The smaller the value is,
|
||||||
the more preferred this specification is (i.e. the sorting function
|
the more preferred this requirement is (i.e. the sorting function
|
||||||
is called with `reverse=False`).
|
is called with `reverse=False`).
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -56,11 +60,18 @@ class AbstractProvider(object):
|
||||||
returned, and for a "named" requirement, the index(es) should be
|
returned, and for a "named" requirement, the index(es) should be
|
||||||
consulted to find concrete candidates for this requirement.
|
consulted to find concrete candidates for this requirement.
|
||||||
|
|
||||||
:param requirements: A collection of requirements which all of the the
|
The return value should produce candidates ordered by preference; the
|
||||||
|
most preferred candidate should come first. The return type may be one
|
||||||
|
of the following:
|
||||||
|
|
||||||
|
* A callable that returns an iterator that yields candidates.
|
||||||
|
* An collection of candidates.
|
||||||
|
* An iterable of candidates. This will be consumed immediately into a
|
||||||
|
list of candidates.
|
||||||
|
|
||||||
|
:param requirements: A collection of requirements which all of the
|
||||||
returned candidates must match. All requirements are guaranteed to
|
returned candidates must match. All requirements are guaranteed to
|
||||||
have the same identifier. The collection is never empty.
|
have the same identifier. The collection is never empty.
|
||||||
:returns: An iterable that orders candidates by preference, e.g. the
|
|
||||||
most preferred candidate should come first.
|
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@ -85,8 +96,7 @@ class AbstractProvider(object):
|
||||||
|
|
||||||
|
|
||||||
class AbstractResolver(object):
|
class AbstractResolver(object):
|
||||||
"""The thing that performs the actual resolution work.
|
"""The thing that performs the actual resolution work."""
|
||||||
"""
|
|
||||||
|
|
||||||
base_exception = Exception
|
base_exception = Exception
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
class BaseReporter(object):
|
class BaseReporter(object):
|
||||||
"""Delegate class to provider progress reporting for the resolver.
|
"""Delegate class to provider progress reporting for the resolver."""
|
||||||
"""
|
|
||||||
|
|
||||||
def starting(self):
|
def starting(self):
|
||||||
"""Called before the resolution actually starts.
|
"""Called before the resolution actually starts."""
|
||||||
"""
|
|
||||||
|
|
||||||
def starting_round(self, index):
|
def starting_round(self, index):
|
||||||
"""Called before each round of resolution starts.
|
"""Called before each round of resolution starts.
|
||||||
|
@ -20,8 +18,7 @@ class BaseReporter(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def ending(self, state):
|
def ending(self, state):
|
||||||
"""Called before the resolution ends successfully.
|
"""Called before the resolution ends successfully."""
|
||||||
"""
|
|
||||||
|
|
||||||
def adding_requirement(self, requirement, parent):
|
def adding_requirement(self, requirement, parent):
|
||||||
"""Called when adding a new requirement into the resolve criteria.
|
"""Called when adding a new requirement into the resolve criteria.
|
||||||
|
@ -34,9 +31,7 @@ class BaseReporter(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def backtracking(self, candidate):
|
def backtracking(self, candidate):
|
||||||
"""Called when rejecting a candidate during backtracking.
|
"""Called when rejecting a candidate during backtracking."""
|
||||||
"""
|
|
||||||
|
|
||||||
def pinning(self, candidate):
|
def pinning(self, candidate):
|
||||||
"""Called when adding a candidate to the potential solution.
|
"""Called when adding a candidate to the potential solution."""
|
||||||
"""
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
from .compat import collections_abc
|
|
||||||
from .providers import AbstractResolver
|
from .providers import AbstractResolver
|
||||||
from .structs import DirectedGraph
|
from .structs import DirectedGraph, build_iter_view
|
||||||
|
|
||||||
|
|
||||||
RequirementInformation = collections.namedtuple(
|
RequirementInformation = collections.namedtuple(
|
||||||
|
@ -76,17 +75,11 @@ class Criterion(object):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_requirement(cls, provider, requirement, parent):
|
def from_requirement(cls, provider, requirement, parent):
|
||||||
"""Build an instance from a requirement.
|
"""Build an instance from a requirement."""
|
||||||
"""
|
cands = build_iter_view(provider.find_matches([requirement]))
|
||||||
candidates = provider.find_matches([requirement])
|
infos = [RequirementInformation(requirement, parent)]
|
||||||
if not isinstance(candidates, collections_abc.Sequence):
|
criterion = cls(cands, infos, incompatibilities=[])
|
||||||
candidates = list(candidates)
|
if not cands:
|
||||||
criterion = cls(
|
|
||||||
candidates=candidates,
|
|
||||||
information=[RequirementInformation(requirement, parent)],
|
|
||||||
incompatibilities=[],
|
|
||||||
)
|
|
||||||
if not candidates:
|
|
||||||
raise RequirementsConflicted(criterion)
|
raise RequirementsConflicted(criterion)
|
||||||
return criterion
|
return criterion
|
||||||
|
|
||||||
|
@ -97,15 +90,12 @@ class Criterion(object):
|
||||||
return (i.parent for i in self.information)
|
return (i.parent for i in self.information)
|
||||||
|
|
||||||
def merged_with(self, provider, requirement, parent):
|
def merged_with(self, provider, requirement, parent):
|
||||||
"""Build a new instance from this and a new requirement.
|
"""Build a new instance from this and a new requirement."""
|
||||||
"""
|
|
||||||
infos = list(self.information)
|
infos = list(self.information)
|
||||||
infos.append(RequirementInformation(requirement, parent))
|
infos.append(RequirementInformation(requirement, parent))
|
||||||
candidates = provider.find_matches([r for r, _ in infos])
|
cands = build_iter_view(provider.find_matches([r for r, _ in infos]))
|
||||||
if not isinstance(candidates, collections_abc.Sequence):
|
criterion = type(self)(cands, infos, list(self.incompatibilities))
|
||||||
candidates = list(candidates)
|
if not cands:
|
||||||
criterion = type(self)(candidates, infos, list(self.incompatibilities))
|
|
||||||
if not candidates:
|
|
||||||
raise RequirementsConflicted(criterion)
|
raise RequirementsConflicted(criterion)
|
||||||
return criterion
|
return criterion
|
||||||
|
|
||||||
|
@ -114,13 +104,12 @@ class Criterion(object):
|
||||||
|
|
||||||
Returns the new instance, or None if we still have no valid candidates.
|
Returns the new instance, or None if we still have no valid candidates.
|
||||||
"""
|
"""
|
||||||
|
cands = self.candidates.excluding(candidate)
|
||||||
|
if not cands:
|
||||||
|
return None
|
||||||
incompats = list(self.incompatibilities)
|
incompats = list(self.incompatibilities)
|
||||||
incompats.append(candidate)
|
incompats.append(candidate)
|
||||||
candidates = [c for c in self.candidates if c != candidate]
|
return type(self)(cands, list(self.information), incompats)
|
||||||
if not candidates:
|
|
||||||
return None
|
|
||||||
criterion = type(self)(candidates, list(self.information), incompats)
|
|
||||||
return criterion
|
|
||||||
|
|
||||||
|
|
||||||
class ResolutionError(ResolverException):
|
class ResolutionError(ResolverException):
|
||||||
|
@ -175,7 +164,8 @@ class Resolution(object):
|
||||||
state = State(mapping=collections.OrderedDict(), criteria={})
|
state = State(mapping=collections.OrderedDict(), criteria={})
|
||||||
else:
|
else:
|
||||||
state = State(
|
state = State(
|
||||||
mapping=base.mapping.copy(), criteria=base.criteria.copy(),
|
mapping=base.mapping.copy(),
|
||||||
|
criteria=base.criteria.copy(),
|
||||||
)
|
)
|
||||||
self._states.append(state)
|
self._states.append(state)
|
||||||
|
|
||||||
|
@ -192,12 +182,10 @@ class Resolution(object):
|
||||||
|
|
||||||
def _get_criterion_item_preference(self, item):
|
def _get_criterion_item_preference(self, item):
|
||||||
name, criterion = item
|
name, criterion = item
|
||||||
try:
|
|
||||||
pinned = self.state.mapping[name]
|
|
||||||
except KeyError:
|
|
||||||
pinned = None
|
|
||||||
return self._p.get_preference(
|
return self._p.get_preference(
|
||||||
pinned, criterion.candidates, criterion.information,
|
self.state.mapping.get(name),
|
||||||
|
criterion.candidates.for_preference(),
|
||||||
|
criterion.information,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _is_current_pin_satisfying(self, name, criterion):
|
def _is_current_pin_satisfying(self, name, criterion):
|
||||||
|
@ -390,8 +378,7 @@ def _build_result(state):
|
||||||
|
|
||||||
|
|
||||||
class Resolver(AbstractResolver):
|
class Resolver(AbstractResolver):
|
||||||
"""The thing that performs the actual resolution work.
|
"""The thing that performs the actual resolution work."""
|
||||||
"""
|
|
||||||
|
|
||||||
base_exception = ResolverException
|
base_exception = ResolverException
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
from .compat import collections_abc
|
||||||
|
|
||||||
|
|
||||||
class DirectedGraph(object):
|
class DirectedGraph(object):
|
||||||
"""A graph structure with directed edges.
|
"""A graph structure with directed edges."""
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._vertices = set()
|
self._vertices = set()
|
||||||
|
@ -17,8 +19,7 @@ class DirectedGraph(object):
|
||||||
return key in self._vertices
|
return key in self._vertices
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
"""Return a shallow copy of this graph.
|
"""Return a shallow copy of this graph."""
|
||||||
"""
|
|
||||||
other = DirectedGraph()
|
other = DirectedGraph()
|
||||||
other._vertices = set(self._vertices)
|
other._vertices = set(self._vertices)
|
||||||
other._forwards = {k: set(v) for k, v in self._forwards.items()}
|
other._forwards = {k: set(v) for k, v in self._forwards.items()}
|
||||||
|
@ -26,8 +27,7 @@ class DirectedGraph(object):
|
||||||
return other
|
return other
|
||||||
|
|
||||||
def add(self, key):
|
def add(self, key):
|
||||||
"""Add a new vertex to the graph.
|
"""Add a new vertex to the graph."""
|
||||||
"""
|
|
||||||
if key in self._vertices:
|
if key in self._vertices:
|
||||||
raise ValueError("vertex exists")
|
raise ValueError("vertex exists")
|
||||||
self._vertices.add(key)
|
self._vertices.add(key)
|
||||||
|
@ -35,8 +35,7 @@ class DirectedGraph(object):
|
||||||
self._backwards[key] = set()
|
self._backwards[key] = set()
|
||||||
|
|
||||||
def remove(self, key):
|
def remove(self, key):
|
||||||
"""Remove a vertex from the graph, disconnecting all edges from/to it.
|
"""Remove a vertex from the graph, disconnecting all edges from/to it."""
|
||||||
"""
|
|
||||||
self._vertices.remove(key)
|
self._vertices.remove(key)
|
||||||
for f in self._forwards.pop(key):
|
for f in self._forwards.pop(key):
|
||||||
self._backwards[f].remove(key)
|
self._backwards[f].remove(key)
|
||||||
|
@ -66,3 +65,79 @@ class DirectedGraph(object):
|
||||||
|
|
||||||
def iter_parents(self, key):
|
def iter_parents(self, key):
|
||||||
return iter(self._backwards[key])
|
return iter(self._backwards[key])
|
||||||
|
|
||||||
|
|
||||||
|
class _FactoryIterableView(object):
|
||||||
|
"""Wrap an iterator factory returned by `find_matches()`.
|
||||||
|
|
||||||
|
Calling `iter()` on this class would invoke the underlying iterator
|
||||||
|
factory, making it a "collection with ordering" that can be iterated
|
||||||
|
through multiple times, but lacks random access methods presented in
|
||||||
|
built-in Python sequence types.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, factory):
|
||||||
|
self._factory = factory
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
try:
|
||||||
|
next(self._factory())
|
||||||
|
except StopIteration:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
__nonzero__ = __bool__ # XXX: Python 2.
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self._factory()
|
||||||
|
|
||||||
|
def for_preference(self):
|
||||||
|
"""Provide an candidate iterable for `get_preference()`"""
|
||||||
|
return self._factory()
|
||||||
|
|
||||||
|
def excluding(self, candidate):
|
||||||
|
"""Create a new `Candidates` instance excluding `candidate`."""
|
||||||
|
|
||||||
|
def factory():
|
||||||
|
return (c for c in self._factory() if c != candidate)
|
||||||
|
|
||||||
|
return type(self)(factory)
|
||||||
|
|
||||||
|
|
||||||
|
class _SequenceIterableView(object):
|
||||||
|
"""Wrap an iterable returned by find_matches().
|
||||||
|
|
||||||
|
This is essentially just a proxy to the underlying sequence that provides
|
||||||
|
the same interface as `_FactoryIterableView`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, sequence):
|
||||||
|
self._sequence = sequence
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
return bool(self._sequence)
|
||||||
|
|
||||||
|
__nonzero__ = __bool__ # XXX: Python 2.
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter(self._sequence)
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._sequence)
|
||||||
|
|
||||||
|
def for_preference(self):
|
||||||
|
"""Provide an candidate iterable for `get_preference()`"""
|
||||||
|
return self._sequence
|
||||||
|
|
||||||
|
def excluding(self, candidate):
|
||||||
|
"""Create a new instance excluding `candidate`."""
|
||||||
|
return type(self)([c for c in self._sequence if c != candidate])
|
||||||
|
|
||||||
|
|
||||||
|
def build_iter_view(matches):
|
||||||
|
"""Build an iterable view from the value returned by `find_matches()`."""
|
||||||
|
if callable(matches):
|
||||||
|
return _FactoryIterableView(matches)
|
||||||
|
if not isinstance(matches, collections_abc.Sequence):
|
||||||
|
matches = list(matches)
|
||||||
|
return _SequenceIterableView(matches)
|
||||||
|
|
|
@ -16,7 +16,7 @@ requests==2.25.0
|
||||||
chardet==3.0.4
|
chardet==3.0.4
|
||||||
idna==2.10
|
idna==2.10
|
||||||
urllib3==1.26.2
|
urllib3==1.26.2
|
||||||
resolvelib==0.4.0
|
resolvelib==0.5.2
|
||||||
retrying==1.3.3
|
retrying==1.3.3
|
||||||
setuptools==44.0.0
|
setuptools==44.0.0
|
||||||
six==1.15.0
|
six==1.15.0
|
||||||
|
|
Loading…
Reference in a new issue