@@ -4,7 +4,7 @@ load("//python/private:version.bzl", "version")
4
4
load (":parse_whl_name.bzl" , "parse_whl_name" )
5
5
load (":python_tag.bzl" , "PY_TAG_GENERIC" , "python_tag" )
6
6
7
- def _get_priority (* , tag , values , allow_wildcard = True ):
7
+ def _priority_by_values (* , tag , values , allow_wildcard = True ):
8
8
keys = []
9
9
for priority , wp in enumerate (values ):
10
10
head , sep , tail = wp .partition ("*" )
@@ -18,12 +18,9 @@ def _get_priority(*, tag, values, allow_wildcard = True):
18
18
elif sep and tag .startswith (head ) and tag .endswith (tail ):
19
19
keys .append (priority )
20
20
21
- if not keys :
22
- return None
23
-
24
- return max (keys )
21
+ return max (keys ) if keys else None
25
22
26
- def _get_py_priority (* , tag , implementation , py_version ):
23
+ def _priority_by_version (* , tag , implementation , py_version ):
27
24
if tag .startswith (PY_TAG_GENERIC ):
28
25
ver_str = tag [len (PY_TAG_GENERIC ):]
29
26
elif tag .startswith (implementation ):
@@ -43,39 +40,83 @@ def _get_py_priority(*, tag, implementation, py_version):
43
40
version .key (ver ),
44
41
)
45
42
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
+
47
59
ret = {}
48
60
for whl in whls :
49
61
parsed = parse_whl_name (whl .filename )
62
+ priority = None
50
63
51
64
# 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
+ ))
60
73
continue
61
74
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 ,
67
80
)
68
81
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
+ ))
70
88
continue
71
89
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 ,
76
95
)
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
77
118
78
- ret [struct ( py = py , abi = abi , platform = platform ) ] = whl
119
+ ret [priority ] = whl
79
120
80
121
return ret
81
122
@@ -102,41 +143,14 @@ def select_whl(*, whls, python_version, platforms, whl_abi_tags, implementation_
102
143
candidates = {}
103
144
implementation = python_tag (implementation_name )
104
145
105
- for priority , whl in _tag_sets (
146
+ candidates = _candidates_by_priority (
106
147
whls = whls ,
107
148
implementation = implementation ,
108
149
py_version = py_version ,
109
150
whl_abi_tags = whl_abi_tags ,
110
151
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
+ )
140
154
141
155
if not candidates :
142
156
return None
0 commit comments