@@ -4,21 +4,55 @@ 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 _get_priority (* , tags , values , allow_wildcard = True ):
8+ keys = []
89 for priority , wp in enumerate (values ):
9- head , sep , tail = wp .partition ("*" )
10- if "*" in tail :
11- fail ("only a single '*' can be present in the matcher" )
12- if not allow_wildcard and sep :
13- fail ("'*' is not allowed in the matcher" )
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 )
21+
22+ if not keys :
23+ return None
24+
25+ return max (keys )
26+
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
36+
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" )
39+
40+ ver = version .parse (ver_str )
41+ if not version .is_compatible (py_version , ver ):
42+ continue
43+
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+ ))
1451
15- for p in tag .split ("." ):
16- if not sep and p == head :
17- return priority
18- elif sep and p .startswith (head ) and p .endswith (tail ):
19- return priority
52+ if not keys :
53+ return None
2054
21- return None
55+ return max ( keys )
2256
2357def select_whl (* , whls , python_version , platforms , whl_abi_tags , implementation_name = "cpython" , limit = 1 , logger = None ):
2458 """Select a whl that is the most suitable for the given platform.
@@ -56,26 +90,22 @@ def select_whl(*, whls, python_version, platforms, whl_abi_tags, implementation_
5690 ))
5791 continue
5892
59- if parsed .python_tag == "py2.py3" :
60- min_version = "2"
61- else :
62- min_version = parsed .python_tag [len (implementation ):]
63-
64- if len (min_version ) > 1 :
65- min_version = "{}.{}" .format (min_version [0 ], min_version [1 :])
66-
67- min_whl_py_version = version .parse (min_version , strict = True )
68- if not version .is_ge (py_version , min_whl_py_version ):
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 :
6999 if logger :
70- logger .debug (lambda : "Discarding the wheel because the min version supported based on the wheel ABI tag '{}' ({}) is not compatible with the provided target Python version '{}' " .format (
71- parsed .abi_tag ,
72- min_whl_py_version . string ,
100+ logger .debug (lambda : "The py_tag '{}' does not match implementation version: {} {} " .format (
101+ parsed .py_tag ,
102+ implementation ,
73103 py_version .string ,
74104 ))
75105 continue
76106
77107 abi_priority = _get_priority (
78- tag = parsed .abi_tag ,
108+ tags = parsed .abi_tag ,
79109 values = whl_abi_tags ,
80110 allow_wildcard = False ,
81111 )
@@ -86,8 +116,9 @@ def select_whl(*, whls, python_version, platforms, whl_abi_tags, implementation_
86116 whl_abi_tags ,
87117 ))
88118 continue
119+
89120 platform_priority = _get_priority (
90- tag = parsed .platform_tag ,
121+ tags = parsed .platform_tag ,
91122 values = platforms ,
92123 )
93124 if platform_priority == None :
@@ -100,10 +131,8 @@ def select_whl(*, whls, python_version, platforms, whl_abi_tags, implementation_
100131
101132 key = (
102133 # Ensure that we chose the highest compatible version
103- parsed . python_tag . startswith ( implementation ) ,
134+ py_priority ,
104135 platform_priority ,
105- # prefer abi_tags in this order
106- version .key (min_whl_py_version ),
107136 abi_priority ,
108137 )
109138 candidates .setdefault (key , whl )
0 commit comments