This specialized class is able to carry more context information than
the previous implementation (which reuses ExplicitRequirement). Error
reports can thus provide better messages by introspecting.
The candidate creation logic is further moved into the factory. The
factory would use pkg_resources.get_distribution() to find a matching
distribution for a givan InstallationCandidate. If found, the Candidate
would be created based on that found distribution, instead of the link.
--ignore-installed is implemented as to always use the link to create
candidates, even if an installed distribution is found.
If a dist contains Requires-Python metadata, it is converted into a
Requirement for the resolver based on whether the Requires-Python
is compatible or not.
If it is compatible, an ExplicitRequirement is returned to hold the
Python information (either sys.version_info, or the user-supplied
--python-version).
If it is incompatible, a special NoMatchRequirement is returned, which
never matches to anything, generating a ResolutionImpossible to report
the Python version incompatibility.
The --ignore-requires-python flag is implemented as to not return a
Requirement for Requires-Python at all.
This introduces a new module "factory" that contains all methods dealing
with producing candidates/requirements from an input
requirement/candidate. This allows both models to know nothing about
each other, and simply rely on the intermediate to produce the other.
I *believe* this also helps us reduce merge conflicts due to adding
arguments to those producer functions, since now we only need to modify
the factory, and exactly one of candidate/requirement.
This is only part of a big scheme--the plan is to also move
Candidate.get_dependencies() and Requirement.find_matches() into the
factory class, so they can avoid holding and passing around finder,
preparer, and make_install_req. This is also necessary to change the
return type of Candidate.get_dependencies() to Requirement without
hard-coupling.
ResolveLib *should* always produce a graph with only one root vertice,
which is None. But we don't really need to rely on that implementation
detail. Vertices without any parents can be assigned 0 in all cases.
This introduces a new general option --unstable-feature that can be used
to opt into "preview" features in pip not enabled by default. Currently
the only available feature is "resolver".
A stub resolver interface (which would fail on invocation) is provided
to respond to the flag.
The --unstable-feature option is hidden from --help since the resolver
does not yet work. This suppression should be removed when we release
the resolver for general/public testing.