123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- class AbstractProvider(object):
- """Delegate class to provide requirement interface for the resolver."""
- def identify(self, requirement_or_candidate):
- """Given a requirement, return an identifier for it.
- This is used to identify a requirement, e.g. whether two requirements
- should have their specifier parts merged.
- """
- raise NotImplementedError
- def get_preference(self, identifier, resolutions, candidates, information):
- """Produce a sort key for given requirement based on preference.
- The preference is defined as "I think this requirement should be
- resolved first". The lower the return value is, the more preferred
- this group of arguments is.
- :param identifier: An identifier as returned by ``identify()``. This
- identifies the dependency matches of which should be returned.
- :param resolutions: Mapping of candidates currently pinned by the
- resolver. Each key is an identifier, and the value 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.
- :param information: Mapping of requirement information of each package.
- Each value is an iterator of *requirement information*.
- A *requirement information* instance is a named tuple with two members:
- * ``requirement`` specifies a requirement contributing to the current
- list of candidates.
- * ``parent`` specifies the candidate that provides (dependend on) the
- requirement, or ``None`` to indicate a root requirement.
- The preference could depend on a various of issues, including (not
- necessarily in this order):
- * Is this package pinned in the current resolution result?
- * How relaxed is the requirement? Stricter ones should probably be
- worked on first? (I don't know, actually.)
- * How many possibilities are there to satisfy this requirement? Those
- with few left should likely be worked on first, I guess?
- * Are there any known conflicts for this requirement? We should
- probably work on those with the most known conflicts.
- 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,
- the more preferred this requirement is (i.e. the sorting function
- is called with ``reverse=False``).
- """
- raise NotImplementedError
- def find_matches(self, identifier, requirements, incompatibilities):
- """Find all possible candidates that satisfy given constraints.
- :param identifier: An identifier as returned by ``identify()``. This
- identifies the dependency matches of which should be returned.
- :param requirements: A mapping of requirements that all returned
- candidates must satisfy. Each key is an identifier, and the value
- an iterator of requirements for that dependency.
- :param incompatibilities: A mapping of known incompatibilities of
- each dependency. Each key is an identifier, and the value an
- iterator of incompatibilities known to the resolver. All
- incompatibilities *must* be excluded from the return value.
- This should try to get candidates based on the requirements' types.
- For VCS, local, and archive requirements, the one-and-only match is
- returned, and for a "named" requirement, the index(es) should be
- consulted to find concrete candidates for this requirement.
- 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.
- """
- raise NotImplementedError
- 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
- requirement.
- A boolean should be returned to indicate whether ``candidate`` is a
- viable solution to the requirement.
- """
- raise NotImplementedError
- def get_dependencies(self, candidate):
- """Get dependencies of a candidate.
- This should return a collection of requirements that `candidate`
- specifies as its dependencies.
- """
- raise NotImplementedError
- class AbstractResolver(object):
- """The thing that performs the actual resolution work."""
- base_exception = Exception
- def __init__(self, provider, reporter):
- self.provider = provider
- self.reporter = reporter
- def resolve(self, requirements, **kwargs):
- """Take a collection of constraints, spit out the resolution result.
- This returns a representation of the final resolution state, with one
- guarenteed attribute ``mapping`` that contains resolved candidates as
- values. The keys are their respective identifiers.
- :param requirements: A collection of constraints.
- :param kwargs: Additional keyword arguments that subclasses may accept.
- :raises: ``self.base_exception`` or its subclass.
- """
- raise NotImplementedError
|