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 prevents us from having to hold multiple references of
finder/preparer/make_install_req in each requirement/candidate class.
Instead we just pass around the factory object, and let others use the
instances on it.
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.