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:
parent
f9c49eff8d
commit
5d81040ee8
2 changed files with 51 additions and 42 deletions
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue