Skip to content

Commit 281f7fc

Browse files
committed
refactor/cleanup code
1 parent 7ebf0c0 commit 281f7fc

File tree

1 file changed

+82
-81
lines changed

1 file changed

+82
-81
lines changed

python/private/pypi/select_whl.bzl

Lines changed: 82 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -4,55 +4,80 @@ 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(*, tags, values, allow_wildcard = True):
7+
def _get_priority(*, tag, values, allow_wildcard = True):
88
keys = []
99
for priority, wp in enumerate(values):
10-
for tag in tags.split("."):
11-
head, sep, tail = wp.partition("*")
12-
if "*" in tail:
13-
fail("only a single '*' can be present in the matcher")
14-
if not allow_wildcard and sep:
15-
fail("'*' is not allowed in the matcher")
16-
17-
if not sep and tag == head:
18-
keys.append(priority)
19-
elif sep and tag.startswith(head) and tag.endswith(tail):
20-
keys.append(priority)
10+
head, sep, tail = wp.partition("*")
11+
if "*" in tail:
12+
fail("only a single '*' can be present in the matcher")
13+
if not allow_wildcard and sep:
14+
fail("'*' is not allowed in the matcher")
15+
16+
if not sep and tag == head:
17+
keys.append(priority)
18+
elif sep and tag.startswith(head) and tag.endswith(tail):
19+
keys.append(priority)
2120

2221
if not keys:
2322
return None
2423

2524
return max(keys)
2625

27-
def _get_py_priority(*, tags, implementation, py_version):
28-
keys = []
29-
for tag in tags.split("."):
30-
if tag.startswith(PY_TAG_GENERIC):
31-
ver_str = tag[len(PY_TAG_GENERIC):]
32-
elif tag.startswith(implementation):
33-
ver_str = tag[len(implementation):]
34-
else:
35-
continue
26+
def _get_py_priority(*, tag, implementation, py_version):
27+
if tag.startswith(PY_TAG_GENERIC):
28+
ver_str = tag[len(PY_TAG_GENERIC):]
29+
elif tag.startswith(implementation):
30+
ver_str = tag[len(implementation):]
31+
else:
32+
return None
3633

37-
# Add a 0 at the end in case it is a single digit
38-
ver_str = "{}.{}".format(ver_str[0], ver_str[1:] or "0")
34+
# Add a 0 at the end in case it is a single digit
35+
ver_str = "{}.{}".format(ver_str[0], ver_str[1:] or "0")
3936

40-
ver = version.parse(ver_str)
41-
if not version.is_compatible(py_version, ver):
42-
continue
37+
ver = version.parse(ver_str)
38+
if not version.is_compatible(py_version, ver):
39+
return None
4340

44-
keys.append((
45-
tag.startswith(implementation),
46-
version.key(ver),
47-
# Prefer shorter py_tags, which will yield more specialized matches,
48-
# like preferring py3 over py2.py3
49-
-len(tags),
50-
))
41+
return (
42+
tag.startswith(implementation),
43+
version.key(ver),
44+
)
5145

52-
if not keys:
53-
return None
46+
def _tag_sets(*, whls, implementation, py_version, whl_abi_tags, platforms):
47+
ret = {}
48+
for whl in whls:
49+
parsed = parse_whl_name(whl.filename)
5450

55-
return max(keys)
51+
# 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
60+
continue
61+
62+
for abi in parsed.abi_tag.split("."):
63+
abi = _get_priority(
64+
tag = abi,
65+
values = whl_abi_tags,
66+
allow_wildcard = False,
67+
)
68+
if py == None:
69+
ret[struct(py = py, abi = abi)] = whl
70+
continue
71+
72+
for p in parsed.platform_tag.split("."):
73+
platform = _get_priority(
74+
tag = p,
75+
values = platforms,
76+
)
77+
78+
ret[struct(py = py, abi = abi, platform = platform)] = whl
79+
80+
return ret
5681

5782
def select_whl(*, whls, python_version, platforms, whl_abi_tags, implementation_name = "cpython", limit = 1, logger = None):
5883
"""Select a whl that is the most suitable for the given platform.
@@ -77,65 +102,41 @@ def select_whl(*, whls, python_version, platforms, whl_abi_tags, implementation_
77102
candidates = {}
78103
implementation = python_tag(implementation_name)
79104

80-
for whl in whls:
81-
parsed = parse_whl_name(whl.filename)
82-
83-
if parsed.python_tag.startswith(PY_TAG_GENERIC):
84-
pass
85-
elif not parsed.python_tag.startswith(implementation):
105+
for priority, whl in _tag_sets(
106+
whls = whls,
107+
implementation = implementation,
108+
py_version = py_version,
109+
whl_abi_tags = whl_abi_tags,
110+
platforms = platforms,
111+
).items():
112+
if priority.py == None:
86113
if logger:
87-
logger.debug(lambda: "Discarding the wheel because the implementation '{}' is not compatible with target implementation '{}'".format(
88-
parsed.python_tag,
89-
implementation,
90-
))
91-
continue
92-
93-
py_priority = _get_py_priority(
94-
tags = parsed.python_tag,
95-
implementation = implementation,
96-
py_version = py_version,
97-
)
98-
if py_priority == None:
99-
if logger:
100-
logger.debug(lambda: "The py_tag '{}' does not match implementation version: {} {}".format(
101-
parsed.py_tag,
114+
logger.debug(lambda: "The python_tag in '{}' does not match implementation or version: {} {}".format(
115+
whl.filename,
102116
implementation,
103117
py_version.string,
104118
))
105119
continue
106-
107-
abi_priority = _get_priority(
108-
tags = parsed.abi_tag,
109-
values = whl_abi_tags,
110-
allow_wildcard = False,
111-
)
112-
if abi_priority == None:
120+
elif priority.abi == None:
113121
if logger:
114-
logger.debug(lambda: "The abi '{}' does not match given list: {}".format(
115-
parsed.abi_tag,
122+
logger.debug(lambda: "The abi_tag in '{}' does not match given list: {}".format(
123+
whl.filename,
116124
whl_abi_tags,
117125
))
118126
continue
119-
120-
platform_priority = _get_priority(
121-
tags = parsed.platform_tag,
122-
values = platforms,
123-
)
124-
if platform_priority == None:
127+
elif priority.platform == None:
125128
if logger:
126-
logger.debug(lambda: "The platform_tag '{}' does not match given list: {}".format(
127-
parsed.platform_tag,
129+
logger.debug(lambda: "The platform_tag in '{}' does not match given list: {}".format(
130+
whl.filename,
128131
platforms,
129132
))
130133
continue
131134

132-
key = (
133-
# Ensure that we chose the highest compatible version
134-
py_priority,
135-
platform_priority,
136-
abi_priority,
137-
)
138-
candidates.setdefault(key, whl)
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)
139140

140141
if not candidates:
141142
return None

0 commit comments

Comments
 (0)