1
1
Fork 0
mirror of https://github.com/pypa/pip synced 2023-12-13 21:30:23 +01:00

Refactor root requirement collection into factory

This commit is contained in:
Tzu-ping Chung 2021-06-20 18:29:15 +08:00
parent f9c49eff8d
commit 5d81040ee8
2 changed files with 51 additions and 42 deletions

View file

@ -9,6 +9,7 @@ from typing import (
Iterator,
List,
Mapping,
NamedTuple,
Optional,
Sequence,
Set,
@ -38,7 +39,10 @@ from pip._internal.models.link import Link
from pip._internal.models.wheel import Wheel
from pip._internal.operations.prepare import RequirementPreparer
from pip._internal.req.constructors import install_req_from_link_and_ireq
from pip._internal.req.req_install import InstallRequirement
from pip._internal.req.req_install import (
InstallRequirement,
check_invalid_constraint_type,
)
from pip._internal.resolution.base import InstallRequirementProvider
from pip._internal.utils.compatibility_tags import get_supported
from pip._internal.utils.hashes import Hashes
@ -81,6 +85,12 @@ C = TypeVar("C")
Cache = Dict[Link, C]
class CollectedRootRequirements(NamedTuple):
requirements: List[Requirement]
constraints: Dict[str, Constraint]
user_requested: Dict[str, int]
class Factory:
def __init__(
self,
@ -408,7 +418,7 @@ class Factory:
and all(req.is_satisfied_by(c) for req in requirements[identifier])
)
def make_requirement_from_install_req(
def _make_requirement_from_install_req(
self, ireq: InstallRequirement, requested_extras: Iterable[str]
) -> Optional[Requirement]:
if not ireq.match_markers(requested_extras):
@ -440,6 +450,37 @@ class Factory:
return UnsatisfiableRequirement(canonicalize_name(ireq.name))
return self.make_requirement_from_candidate(cand)
def collect_root_requirements(
self, root_ireqs: List[InstallRequirement]
) -> CollectedRootRequirements:
collected = CollectedRootRequirements([], {}, {})
for i, ireq in enumerate(root_ireqs):
if ireq.constraint:
# Ensure we only accept valid constraints
problem = check_invalid_constraint_type(ireq)
if problem:
raise InstallationError(problem)
if not ireq.match_markers():
continue
assert ireq.name, "Constraint must be named"
name = canonicalize_name(ireq.name)
if name in collected.constraints:
collected.constraints[name] &= ireq
else:
collected.constraints[name] = Constraint.from_ireq(ireq)
else:
if ireq.user_supplied and ireq.name:
canonical_name = canonicalize_name(ireq.name)
if canonical_name not in collected.user_requested:
collected.user_requested[canonical_name] = i
req = self._make_requirement_from_install_req(
ireq,
requested_extras=(),
)
if req is not None:
collected.requirements.append(req)
return collected
def make_requirement_from_candidate(
self, candidate: Candidate
) -> ExplicitRequirement:
@ -452,7 +493,7 @@ class Factory:
requested_extras: Iterable[str] = (),
) -> Optional[Requirement]:
ireq = self._make_install_req_from_spec(specifier, comes_from)
return self.make_requirement_from_install_req(ireq, requested_extras)
return self._make_requirement_from_install_req(ireq, requested_extras)
def make_requires_python_requirement(
self, specifier: Optional[SpecifierSet]

View file

@ -10,13 +10,9 @@ from pip._vendor.resolvelib import Resolver as RLResolver
from pip._vendor.resolvelib.structs import DirectedGraph
from pip._internal.cache import WheelCache
from pip._internal.exceptions import InstallationError
from pip._internal.index.package_finder import PackageFinder
from pip._internal.operations.prepare import RequirementPreparer
from pip._internal.req.req_install import (
InstallRequirement,
check_invalid_constraint_type,
)
from pip._internal.req.req_install import InstallRequirement
from pip._internal.req.req_set import RequirementSet
from pip._internal.resolution.base import BaseResolver, InstallRequirementProvider
from pip._internal.resolution.resolvelib.provider import PipProvider
@ -28,7 +24,7 @@ from pip._internal.utils.deprecation import deprecated
from pip._internal.utils.filetypes import is_archive_file
from pip._internal.utils.misc import dist_is_editable
from .base import Candidate, Constraint, Requirement
from .base import Candidate, Requirement
from .factory import Factory
if TYPE_CHECKING:
@ -78,41 +74,13 @@ class Resolver(BaseResolver):
def resolve(
self, root_reqs: List[InstallRequirement], check_supported_wheels: bool
) -> RequirementSet:
constraints: Dict[str, Constraint] = {}
user_requested: Dict[str, int] = {}
requirements = []
for i, req in enumerate(root_reqs):
if req.constraint:
# Ensure we only accept valid constraints
problem = check_invalid_constraint_type(req)
if problem:
raise InstallationError(problem)
if not req.match_markers():
continue
assert req.name, "Constraint must be named"
name = canonicalize_name(req.name)
if name in constraints:
constraints[name] &= req
else:
constraints[name] = Constraint.from_ireq(req)
else:
if req.user_supplied and req.name:
canonical_name = canonicalize_name(req.name)
if canonical_name not in user_requested:
user_requested[canonical_name] = i
r = self.factory.make_requirement_from_install_req(
req, requested_extras=()
)
if r is not None:
requirements.append(r)
collected = self.factory.collect_root_requirements(root_reqs)
provider = PipProvider(
factory=self.factory,
constraints=constraints,
constraints=collected.constraints,
ignore_dependencies=self.ignore_dependencies,
upgrade_strategy=self.upgrade_strategy,
user_requested=user_requested,
user_requested=collected.user_requested,
)
if "PIP_RESOLVER_DEBUG" in os.environ:
reporter: BaseReporter = PipDebuggingReporter()
@ -126,13 +94,13 @@ class Resolver(BaseResolver):
try:
try_to_avoid_resolution_too_deep = 2000000
result = self._result = resolver.resolve(
requirements, max_rounds=try_to_avoid_resolution_too_deep
collected.requirements, max_rounds=try_to_avoid_resolution_too_deep
)
except ResolutionImpossible as e:
error = self.factory.get_installation_error(
cast("ResolutionImpossible[Requirement, Candidate]", e),
constraints,
collected.constraints,
)
raise error from e