2020-03-09 10:06:32 +01:00
|
|
|
from pip._vendor.packaging.utils import canonicalize_name
|
|
|
|
|
|
|
|
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
|
|
|
|
2020-03-25 13:25:23 +01:00
|
|
|
from .base import Requirement, format_name
|
2020-03-09 10:06:32 +01:00
|
|
|
|
|
|
|
if MYPY_CHECK_RUNNING:
|
2020-03-12 16:18:47 +01:00
|
|
|
from typing import Sequence
|
2020-03-09 10:06:32 +01:00
|
|
|
|
2020-03-12 16:18:47 +01:00
|
|
|
from pip._internal.req.req_install import InstallRequirement
|
|
|
|
|
|
|
|
from .base import Candidate
|
2020-03-26 20:14:51 +01:00
|
|
|
from .factory import Factory
|
2020-03-09 10:06:32 +01:00
|
|
|
|
|
|
|
|
2020-03-12 16:18:47 +01:00
|
|
|
class ExplicitRequirement(Requirement):
|
|
|
|
def __init__(self, candidate):
|
|
|
|
# type: (Candidate) -> None
|
|
|
|
self.candidate = candidate
|
2020-03-09 10:06:32 +01:00
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
# type: () -> str
|
2020-03-19 11:53:15 +01:00
|
|
|
# No need to canonicalise - the candidate did this
|
2020-03-12 16:18:47 +01:00
|
|
|
return self.candidate.name
|
|
|
|
|
|
|
|
def find_matches(self):
|
|
|
|
# type: () -> Sequence[Candidate]
|
|
|
|
return [self.candidate]
|
2020-03-09 10:06:32 +01:00
|
|
|
|
|
|
|
def is_satisfied_by(self, candidate):
|
|
|
|
# type: (Candidate) -> bool
|
2020-03-12 16:18:47 +01:00
|
|
|
return candidate == self.candidate
|
2020-03-09 10:06:32 +01:00
|
|
|
|
|
|
|
|
2020-04-01 12:14:36 +02:00
|
|
|
class NoMatchRequirement(Requirement):
|
|
|
|
"""A requirement that never matches anything.
|
2020-04-02 15:42:26 +02:00
|
|
|
|
|
|
|
Note: Similar to ExplicitRequirement, the caller should handle name
|
|
|
|
canonicalisation; this class does not perform it.
|
2020-04-01 12:14:36 +02:00
|
|
|
"""
|
|
|
|
def __init__(self, name):
|
|
|
|
# type: (str) -> None
|
2020-04-02 15:42:26 +02:00
|
|
|
self._name = name
|
2020-04-01 12:14:36 +02:00
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
# type: () -> str
|
|
|
|
return self._name
|
|
|
|
|
|
|
|
def find_matches(self):
|
|
|
|
# type: () -> Sequence[Candidate]
|
|
|
|
return []
|
|
|
|
|
|
|
|
def is_satisfied_by(self, candidate):
|
|
|
|
# type: (Candidate) -> bool
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
2020-03-12 16:18:47 +01:00
|
|
|
class SpecifierRequirement(Requirement):
|
2020-03-27 15:40:05 +01:00
|
|
|
def __init__(self, ireq, factory):
|
|
|
|
# type: (InstallRequirement, Factory) -> None
|
2020-03-12 16:18:47 +01:00
|
|
|
assert ireq.link is None, "This is a link, not a specifier"
|
2020-03-09 10:06:32 +01:00
|
|
|
self._ireq = ireq
|
2020-03-26 20:14:51 +01:00
|
|
|
self._factory = factory
|
2020-03-25 13:25:23 +01:00
|
|
|
self.extras = ireq.req.extras
|
2020-03-09 10:06:32 +01:00
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
# type: () -> str
|
|
|
|
canonical_name = canonicalize_name(self._ireq.req.name)
|
2020-03-25 13:25:23 +01:00
|
|
|
return format_name(canonical_name, self.extras)
|
2020-03-09 10:06:32 +01:00
|
|
|
|
2020-03-12 16:18:47 +01:00
|
|
|
def find_matches(self):
|
|
|
|
# type: () -> Sequence[Candidate]
|
2020-03-27 15:40:05 +01:00
|
|
|
found = self._factory.finder.find_best_candidate(
|
2020-03-09 10:06:32 +01:00
|
|
|
project_name=self._ireq.req.name,
|
|
|
|
specifier=self._ireq.req.specifier,
|
|
|
|
hashes=self._ireq.hashes(trust_internet=False),
|
|
|
|
)
|
|
|
|
return [
|
2020-04-02 13:49:45 +02:00
|
|
|
self._factory.make_candidate_from_ican(
|
|
|
|
ican=ican,
|
2020-03-26 20:14:51 +01:00
|
|
|
extras=self.extras,
|
|
|
|
parent=self._ireq,
|
2020-03-12 16:18:47 +01:00
|
|
|
)
|
2020-03-09 10:06:32 +01:00
|
|
|
for ican in found.iter_applicable()
|
|
|
|
]
|
|
|
|
|
|
|
|
def is_satisfied_by(self, candidate):
|
|
|
|
# type: (Candidate) -> bool
|
2020-03-12 16:18:47 +01:00
|
|
|
assert candidate.name == self.name, \
|
2020-03-18 15:54:15 +01:00
|
|
|
"Internal issue: Candidate is not for this requirement " \
|
|
|
|
" {} vs {}".format(candidate.name, self.name)
|
2020-03-09 10:06:32 +01:00
|
|
|
return candidate.version in self._ireq.req.specifier
|