Skip to content

Commit a53c1e8

Browse files
committed
cleanup
1 parent 281f7fc commit a53c1e8

File tree

2 files changed

+115
-56
lines changed

2 files changed

+115
-56
lines changed

python/private/pypi/select_whl.bzl

Lines changed: 70 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ load("//python/private:version.bzl", "version")
44
load(":parse_whl_name.bzl", "parse_whl_name")
55
load(":python_tag.bzl", "PY_TAG_GENERIC", "python_tag")
66

7-
def _get_priority(*, tag, values, allow_wildcard = True):
7+
def _priority_by_values(*, tag, values, allow_wildcard = True):
88
keys = []
99
for priority, wp in enumerate(values):
1010
head, sep, tail = wp.partition("*")
@@ -18,12 +18,9 @@ def _get_priority(*, tag, values, allow_wildcard = True):
1818
elif sep and tag.startswith(head) and tag.endswith(tail):
1919
keys.append(priority)
2020

21-
if not keys:
22-
return None
23-
24-
return max(keys)
21+
return max(keys) if keys else None
2522

26-
def _get_py_priority(*, tag, implementation, py_version):
23+
def _priority_by_version(*, tag, implementation, py_version):
2724
if tag.startswith(PY_TAG_GENERIC):
2825
ver_str = tag[len(PY_TAG_GENERIC):]
2926
elif tag.startswith(implementation):
@@ -43,39 +40,83 @@ def _get_py_priority(*, tag, implementation, py_version):
4340
version.key(ver),
4441
)
4542

46-
def _tag_sets(*, whls, implementation, py_version, whl_abi_tags, platforms):
43+
def _candidates_by_priority(*, whls, implementation, py_version, whl_abi_tags, platforms, logger):
44+
"""Calculate the priority of each wheel
45+
46+
Args:
47+
whls: {type}`list[struct]` The whls to select from.
48+
implementation: {type}`str` The target Python implementation.
49+
py_version: {type}`struct` The target python version.
50+
whl_abi_tags: {type}`list[str]` The whl abi tags to select from.
51+
platforms: {type}`list[str]` The whl platform tags to select from.
52+
logger: The logger to use for debugging info
53+
54+
Returns:
55+
A dictionary where keys are priority tuples which allows us to sort and pick the
56+
last item.
57+
"""
58+
4759
ret = {}
4860
for whl in whls:
4961
parsed = parse_whl_name(whl.filename)
62+
priority = None
5063

5164
# See https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/#compressed-tag-sets
52-
for py in parsed.python_tag.split("."):
53-
py = _get_py_priority(
54-
tag = py,
55-
implementation = implementation,
56-
py_version = py_version,
57-
)
58-
if py == None:
59-
ret[struct(py = py)] = whl
65+
for platform in parsed.platform_tag.split("."):
66+
platform = _priority_by_values(tag = platform, values = platforms)
67+
if platform == None:
68+
if logger:
69+
logger.debug(lambda: "The platform_tag in '{}' does not match given list: {}".format(
70+
whl.filename,
71+
platforms,
72+
))
6073
continue
6174

62-
for abi in parsed.abi_tag.split("."):
63-
abi = _get_priority(
64-
tag = abi,
65-
values = whl_abi_tags,
66-
allow_wildcard = False,
75+
for py in parsed.python_tag.split("."):
76+
py = _priority_by_version(
77+
tag = py,
78+
implementation = implementation,
79+
py_version = py_version,
6780
)
6881
if py == None:
69-
ret[struct(py = py, abi = abi)] = whl
82+
if logger:
83+
logger.debug(lambda: "The python_tag in '{}' does not match implementation or version: {} {}".format(
84+
whl.filename,
85+
implementation,
86+
py_version.string,
87+
))
7088
continue
7189

72-
for p in parsed.platform_tag.split("."):
73-
platform = _get_priority(
74-
tag = p,
75-
values = platforms,
90+
for abi in parsed.abi_tag.split("."):
91+
abi = _priority_by_values(
92+
tag = abi,
93+
values = whl_abi_tags,
94+
allow_wildcard = False,
7695
)
96+
if abi == None:
97+
if logger:
98+
logger.debug(lambda: "The abi_tag in '{}' does not match given list: {}".format(
99+
whl.filename,
100+
whl_abi_tags,
101+
))
102+
continue
103+
104+
# 1. Prefer platform wheels
105+
# 2. Then prefer implementation/python version
106+
# 3. Then prefer more specific ABI wheels
107+
candidate = (platform, py, abi)
108+
priority = priority or candidate
109+
if candidate > priority:
110+
priority = candidate
111+
112+
if priority == None:
113+
if logger:
114+
logger.debug(lambda: "The whl '{}' is incompatible".format(
115+
whl.filename,
116+
))
117+
continue
77118

78-
ret[struct(py = py, abi = abi, platform = platform)] = whl
119+
ret[priority] = whl
79120

80121
return ret
81122

@@ -102,41 +143,14 @@ def select_whl(*, whls, python_version, platforms, whl_abi_tags, implementation_
102143
candidates = {}
103144
implementation = python_tag(implementation_name)
104145

105-
for priority, whl in _tag_sets(
146+
candidates = _candidates_by_priority(
106147
whls = whls,
107148
implementation = implementation,
108149
py_version = py_version,
109150
whl_abi_tags = whl_abi_tags,
110151
platforms = platforms,
111-
).items():
112-
if priority.py == None:
113-
if logger:
114-
logger.debug(lambda: "The python_tag in '{}' does not match implementation or version: {} {}".format(
115-
whl.filename,
116-
implementation,
117-
py_version.string,
118-
))
119-
continue
120-
elif priority.abi == None:
121-
if logger:
122-
logger.debug(lambda: "The abi_tag in '{}' does not match given list: {}".format(
123-
whl.filename,
124-
whl_abi_tags,
125-
))
126-
continue
127-
elif priority.platform == None:
128-
if logger:
129-
logger.debug(lambda: "The platform_tag in '{}' does not match given list: {}".format(
130-
whl.filename,
131-
platforms,
132-
))
133-
continue
134-
135-
candidates.setdefault((
136-
priority.platform, # Prefer platform wheels
137-
priority.py, # Then prefer implementation/python version
138-
priority.abi, # Then prefer more specific ABI wheels
139-
), whl)
152+
logger = logger,
153+
)
140154

141155
if not candidates:
142156
return None

tests/pypi/select_whl/select_whl_tests.bzl

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,29 @@ def _test_not_select_py2(env):
118118

119119
_tests.append(_test_not_select_py2)
120120

121+
def _test_not_select_abi3(env):
122+
# Check we prefer platform specific wheels
123+
got = _select_whl(
124+
whls = [
125+
"pkg-0.0.1-py3-none-any.whl",
126+
# the following should be ignored
127+
"pkg-0.0.1-py3-abi3-any.whl",
128+
"pkg-0.0.1-py3-abi3-p1.p2.p2.whl",
129+
],
130+
platforms = ["any", "p1"],
131+
whl_abi_tags = ["none"],
132+
python_version = "3.13",
133+
limit = 2,
134+
debug = True,
135+
)
136+
_match(
137+
env,
138+
got,
139+
"pkg-0.0.1-py3-none-any.whl",
140+
)
141+
142+
_tests.append(_test_not_select_abi3)
143+
121144
def _test_select_cp312(env):
122145
# Check we prefer platform specific wheels
123146
got = _select_whl(
@@ -347,6 +370,28 @@ def _test_pytags_all_possible(env):
347370

348371
_tests.append(_test_pytags_all_possible)
349372

373+
def _test_manylinx_musllinux_pref(env):
374+
got = _select_whl(
375+
whls = [
376+
"pkg-0.0.1-py3-none-manylinux_2_31_x86_64.musllinux_1_1_x86_64.whl",
377+
],
378+
platforms = [
379+
"manylinux_*_x86_64",
380+
"musllinux_*_x86_64",
381+
],
382+
whl_abi_tags = ["none"],
383+
python_version = "3.12",
384+
limit = 2,
385+
)
386+
_match(
387+
env,
388+
got,
389+
# there is only wheel, just select that
390+
"pkg-0.0.1-py3-none-manylinux_2_31_x86_64.musllinux_1_1_x86_64.whl",
391+
)
392+
393+
_tests.append(_test_manylinx_musllinux_pref)
394+
350395
def select_whl_test_suite(name):
351396
"""Create the test suite.
352397

0 commit comments

Comments
 (0)