Skip to content

Commit 785266e

Browse files
committed
Replace custom wheel filename regex with packaging parse_wheel_filename
1 parent e98cc5c commit 785266e

File tree

4 files changed

+43
-50
lines changed

4 files changed

+43
-50
lines changed

src/pip/_internal/index/package_finder.py

+1-5
Original file line numberDiff line numberDiff line change
@@ -528,11 +528,7 @@ def _sort_key(self, candidate: InstallationCandidate) -> CandidateSortingKey:
528528
)
529529
if self._prefer_binary:
530530
binary_preference = 1
531-
if wheel.build_tag is not None:
532-
match = re.match(r"^(\d+)(.*)$", wheel.build_tag)
533-
assert match is not None, "guaranteed by filename validation"
534-
build_tag_groups = match.groups()
535-
build_tag = (int(build_tag_groups[0]), build_tag_groups[1])
531+
build_tag = wheel.build_tag
536532
else: # sdist
537533
pri = -(support_num)
538534
has_allowed_hash = int(link.is_hash_allowed(self._hashes))

src/pip/_internal/metadata/importlib/_envs.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@
88
import zipimport
99
from typing import Iterator, List, Optional, Sequence, Set, Tuple
1010

11-
from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
11+
from pip._vendor.packaging.utils import (
12+
InvalidWheelFilename,
13+
NormalizedName,
14+
canonicalize_name,
15+
parse_wheel_filename,
16+
)
1217

1318
from pip._internal.metadata.base import BaseDistribution, BaseEnvironment
14-
from pip._internal.models.wheel import Wheel
1519
from pip._internal.utils.deprecation import deprecated
1620
from pip._internal.utils.filetypes import WHEEL_EXTENSION
1721

@@ -26,7 +30,9 @@ def _looks_like_wheel(location: str) -> bool:
2630
return False
2731
if not os.path.isfile(location):
2832
return False
29-
if not Wheel.wheel_file_re.match(os.path.basename(location)):
33+
try:
34+
parse_wheel_filename(os.path.basename(location))
35+
except InvalidWheelFilename:
3036
return False
3137
return zipfile.is_zipfile(location)
3238

src/pip/_internal/models/wheel.py

+11-27
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,29 @@
22
name that have meaning.
33
"""
44

5-
import re
65
from typing import Dict, Iterable, List
76

87
from pip._vendor.packaging.tags import Tag
8+
from pip._vendor.packaging.utils import (
9+
InvalidWheelFilename as _PackagingInvalidWheelFilename,
10+
)
11+
from pip._vendor.packaging.utils import parse_wheel_filename
912

1013
from pip._internal.exceptions import InvalidWheelFilename
1114

1215

1316
class Wheel:
1417
"""A wheel file"""
1518

16-
wheel_file_re = re.compile(
17-
r"""^(?P<namever>(?P<name>[^\s-]+?)-(?P<ver>[^\s-]*?))
18-
((-(?P<build>\d[^-]*?))?-(?P<pyver>[^\s-]+?)-(?P<abi>[^\s-]+?)-(?P<plat>[^\s-]+?)
19-
\.whl|\.dist-info)$""",
20-
re.VERBOSE,
21-
)
22-
2319
def __init__(self, filename: str) -> None:
24-
"""
25-
:raises InvalidWheelFilename: when the filename is invalid for a wheel
26-
"""
27-
wheel_info = self.wheel_file_re.match(filename)
28-
if not wheel_info:
29-
raise InvalidWheelFilename(f"{filename} is not a valid wheel filename.")
3020
self.filename = filename
31-
self.name = wheel_info.group("name").replace("_", "-")
32-
# we'll assume "_" means "-" due to wheel naming scheme
33-
# (https://github.com/pypa/pip/issues/1150)
34-
self.version = wheel_info.group("ver").replace("_", "-")
35-
self.build_tag = wheel_info.group("build")
36-
self.pyversions = wheel_info.group("pyver").split(".")
37-
self.abis = wheel_info.group("abi").split(".")
38-
self.plats = wheel_info.group("plat").split(".")
39-
40-
# All the tag combinations from this file
41-
self.file_tags = {
42-
Tag(x, y, z) for x in self.pyversions for y in self.abis for z in self.plats
43-
}
21+
try:
22+
wheel_info = parse_wheel_filename(filename)
23+
except _PackagingInvalidWheelFilename as e:
24+
raise InvalidWheelFilename(e.args[0]) from None
25+
26+
self.name, _version, self.build_tag, self.file_tags = wheel_info
27+
self.version = str(_version)
4428

4529
def get_formatted_file_tags(self) -> List[str]:
4630
"""Return the wheel's tags as a sorted list of strings."""

tests/unit/test_models_wheel.py

+22-15
Original file line numberDiff line numberDiff line change
@@ -11,35 +11,43 @@ def test_std_wheel_pattern(self) -> None:
1111
w = Wheel("simple-1.1.1-py2-none-any.whl")
1212
assert w.name == "simple"
1313
assert w.version == "1.1.1"
14-
assert w.pyversions == ["py2"]
15-
assert w.abis == ["none"]
16-
assert w.plats == ["any"]
14+
assert w.build_tag == ()
15+
assert w.file_tags == frozenset(
16+
[Tag(interpreter="py2", abi="none", platform="any")]
17+
)
1718

1819
def test_wheel_pattern_multi_values(self) -> None:
1920
w = Wheel("simple-1.1-py2.py3-abi1.abi2-any.whl")
2021
assert w.name == "simple"
2122
assert w.version == "1.1"
22-
assert w.pyversions == ["py2", "py3"]
23-
assert w.abis == ["abi1", "abi2"]
24-
assert w.plats == ["any"]
23+
assert w.build_tag == ()
24+
assert w.file_tags == frozenset(
25+
[
26+
Tag(interpreter="py2", abi="abi1", platform="any"),
27+
Tag(interpreter="py2", abi="abi2", platform="any"),
28+
Tag(interpreter="py3", abi="abi1", platform="any"),
29+
Tag(interpreter="py3", abi="abi2", platform="any"),
30+
]
31+
)
2532

2633
def test_wheel_with_build_tag(self) -> None:
2734
# pip doesn't do anything with build tags, but theoretically, we might
2835
# see one, in this case the build tag = '4'
2936
w = Wheel("simple-1.1-4-py2-none-any.whl")
3037
assert w.name == "simple"
3138
assert w.version == "1.1"
32-
assert w.pyversions == ["py2"]
33-
assert w.abis == ["none"]
34-
assert w.plats == ["any"]
39+
assert w.build_tag == (4, "")
40+
assert w.file_tags == frozenset(
41+
[Tag(interpreter="py2", abi="none", platform="any")]
42+
)
3543

3644
def test_single_digit_version(self) -> None:
3745
w = Wheel("simple-1-py2-none-any.whl")
3846
assert w.version == "1"
3947

4048
def test_non_pep440_version(self) -> None:
41-
w = Wheel("simple-_invalid_-py2-none-any.whl")
42-
assert w.version == "-invalid-"
49+
with pytest.raises(InvalidWheelFilename):
50+
Wheel("simple-_invalid_-py2-none-any.whl")
4351

4452
def test_missing_version_raises(self) -> None:
4553
with pytest.raises(InvalidWheelFilename):
@@ -172,8 +180,7 @@ def test_support_index_min__none_supported(self) -> None:
172180

173181
def test_version_underscore_conversion(self) -> None:
174182
"""
175-
Test that we convert '_' to '-' for versions parsed out of wheel
176-
filenames
183+
'_' is not PEP 440 compliant in the version part of a wheel filename
177184
"""
178-
w = Wheel("simple-0.1_1-py2-none-any.whl")
179-
assert w.version == "0.1-1"
185+
with pytest.raises(InvalidWheelFilename):
186+
Wheel("simple-0.1_1-py2-none-any.whl")

0 commit comments

Comments
 (0)