@@ -4,7 +4,7 @@ load("//python/private:version.bzl", "version")
44load (":parse_whl_name.bzl" , "parse_whl_name" )
55load (":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
0 commit comments