mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
Move _link_package_versions() to CandidateEvaluator.
This commit is contained in:
parent
58ee598b03
commit
651d6fe705
|
@ -258,20 +258,111 @@ def _get_html_page(link, session=None):
|
||||||
|
|
||||||
class CandidateEvaluator(object):
|
class CandidateEvaluator(object):
|
||||||
|
|
||||||
|
_py_version_re = re.compile(r'-py([123]\.?[0-9]?)$')
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
valid_tags, # type: List[Pep425Tag]
|
valid_tags, # type: List[Pep425Tag]
|
||||||
prefer_binary=False # type: bool
|
prefer_binary=False # type: bool
|
||||||
|
|
||||||
):
|
):
|
||||||
# type: (...) -> None
|
# type: (...) -> None
|
||||||
self._prefer_binary = prefer_binary
|
self._prefer_binary = prefer_binary
|
||||||
self._valid_tags = valid_tags
|
self._valid_tags = valid_tags
|
||||||
|
|
||||||
|
# These are boring links that have already been logged somehow.
|
||||||
|
self._logged_links = set() # type: Set[Link]
|
||||||
|
|
||||||
|
def _log_skipped_link(self, link, reason):
|
||||||
|
# type: (Link, str) -> None
|
||||||
|
if link not in self._logged_links:
|
||||||
|
logger.debug('Skipping link %s; %s', link, reason)
|
||||||
|
self._logged_links.add(link)
|
||||||
|
|
||||||
def is_wheel_supported(self, wheel):
|
def is_wheel_supported(self, wheel):
|
||||||
# type: (Wheel) -> bool
|
# type: (Wheel) -> bool
|
||||||
return wheel.supported(self._valid_tags)
|
return wheel.supported(self._valid_tags)
|
||||||
|
|
||||||
|
def _link_package_versions(self, link, search):
|
||||||
|
# type: (Link, Search) -> Optional[InstallationCandidate]
|
||||||
|
"""Return an InstallationCandidate or None"""
|
||||||
|
version = None
|
||||||
|
if link.egg_fragment:
|
||||||
|
egg_info = link.egg_fragment
|
||||||
|
ext = link.ext
|
||||||
|
else:
|
||||||
|
egg_info, ext = link.splitext()
|
||||||
|
if not ext:
|
||||||
|
self._log_skipped_link(link, 'not a file')
|
||||||
|
return None
|
||||||
|
if ext not in SUPPORTED_EXTENSIONS:
|
||||||
|
self._log_skipped_link(
|
||||||
|
link, 'unsupported archive format: %s' % ext,
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
if "binary" not in search.formats and ext == WHEEL_EXTENSION:
|
||||||
|
self._log_skipped_link(
|
||||||
|
link, 'No binaries permitted for %s' % search.supplied,
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
if "macosx10" in link.path and ext == '.zip':
|
||||||
|
self._log_skipped_link(link, 'macosx10 one')
|
||||||
|
return None
|
||||||
|
if ext == WHEEL_EXTENSION:
|
||||||
|
try:
|
||||||
|
wheel = Wheel(link.filename)
|
||||||
|
except InvalidWheelFilename:
|
||||||
|
self._log_skipped_link(link, 'invalid wheel filename')
|
||||||
|
return None
|
||||||
|
if canonicalize_name(wheel.name) != search.canonical:
|
||||||
|
self._log_skipped_link(
|
||||||
|
link, 'wrong project name (not %s)' % search.supplied)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not self.is_wheel_supported(wheel):
|
||||||
|
self._log_skipped_link(
|
||||||
|
link, 'it is not compatible with this Python')
|
||||||
|
return None
|
||||||
|
|
||||||
|
version = wheel.version
|
||||||
|
|
||||||
|
# This should be up by the search.ok_binary check, but see issue 2700.
|
||||||
|
if "source" not in search.formats and ext != WHEEL_EXTENSION:
|
||||||
|
self._log_skipped_link(
|
||||||
|
link, 'No sources permitted for %s' % search.supplied,
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not version:
|
||||||
|
version = _egg_info_matches(egg_info, search.canonical)
|
||||||
|
if not version:
|
||||||
|
self._log_skipped_link(
|
||||||
|
link, 'Missing project version for %s' % search.supplied)
|
||||||
|
return None
|
||||||
|
|
||||||
|
match = self._py_version_re.search(version)
|
||||||
|
if match:
|
||||||
|
version = version[:match.start()]
|
||||||
|
py_version = match.group(1)
|
||||||
|
if py_version != sys.version[:3]:
|
||||||
|
self._log_skipped_link(
|
||||||
|
link, 'Python version is incorrect')
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
support_this_python = check_requires_python(link.requires_python)
|
||||||
|
except specifiers.InvalidSpecifier:
|
||||||
|
logger.debug("Package %s has an invalid Requires-Python entry: %s",
|
||||||
|
link.filename, link.requires_python)
|
||||||
|
support_this_python = True
|
||||||
|
|
||||||
|
if not support_this_python:
|
||||||
|
logger.debug("The package %s is incompatible with the python "
|
||||||
|
"version in use. Acceptable python versions are: %s",
|
||||||
|
link, link.requires_python)
|
||||||
|
return None
|
||||||
|
logger.debug('Found link %s, version: %s', link, version)
|
||||||
|
|
||||||
|
return InstallationCandidate(search.supplied, version, link)
|
||||||
|
|
||||||
def _sort_key(self, candidate):
|
def _sort_key(self, candidate):
|
||||||
# type: (InstallationCandidate) -> CandidateSortingKey
|
# type: (InstallationCandidate) -> CandidateSortingKey
|
||||||
"""
|
"""
|
||||||
|
@ -457,9 +548,6 @@ class PackageFinder(object):
|
||||||
|
|
||||||
self.index_urls = index_urls
|
self.index_urls = index_urls
|
||||||
|
|
||||||
# These are boring links that have already been logged somehow:
|
|
||||||
self.logged_links = set() # type: Set[Link]
|
|
||||||
|
|
||||||
self.format_control = format_control or FormatControl(set(), set())
|
self.format_control = format_control or FormatControl(set(), set())
|
||||||
|
|
||||||
# Domains that we won't emit warnings for when not using HTTPS
|
# Domains that we won't emit warnings for when not using HTTPS
|
||||||
|
@ -849,8 +937,6 @@ class PackageFinder(object):
|
||||||
|
|
||||||
yield page
|
yield page
|
||||||
|
|
||||||
_py_version_re = re.compile(r'-py([123]\.?[0-9]?)$')
|
|
||||||
|
|
||||||
def _sort_links(self, links):
|
def _sort_links(self, links):
|
||||||
# type: (Iterable[Link]) -> List[Link]
|
# type: (Iterable[Link]) -> List[Link]
|
||||||
"""
|
"""
|
||||||
|
@ -876,98 +962,11 @@ class PackageFinder(object):
|
||||||
# type: (...) -> List[InstallationCandidate]
|
# type: (...) -> List[InstallationCandidate]
|
||||||
result = []
|
result = []
|
||||||
for link in self._sort_links(links):
|
for link in self._sort_links(links):
|
||||||
v = self._link_package_versions(link, search)
|
v = self.candidate_evaluator._link_package_versions(link, search)
|
||||||
if v is not None:
|
if v is not None:
|
||||||
result.append(v)
|
result.append(v)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _log_skipped_link(self, link, reason):
|
|
||||||
# type: (Link, str) -> None
|
|
||||||
if link not in self.logged_links:
|
|
||||||
logger.debug('Skipping link %s; %s', link, reason)
|
|
||||||
self.logged_links.add(link)
|
|
||||||
|
|
||||||
def _link_package_versions(self, link, search):
|
|
||||||
# type: (Link, Search) -> Optional[InstallationCandidate]
|
|
||||||
"""Return an InstallationCandidate or None"""
|
|
||||||
version = None
|
|
||||||
if link.egg_fragment:
|
|
||||||
egg_info = link.egg_fragment
|
|
||||||
ext = link.ext
|
|
||||||
else:
|
|
||||||
egg_info, ext = link.splitext()
|
|
||||||
if not ext:
|
|
||||||
self._log_skipped_link(link, 'not a file')
|
|
||||||
return None
|
|
||||||
if ext not in SUPPORTED_EXTENSIONS:
|
|
||||||
self._log_skipped_link(
|
|
||||||
link, 'unsupported archive format: %s' % ext,
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
if "binary" not in search.formats and ext == WHEEL_EXTENSION:
|
|
||||||
self._log_skipped_link(
|
|
||||||
link, 'No binaries permitted for %s' % search.supplied,
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
if "macosx10" in link.path and ext == '.zip':
|
|
||||||
self._log_skipped_link(link, 'macosx10 one')
|
|
||||||
return None
|
|
||||||
if ext == WHEEL_EXTENSION:
|
|
||||||
try:
|
|
||||||
wheel = Wheel(link.filename)
|
|
||||||
except InvalidWheelFilename:
|
|
||||||
self._log_skipped_link(link, 'invalid wheel filename')
|
|
||||||
return None
|
|
||||||
if canonicalize_name(wheel.name) != search.canonical:
|
|
||||||
self._log_skipped_link(
|
|
||||||
link, 'wrong project name (not %s)' % search.supplied)
|
|
||||||
return None
|
|
||||||
|
|
||||||
if not self.candidate_evaluator.is_wheel_supported(wheel):
|
|
||||||
self._log_skipped_link(
|
|
||||||
link, 'it is not compatible with this Python')
|
|
||||||
return None
|
|
||||||
|
|
||||||
version = wheel.version
|
|
||||||
|
|
||||||
# This should be up by the search.ok_binary check, but see issue 2700.
|
|
||||||
if "source" not in search.formats and ext != WHEEL_EXTENSION:
|
|
||||||
self._log_skipped_link(
|
|
||||||
link, 'No sources permitted for %s' % search.supplied,
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
|
|
||||||
if not version:
|
|
||||||
version = _egg_info_matches(egg_info, search.canonical)
|
|
||||||
if not version:
|
|
||||||
self._log_skipped_link(
|
|
||||||
link, 'Missing project version for %s' % search.supplied)
|
|
||||||
return None
|
|
||||||
|
|
||||||
match = self._py_version_re.search(version)
|
|
||||||
if match:
|
|
||||||
version = version[:match.start()]
|
|
||||||
py_version = match.group(1)
|
|
||||||
if py_version != sys.version[:3]:
|
|
||||||
self._log_skipped_link(
|
|
||||||
link, 'Python version is incorrect')
|
|
||||||
return None
|
|
||||||
try:
|
|
||||||
support_this_python = check_requires_python(link.requires_python)
|
|
||||||
except specifiers.InvalidSpecifier:
|
|
||||||
logger.debug("Package %s has an invalid Requires-Python entry: %s",
|
|
||||||
link.filename, link.requires_python)
|
|
||||||
support_this_python = True
|
|
||||||
|
|
||||||
if not support_this_python:
|
|
||||||
logger.debug("The package %s is incompatible with the python "
|
|
||||||
"version in use. Acceptable python versions are: %s",
|
|
||||||
link, link.requires_python)
|
|
||||||
return None
|
|
||||||
logger.debug('Found link %s, version: %s', link, version)
|
|
||||||
|
|
||||||
return InstallationCandidate(search.supplied, version, link)
|
|
||||||
|
|
||||||
|
|
||||||
def _find_name_version_sep(egg_info, canonical_name):
|
def _find_name_version_sep(egg_info, canonical_name):
|
||||||
# type: (str, str) -> int
|
# type: (str, str) -> int
|
||||||
|
|
|
@ -471,11 +471,8 @@ class TestLinkPackageVersions(object):
|
||||||
self.version = '1.0'
|
self.version = '1.0'
|
||||||
self.search_name = 'pytest'
|
self.search_name = 'pytest'
|
||||||
self.canonical_name = 'pytest'
|
self.canonical_name = 'pytest'
|
||||||
self.finder = PackageFinder(
|
valid_tags = pip._internal.pep425tags.get_supported()
|
||||||
[],
|
self.evaluator = CandidateEvaluator(valid_tags=valid_tags)
|
||||||
[],
|
|
||||||
session=PipSession(),
|
|
||||||
)
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'url',
|
'url',
|
||||||
|
@ -492,7 +489,7 @@ class TestLinkPackageVersions(object):
|
||||||
canonical=self.canonical_name,
|
canonical=self.canonical_name,
|
||||||
formats=['source', 'binary'],
|
formats=['source', 'binary'],
|
||||||
)
|
)
|
||||||
result = self.finder._link_package_versions(link, search)
|
result = self.evaluator._link_package_versions(link, search)
|
||||||
expected = InstallationCandidate(self.search_name, self.version, link)
|
expected = InstallationCandidate(self.search_name, self.version, link)
|
||||||
assert result == expected, result
|
assert result == expected, result
|
||||||
|
|
||||||
|
@ -513,7 +510,7 @@ class TestLinkPackageVersions(object):
|
||||||
canonical=self.canonical_name,
|
canonical=self.canonical_name,
|
||||||
formats=['source', 'binary'],
|
formats=['source', 'binary'],
|
||||||
)
|
)
|
||||||
result = self.finder._link_package_versions(link, search)
|
result = self.evaluator._link_package_versions(link, search)
|
||||||
assert result is None, result
|
assert result is None, result
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue