mirror of https://github.com/pypa/pip
Decouple candidate and requirement modules
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.
This commit is contained in:
parent
c3d86200b0
commit
07563847b0
|
@ -9,7 +9,7 @@ from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
|||
from .base import Candidate, format_name
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from typing import Any, Dict, Optional, Sequence, Set
|
||||
from typing import Any, Optional, Sequence, Set
|
||||
|
||||
from pip._internal.models.link import Link
|
||||
from pip._internal.operations.prepare import RequirementPreparer
|
||||
|
@ -18,33 +18,10 @@ if MYPY_CHECK_RUNNING:
|
|||
from pip._vendor.packaging.version import _BaseVersion
|
||||
from pip._vendor.pkg_resources import Distribution
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
_CANDIDATE_CACHE = {} # type: Dict[Link, LinkCandidate]
|
||||
|
||||
|
||||
def make_candidate(
|
||||
link, # type: Link
|
||||
preparer, # type: RequirementPreparer
|
||||
parent, # type: InstallRequirement
|
||||
make_install_req, # type: InstallRequirementProvider
|
||||
extras # type: Set[str]
|
||||
):
|
||||
# type: (...) -> Candidate
|
||||
if link not in _CANDIDATE_CACHE:
|
||||
_CANDIDATE_CACHE[link] = LinkCandidate(
|
||||
link,
|
||||
preparer,
|
||||
parent=parent,
|
||||
make_install_req=make_install_req
|
||||
)
|
||||
base = _CANDIDATE_CACHE[link]
|
||||
if extras:
|
||||
return ExtrasCandidate(base, extras)
|
||||
return base
|
||||
|
||||
|
||||
def make_install_req_from_link(link, parent):
|
||||
# type: (Link, InstallRequirement) -> InstallRequirement
|
||||
# TODO: Do we need to support editables?
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
from .candidates import ExtrasCandidate, LinkCandidate
|
||||
from .requirements import ExplicitRequirement, SpecifierRequirement
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from typing import Dict, Set
|
||||
|
||||
from pip._internal.index.package_finder import PackageFinder
|
||||
from pip._internal.models.link import Link
|
||||
from pip._internal.operations.prepare import RequirementPreparer
|
||||
from pip._internal.req.req_install import InstallRequirement
|
||||
from pip._internal.resolution.base import InstallRequirementProvider
|
||||
|
||||
from .base import Candidate, Requirement
|
||||
|
||||
|
||||
class Factory(object):
|
||||
def __init__(
|
||||
self,
|
||||
finder, # type: PackageFinder
|
||||
preparer, # type: RequirementPreparer
|
||||
make_install_req, # type: InstallRequirementProvider
|
||||
):
|
||||
# type: (...) -> None
|
||||
self._finder = finder
|
||||
self._preparer = preparer
|
||||
self._make_install_req = make_install_req
|
||||
self._candidate_cache = {} # type: Dict[Link, LinkCandidate]
|
||||
|
||||
def make_candidate(
|
||||
self,
|
||||
link, # type: Link
|
||||
extras, # type: Set[str]
|
||||
parent, # type: InstallRequirement
|
||||
):
|
||||
# type: (...) -> Candidate
|
||||
if link not in self._candidate_cache:
|
||||
self._candidate_cache[link] = LinkCandidate(
|
||||
link,
|
||||
self._preparer,
|
||||
parent=parent,
|
||||
make_install_req=self._make_install_req
|
||||
)
|
||||
base = self._candidate_cache[link]
|
||||
if extras:
|
||||
return ExtrasCandidate(base, extras)
|
||||
return base
|
||||
|
||||
def make_requirement(self, ireq):
|
||||
# type: (InstallRequirement) -> Requirement
|
||||
if ireq.link:
|
||||
cand = self.make_candidate(ireq.link, extras=set(), parent=ireq)
|
||||
return ExplicitRequirement(cand)
|
||||
else:
|
||||
return SpecifierRequirement(
|
||||
ireq,
|
||||
finder=self._finder,
|
||||
preparer=self._preparer,
|
||||
factory=self,
|
||||
make_install_req=self._make_install_req,
|
||||
)
|
|
@ -2,41 +2,24 @@ from pip._vendor.resolvelib.providers import AbstractProvider
|
|||
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
from .requirements import make_requirement
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from typing import Any, Optional, Sequence, Tuple, Union
|
||||
|
||||
from pip._internal.index.package_finder import PackageFinder
|
||||
from pip._internal.operations.prepare import RequirementPreparer
|
||||
from pip._internal.req.req_install import InstallRequirement
|
||||
from pip._internal.resolution.base import InstallRequirementProvider
|
||||
|
||||
from .base import Requirement, Candidate
|
||||
from .factory import Factory
|
||||
|
||||
|
||||
class PipProvider(AbstractProvider):
|
||||
def __init__(
|
||||
self,
|
||||
finder, # type: PackageFinder
|
||||
preparer, # type: RequirementPreparer
|
||||
factory, # type: Factory
|
||||
ignore_dependencies, # type: bool
|
||||
make_install_req # type: InstallRequirementProvider
|
||||
):
|
||||
# type: (...) -> None
|
||||
self._finder = finder
|
||||
self._preparer = preparer
|
||||
self._factory = factory
|
||||
self._ignore_dependencies = ignore_dependencies
|
||||
self._make_install_req = make_install_req
|
||||
|
||||
def make_requirement(self, ireq):
|
||||
# type: (InstallRequirement) -> Requirement
|
||||
return make_requirement(
|
||||
ireq,
|
||||
self._finder,
|
||||
self._preparer,
|
||||
self._make_install_req
|
||||
)
|
||||
|
||||
def get_install_requirement(self, c):
|
||||
# type: (Candidate) -> Optional[InstallRequirement]
|
||||
|
@ -69,11 +52,6 @@ class PipProvider(AbstractProvider):
|
|||
if self._ignore_dependencies:
|
||||
return []
|
||||
return [
|
||||
make_requirement(
|
||||
r,
|
||||
self._finder,
|
||||
self._preparer,
|
||||
self._make_install_req
|
||||
)
|
||||
self._factory.make_requirement(r)
|
||||
for r in candidate.get_dependencies()
|
||||
]
|
||||
|
|
|
@ -3,7 +3,6 @@ from pip._vendor.packaging.utils import canonicalize_name
|
|||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
from .base import Requirement, format_name
|
||||
from .candidates import make_candidate
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from typing import Sequence
|
||||
|
@ -14,31 +13,7 @@ if MYPY_CHECK_RUNNING:
|
|||
from pip._internal.resolution.base import InstallRequirementProvider
|
||||
|
||||
from .base import Candidate
|
||||
|
||||
|
||||
def make_requirement(
|
||||
ireq, # type: InstallRequirement
|
||||
finder, # type: PackageFinder
|
||||
preparer, # type: RequirementPreparer
|
||||
make_install_req # type: InstallRequirementProvider
|
||||
):
|
||||
# type: (...) -> Requirement
|
||||
if ireq.link:
|
||||
candidate = make_candidate(
|
||||
ireq.link,
|
||||
preparer,
|
||||
ireq,
|
||||
make_install_req,
|
||||
set()
|
||||
)
|
||||
return ExplicitRequirement(candidate)
|
||||
else:
|
||||
return SpecifierRequirement(
|
||||
ireq,
|
||||
finder,
|
||||
preparer,
|
||||
make_install_req
|
||||
)
|
||||
from .factory import Factory
|
||||
|
||||
|
||||
class ExplicitRequirement(Requirement):
|
||||
|
@ -66,12 +41,14 @@ class SpecifierRequirement(Requirement):
|
|||
self,
|
||||
ireq, # type: InstallRequirement
|
||||
finder, # type: PackageFinder
|
||||
preparer, # type:RequirementPreparer
|
||||
preparer, # type: RequirementPreparer
|
||||
factory, # type: Factory
|
||||
make_install_req # type: InstallRequirementProvider
|
||||
):
|
||||
# type: (...) -> None
|
||||
assert ireq.link is None, "This is a link, not a specifier"
|
||||
self._ireq = ireq
|
||||
self._factory = factory
|
||||
self._finder = finder
|
||||
self._preparer = preparer
|
||||
self._make_install_req = make_install_req
|
||||
|
@ -91,12 +68,10 @@ class SpecifierRequirement(Requirement):
|
|||
hashes=self._ireq.hashes(trust_internet=False),
|
||||
)
|
||||
return [
|
||||
make_candidate(
|
||||
ican.link,
|
||||
self._preparer,
|
||||
self._ireq,
|
||||
self._make_install_req,
|
||||
self.extras
|
||||
self._factory.make_candidate(
|
||||
link=ican.link,
|
||||
extras=self.extras,
|
||||
parent=self._ireq,
|
||||
)
|
||||
for ican in found.iter_applicable()
|
||||
]
|
||||
|
|
|
@ -9,6 +9,8 @@ from pip._internal.resolution.base import BaseResolver
|
|||
from pip._internal.resolution.resolvelib.provider import PipProvider
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
from .factory import Factory
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
|
@ -35,24 +37,24 @@ class Resolver(BaseResolver):
|
|||
py_version_info=None, # type: Optional[Tuple[int, ...]]
|
||||
):
|
||||
super(Resolver, self).__init__()
|
||||
self.finder = finder
|
||||
self.preparer = preparer
|
||||
self.factory = Factory(
|
||||
finder=finder,
|
||||
preparer=preparer,
|
||||
make_install_req=make_install_req,
|
||||
)
|
||||
self.ignore_dependencies = ignore_dependencies
|
||||
self.make_install_req = make_install_req
|
||||
self._result = None # type: Optional[Result]
|
||||
|
||||
def resolve(self, root_reqs, check_supported_wheels):
|
||||
# type: (List[InstallRequirement], bool) -> RequirementSet
|
||||
provider = PipProvider(
|
||||
finder=self.finder,
|
||||
preparer=self.preparer,
|
||||
factory=self.factory,
|
||||
ignore_dependencies=self.ignore_dependencies,
|
||||
make_install_req=self.make_install_req,
|
||||
)
|
||||
reporter = BaseReporter()
|
||||
resolver = RLResolver(provider, reporter)
|
||||
|
||||
requirements = [provider.make_requirement(r) for r in root_reqs]
|
||||
requirements = [self.factory.make_requirement(r) for r in root_reqs]
|
||||
self._result = resolver.resolve(requirements)
|
||||
|
||||
req_set = RequirementSet(check_supported_wheels=check_supported_wheels)
|
||||
|
|
Loading…
Reference in New Issue