From 80b2c82d0c472deb40b09da5b045786c85b9a159 Mon Sep 17 00:00:00 2001 From: Chris Hunt Date: Sat, 23 Nov 2019 18:02:25 -0500 Subject: [PATCH 1/2] Use packaging.tags.Tag in place of Tuple This is the standard type used by packaging.tags. Making this change throughout the code lets us start switching over to using its tag-generating functions in get_supported(). We also get rid of a test, since it was superseded by `__str__` in packaging.tags.Tag. --- src/pip/_internal/cache.py | 10 +++--- src/pip/_internal/commands/debug.py | 3 +- src/pip/_internal/index/package_finder.py | 6 ++-- src/pip/_internal/models/target_python.py | 7 +++-- src/pip/_internal/models/wheel.py | 13 ++++---- src/pip/_internal/pep425tags.py | 12 ++++--- tests/unit/test_cache.py | 8 +++-- tests/unit/test_finder.py | 7 +++-- tests/unit/test_models_wheel.py | 13 ++++---- tests/unit/test_pep425tags.py | 38 ++++++++++++++--------- 10 files changed, 68 insertions(+), 49 deletions(-) diff --git a/src/pip/_internal/cache.py b/src/pip/_internal/cache.py index 3f5a78299fa..c0e002c414e 100644 --- a/src/pip/_internal/cache.py +++ b/src/pip/_internal/cache.py @@ -22,8 +22,10 @@ if MYPY_CHECK_RUNNING: from typing import Optional, Set, List, Any, Dict + + from pip._vendor.packaging.tags import Tag + from pip._internal.models.format_control import FormatControl - from pip._internal.pep425tags import Pep425Tag logger = logging.getLogger(__name__) @@ -161,7 +163,7 @@ def get( self, link, # type: Link package_name, # type: Optional[str] - supported_tags, # type: List[Pep425Tag] + supported_tags, # type: List[Tag] ): # type: (...) -> Link """Returns a link to a cached item if it exists, otherwise returns the @@ -214,7 +216,7 @@ def get( self, link, # type: Link package_name, # type: Optional[str] - supported_tags, # type: List[Pep425Tag] + supported_tags, # type: List[Tag] ): # type: (...) -> Link candidates = [] @@ -304,7 +306,7 @@ def get( self, link, # type: Link package_name, # type: Optional[str] - supported_tags, # type: List[Pep425Tag] + supported_tags, # type: List[Tag] ): # type: (...) -> Link retval = self._wheel_cache.get( diff --git a/src/pip/_internal/commands/debug.py b/src/pip/_internal/commands/debug.py index 2a262e759eb..fe93b3a3926 100644 --- a/src/pip/_internal/commands/debug.py +++ b/src/pip/_internal/commands/debug.py @@ -14,7 +14,6 @@ from pip._internal.cli.base_command import Command from pip._internal.cli.cmdoptions import make_target_python from pip._internal.cli.status_codes import SUCCESS -from pip._internal.pep425tags import format_tag from pip._internal.utils.logging import indent_log from pip._internal.utils.misc import get_pip_version from pip._internal.utils.typing import MYPY_CHECK_RUNNING @@ -68,7 +67,7 @@ def show_tags(options): with indent_log(): for tag in tags: - logger.info(format_tag(tag)) + logger.info(str(tag)) if tags_limited: msg = ( diff --git a/src/pip/_internal/index/package_finder.py b/src/pip/_internal/index/package_finder.py index d9ee8b5a877..a74d78db5a6 100644 --- a/src/pip/_internal/index/package_finder.py +++ b/src/pip/_internal/index/package_finder.py @@ -37,11 +37,13 @@ from typing import ( FrozenSet, Iterable, List, Optional, Set, Text, Tuple, Union, ) + + from pip._vendor.packaging.tags import Tag from pip._vendor.packaging.version import _BaseVersion + from pip._internal.index.collector import LinkCollector from pip._internal.models.search_scope import SearchScope from pip._internal.req import InstallRequirement - from pip._internal.pep425tags import Pep425Tag from pip._internal.utils.hashes import Hashes BuildTag = Union[Tuple[()], Tuple[int, str]] @@ -425,7 +427,7 @@ def create( def __init__( self, project_name, # type: str - supported_tags, # type: List[Pep425Tag] + supported_tags, # type: List[Tag] specifier, # type: specifiers.BaseSpecifier prefer_binary=False, # type: bool allow_all_prereleases=False, # type: bool diff --git a/src/pip/_internal/models/target_python.py b/src/pip/_internal/models/target_python.py index cd08c917899..97ae85a0945 100644 --- a/src/pip/_internal/models/target_python.py +++ b/src/pip/_internal/models/target_python.py @@ -6,7 +6,8 @@ if MYPY_CHECK_RUNNING: from typing import List, Optional, Tuple - from pip._internal.pep425tags import Pep425Tag + + from pip._vendor.packaging.tags import Tag class TargetPython(object): @@ -55,7 +56,7 @@ def __init__( self.py_version_info = py_version_info # This is used to cache the return value of get_tags(). - self._valid_tags = None # type: Optional[List[Pep425Tag]] + self._valid_tags = None # type: Optional[List[Tag]] def format_given(self): # type: () -> str @@ -80,7 +81,7 @@ def format_given(self): ) def get_tags(self): - # type: () -> List[Pep425Tag] + # type: () -> List[Tag] """ Return the supported PEP 425 tags to check wheel candidates against. diff --git a/src/pip/_internal/models/wheel.py b/src/pip/_internal/models/wheel.py index 4c7a8af78fa..f1e3f44c598 100644 --- a/src/pip/_internal/models/wheel.py +++ b/src/pip/_internal/models/wheel.py @@ -3,15 +3,14 @@ """ import re +from pip._vendor.packaging.tags import Tag + from pip._internal.exceptions import InvalidWheelFilename -from pip._internal.pep425tags import format_tag from pip._internal.utils.typing import MYPY_CHECK_RUNNING if MYPY_CHECK_RUNNING: from typing import List - from pip._internal.pep425tags import Pep425Tag - class Wheel(object): """A wheel file""" @@ -45,17 +44,17 @@ def __init__(self, filename): # All the tag combinations from this file self.file_tags = { - (x, y, z) for x in self.pyversions + Tag(x, y, z) for x in self.pyversions for y in self.abis for z in self.plats } def get_formatted_file_tags(self): # type: () -> List[str] """Return the wheel's tags as a sorted list of strings.""" - return sorted(format_tag(tag) for tag in self.file_tags) + return sorted(str(tag) for tag in self.file_tags) def support_index_min(self, tags): - # type: (List[Pep425Tag]) -> int + # type: (List[Tag]) -> int """Return the lowest index that one of the wheel's file_tag combinations achieves in the given list of supported tags. @@ -71,7 +70,7 @@ def support_index_min(self, tags): return min(tags.index(tag) for tag in self.file_tags if tag in tags) def supported(self, tags): - # type: (List[Pep425Tag]) -> bool + # type: (List[Tag]) -> bool """Return whether the wheel is compatible with one of the given tags. :param tags: the PEP 425 tags to check the wheel against. diff --git a/src/pip/_internal/pep425tags.py b/src/pip/_internal/pep425tags.py index 841597596b2..f2e62c93896 100644 --- a/src/pip/_internal/pep425tags.py +++ b/src/pip/_internal/pep425tags.py @@ -9,7 +9,11 @@ import sysconfig from collections import OrderedDict -from pip._vendor.packaging.tags import interpreter_name, interpreter_version +from pip._vendor.packaging.tags import ( + Tag, + interpreter_name, + interpreter_version, +) from pip._vendor.six import PY2 import pip._internal.utils.glibc @@ -20,8 +24,6 @@ Tuple, Callable, List, Optional, Union, Dict ) - Pep425Tag = Tuple[str, str, str] - logger = logging.getLogger(__name__) _osx_arch_pat = re.compile(r'(.+)_(\d+)_(\d+)_(.+)') @@ -365,7 +367,7 @@ def get_supported( impl=None, # type: Optional[str] abi=None # type: Optional[str] ): - # type: (...) -> List[Pep425Tag] + # type: (...) -> List[Tag] """Return a list of supported tags for each version specified in `versions`. @@ -433,4 +435,4 @@ def get_supported( for version in other_versions: supported.append(('py%s' % (version,), 'none', 'any')) - return supported + return [Tag(*parts) for parts in supported] diff --git a/tests/unit/test_cache.py b/tests/unit/test_cache.py index 5d81fc01d14..1a4f98b28bd 100644 --- a/tests/unit/test_cache.py +++ b/tests/unit/test_cache.py @@ -1,5 +1,7 @@ import os +from pip._vendor.packaging.tags import Tag + from pip._internal.cache import WheelCache, _hash_dict from pip._internal.models.format_control import FormatControl from pip._internal.models.link import Link @@ -39,11 +41,11 @@ def test_wheel_name_filter(tmpdir): with open(os.path.join(cache_path, "package-1.0-py3-none-any.whl"), "w"): pass # package matches wheel name - cached_link = wc.get(link, "package", [("py3", "none", "any")]) + cached_link = wc.get(link, "package", [Tag("py3", "none", "any")]) assert cached_link is not link assert os.path.exists(cached_link.file_path) # package2 does not match wheel name - assert wc.get(link, "package2", [("py3", "none", "any")]) is link + assert wc.get(link, "package2", [Tag("py3", "none", "any")]) is link def test_cache_hash(): @@ -89,7 +91,7 @@ def test_get_with_legacy_entry_only(tmpdir): ensure_dir(legacy_path) with open(os.path.join(legacy_path, "test-1.0.0-py3-none-any.whl"), "w"): pass - cached_link = wc.get(link, "test", [("py3", "none", "any")]) + cached_link = wc.get(link, "test", [Tag("py3", "none", "any")]) assert ( os.path.normcase(os.path.dirname(cached_link.file_path)) == os.path.normcase(legacy_path) diff --git a/tests/unit/test_finder.py b/tests/unit/test_finder.py index b8e179c115e..fb2326c82d5 100644 --- a/tests/unit/test_finder.py +++ b/tests/unit/test_finder.py @@ -4,6 +4,7 @@ import pytest from mock import Mock, patch from pip._vendor.packaging.specifiers import SpecifierSet +from pip._vendor.packaging.tags import Tag from pkg_resources import parse_version import pip._internal.pep425tags @@ -238,9 +239,9 @@ def test_link_sorting(self): ), ] valid_tags = [ - ('pyT', 'none', 'TEST'), - ('pyT', 'TEST', 'any'), - ('pyT', 'none', 'any'), + Tag('pyT', 'none', 'TEST'), + Tag('pyT', 'TEST', 'any'), + Tag('pyT', 'none', 'any'), ] specifier = SpecifierSet() evaluator = CandidateEvaluator( diff --git a/tests/unit/test_models_wheel.py b/tests/unit/test_models_wheel.py index 8b351356d83..f74dd367954 100644 --- a/tests/unit/test_models_wheel.py +++ b/tests/unit/test_models_wheel.py @@ -1,4 +1,5 @@ import pytest +from pip._vendor.packaging.tags import Tag from pip._internal import pep425tags from pip._internal.exceptions import InvalidWheelFilename @@ -54,21 +55,21 @@ def test_supported_single_version(self): Test single-version wheel is known to be supported """ w = Wheel('simple-0.1-py2-none-any.whl') - assert w.supported(tags=[('py2', 'none', 'any')]) + assert w.supported(tags=[Tag('py2', 'none', 'any')]) def test_supported_multi_version(self): """ Test multi-version wheel is known to be supported """ w = Wheel('simple-0.1-py2.py3-none-any.whl') - assert w.supported(tags=[('py3', 'none', 'any')]) + assert w.supported(tags=[Tag('py3', 'none', 'any')]) def test_not_supported_version(self): """ Test unsupported wheel is known to be unsupported """ w = Wheel('simple-0.1-py2-none-any.whl') - assert not w.supported(tags=[('py1', 'none', 'any')]) + assert not w.supported(tags=[Tag('py1', 'none', 'any')]) def test_supported_osx_version(self): """ @@ -153,9 +154,9 @@ def test_support_index_min(self): Test results from `support_index_min` """ tags = [ - ('py2', 'none', 'TEST'), - ('py2', 'TEST', 'any'), - ('py2', 'none', 'any'), + Tag('py2', 'none', 'TEST'), + Tag('py2', 'TEST', 'any'), + Tag('py2', 'none', 'any'), ] w = Wheel('simple-0.1-py2-none-any.whl') assert w.support_index_min(tags=tags) == 2 diff --git a/tests/unit/test_pep425tags.py b/tests/unit/test_pep425tags.py index b41edcc7bf5..14ea5f0ac96 100644 --- a/tests/unit/test_pep425tags.py +++ b/tests/unit/test_pep425tags.py @@ -98,10 +98,10 @@ def test_no_hyphen_tag(self): mock_gcf): supported = pip._internal.pep425tags.get_supported() - for (py, abi, plat) in supported: - assert '-' not in py - assert '-' not in abi - assert '-' not in plat + for tag in supported: + assert '-' not in tag.interpreter + assert '-' not in tag.abi + assert '-' not in tag.platform def test_manual_abi_noflags(self): """ @@ -192,8 +192,10 @@ def test_manylinux1_tag_is_first(self): Test that the more specific tag manylinux1 comes first. """ groups = {} - for pyimpl, abi, arch in pep425tags.get_supported(): - groups.setdefault((pyimpl, abi), []).append(arch) + for tag in pep425tags.get_supported(): + groups.setdefault( + (tag.interpreter, tag.abi), [] + ).append(tag.platform) for arches in groups.values(): if arches == ['any']: @@ -218,8 +220,10 @@ def test_manylinux2010_tag_is_first(self): Test that the more specific tag manylinux2010 comes first. """ groups = {} - for pyimpl, abi, arch in pep425tags.get_supported(): - groups.setdefault((pyimpl, abi), []).append(arch) + for tag in pep425tags.get_supported(): + groups.setdefault( + (tag.interpreter, tag.abi), [] + ).append(tag.platform) for arches in groups.values(): if arches == ['any']: @@ -245,8 +249,10 @@ def test_manylinux2010_implies_manylinux1(self, manylinux2010, manylinux1): """ groups = {} supported = pep425tags.get_supported(platform=manylinux2010) - for pyimpl, abi, arch in supported: - groups.setdefault((pyimpl, abi), []).append(arch) + for tag in supported: + groups.setdefault( + (tag.interpreter, tag.abi), [] + ).append(tag.platform) for arches in groups.values(): if arches == ['any']: @@ -265,8 +271,10 @@ def test_manylinux2014_tag_is_first(self): Test that the more specific tag manylinux2014 comes first. """ groups = {} - for pyimpl, abi, arch in pep425tags.get_supported(): - groups.setdefault((pyimpl, abi), []).append(arch) + for tag in pep425tags.get_supported(): + groups.setdefault( + (tag.interpreter, tag.abi), [] + ).append(tag.platform) for arches in groups.values(): if arches == ['any']: @@ -295,8 +303,10 @@ def test_manylinuxA_implies_manylinuxB(self, manylinuxA, manylinuxB): """ groups = {} supported = pep425tags.get_supported(platform=manylinuxA) - for pyimpl, abi, arch in supported: - groups.setdefault((pyimpl, abi), []).append(arch) + for tag in supported: + groups.setdefault( + (tag.interpreter, tag.abi), [] + ).append(tag.platform) expected_arches = [manylinuxA] expected_arches.extend(manylinuxB) From 58f175fdf2505d119467c78222d9736cf54dc968 Mon Sep 17 00:00:00 2001 From: Chris Hunt Date: Sat, 23 Nov 2019 18:02:26 -0500 Subject: [PATCH 2/2] Remove unused format_tag Since we delegate tag formatting to packaging.tags.Tag, we don't need this function or its tests. --- src/pip/_internal/pep425tags.py | 9 --------- tests/unit/test_pep425tags.py | 9 --------- 2 files changed, 18 deletions(-) diff --git a/src/pip/_internal/pep425tags.py b/src/pip/_internal/pep425tags.py index f2e62c93896..25c0cedd681 100644 --- a/src/pip/_internal/pep425tags.py +++ b/src/pip/_internal/pep425tags.py @@ -29,15 +29,6 @@ _osx_arch_pat = re.compile(r'(.+)_(\d+)_(\d+)_(.+)') -def format_tag(file_tag): - # type: (Tuple[str, ...]) -> str - """Format three tags in the form "--". - - :param file_tag: A 3-tuple of tags (python_tag, abi_tag, platform_tag). - """ - return '-'.join(file_tag) - - def get_config_var(var): # type: (str) -> Optional[str] return sysconfig.get_config_var(var) diff --git a/tests/unit/test_pep425tags.py b/tests/unit/test_pep425tags.py index 14ea5f0ac96..eaa88888fb0 100644 --- a/tests/unit/test_pep425tags.py +++ b/tests/unit/test_pep425tags.py @@ -7,15 +7,6 @@ from pip._internal import pep425tags -@pytest.mark.parametrize('file_tag, expected', [ - (('py27', 'none', 'any'), 'py27-none-any'), - (('cp33', 'cp32dmu', 'linux_x86_64'), 'cp33-cp32dmu-linux_x86_64'), -]) -def test_format_tag(file_tag, expected): - actual = pep425tags.format_tag(file_tag) - assert actual == expected - - @pytest.mark.parametrize('version_info, expected', [ ((2,), '2'), ((2, 8), '28'),