diff --git a/news/4299.feature b/news/4299.feature new file mode 100644 index 00000000000..0f9f3c618b4 --- /dev/null +++ b/news/4299.feature @@ -0,0 +1 @@ +Support build-numbers in wheel versions and support sorting with build-numbers. diff --git a/pip/index.py b/pip/index.py index 5808b921a88..46f97e8e39a 100644 --- a/pip/index.py +++ b/pip/index.py @@ -278,6 +278,7 @@ def _candidate_sort_key(self, candidate): with the same version, would have to be considered equal """ support_num = len(self.valid_tags) + build_tag = tuple() if candidate.location.is_wheel: # can raise InvalidWheelFilename wheel = Wheel(candidate.location.filename) @@ -287,9 +288,13 @@ def _candidate_sort_key(self, candidate): "can't be sorted." % wheel.filename ) pri = -(wheel.support_index_min(self.valid_tags)) + if wheel.build_tag is not None: + match = re.match('^(\d+)(.*)$', wheel.build_tag) + build_tag_groups = match.groups() + build_tag = (int(build_tag_groups[0]), build_tag_groups[1]) else: # sdist pri = -(support_num) - return (candidate.version, pri) + return (candidate.version, build_tag, pri) def _validate_secure_origin(self, logger, location): # Determine if this url used a secure transport mechanism diff --git a/pip/wheel.py b/pip/wheel.py index 31cceed19ef..3727522cd43 100644 --- a/pip/wheel.py +++ b/pip/wheel.py @@ -482,7 +482,7 @@ class Wheel(object): wheel_file_re = re.compile( r"""^(?P(?P.+?)-(?P.*?)) - ((-(?P\d.*?))?-(?P.+?)-(?P.+?)-(?P.+?) + ((-(?P\d[^-]*?))?-(?P.+?)-(?P.+?)-(?P.+?) \.whl|\.dist-info)$""", re.VERBOSE ) @@ -501,6 +501,7 @@ def __init__(self, filename): # we'll assume "_" means "-" due to wheel naming scheme # (https://github.com/pypa/pip/issues/1150) self.version = wheel_info.group('ver').replace('_', '-') + self.build_tag = wheel_info.group('build') self.pyversions = wheel_info.group('pyver').split('.') self.abis = wheel_info.group('abi').split('.') self.plats = wheel_info.group('plat').split('.') diff --git a/tests/data/packages/simplewheel-2.0-1-py2.py3-none-any.whl b/tests/data/packages/simplewheel-2.0-1-py2.py3-none-any.whl new file mode 100644 index 00000000000..acf0c56cfd9 Binary files /dev/null and b/tests/data/packages/simplewheel-2.0-1-py2.py3-none-any.whl differ diff --git a/tests/unit/test_finder.py b/tests/unit/test_finder.py index 638d1f9cdd1..7cfb6d48019 100644 --- a/tests/unit/test_finder.py +++ b/tests/unit/test_finder.py @@ -251,6 +251,31 @@ def test_link_sorting(self): assert links == results == results2, results2 + def test_link_sorting_wheels_with_build_tags(self): + """Verify build tags affect sorting.""" + links = [ + InstallationCandidate( + "simplewheel", + "2.0", + Link("simplewheel-2.0-1-py2.py3-none-any.whl"), + ), + InstallationCandidate( + "simplewheel", + "2.0", + Link("simplewheel-2.0-py2.py3-none-any.whl"), + ), + InstallationCandidate( + "simplewheel", + "1.0", + Link("simplewheel-1.0-py2.py3-none-any.whl"), + ), + ] + finder = PackageFinder([], [], session=PipSession()) + results = sorted(links, key=finder._candidate_sort_key, reverse=True) + results2 = sorted(reversed(links), key=finder._candidate_sort_key, + reverse=True) + assert links == results == results2, results2 + def test_finder_priority_file_over_page(data): """Test PackageFinder prefers file links over equivalent page links"""