@@ -30,6 +30,7 @@ load(":hub_repository.bzl", "hub_repository", "whl_config_settings_to_json")
30
30
load (":parse_requirements.bzl" , "parse_requirements" )
31
31
load (":parse_whl_name.bzl" , "parse_whl_name" )
32
32
load (":pep508_env.bzl" , "env" )
33
+ load (":pep508_evaluate.bzl" , "evaluate" )
33
34
load (":pip_repository_attrs.bzl" , "ATTRS" )
34
35
load (":python_tag.bzl" , "python_tag" )
35
36
load (":requirements_files_by_platform.bzl" , "requirements_files_by_platform" )
@@ -80,21 +81,27 @@ def _platforms(*, python_version, minor_mapping, config):
80
81
for platform , values in config .platforms .items ():
81
82
# TODO @aignas 2025-07-07: this is probably doing the parsing of the version too
82
83
# many times.
83
- key = "{}{}{}.{}_ {}" .format (
84
+ abi = "{}{}{}.{}" .format (
84
85
python_tag (values .env ["implementation_name" ]),
85
86
python_version .release [0 ],
86
87
python_version .release [1 ],
87
88
python_version .release [2 ],
88
- platform ,
89
89
)
90
+ key = "{}_{}" .format (abi , platform )
91
+
92
+ env_ = env (
93
+ env = values .env ,
94
+ os = values .os_name ,
95
+ arch = values .arch_name ,
96
+ python_version = python_version .string ,
97
+ )
98
+
99
+ if values .marker and not evaluate (values .marker , env = env_ ):
100
+ continue
90
101
91
102
platforms [key ] = struct (
92
- env = env (
93
- env = values .env ,
94
- os = values .os_name ,
95
- arch = values .arch_name ,
96
- python_version = python_version .string ,
97
- ),
103
+ env = env_ ,
104
+ triple = "{}_{}_{}" .format (abi , values .os_name , values .arch_name ),
98
105
whl_abi_tags = [
99
106
v .format (
100
107
major = python_version .release [0 ],
@@ -203,17 +210,19 @@ def _create_whl_repos(
203
210
whl_group_mapping = {}
204
211
requirement_cycles = {}
205
212
213
+ platforms = _platforms (
214
+ python_version = pip_attr .python_version ,
215
+ minor_mapping = minor_mapping ,
216
+ config = config ,
217
+ )
218
+
206
219
if evaluate_markers :
207
220
# This is most likely unit tests
208
221
pass
209
222
elif config .enable_pipstar :
210
223
evaluate_markers = lambda _ , requirements : evaluate_markers_star (
211
224
requirements = requirements ,
212
- platforms = _platforms (
213
- python_version = pip_attr .python_version ,
214
- minor_mapping = minor_mapping ,
215
- config = config ,
216
- ),
225
+ platforms = platforms ,
217
226
)
218
227
else :
219
228
# NOTE @aignas 2024-08-02: , we will execute any interpreter that we find either
@@ -232,7 +241,14 @@ def _create_whl_repos(
232
241
# spin up a Python interpreter.
233
242
evaluate_markers = lambda module_ctx , requirements : evaluate_markers_py (
234
243
module_ctx ,
235
- requirements = requirements ,
244
+ requirements = {
245
+ k : {
246
+ # TODO @aignas 2025-07-06: should we leave this as is?
247
+ p : platforms [p ].triple
248
+ for p in plats
249
+ }
250
+ for k , plats in requirements .items ()
251
+ },
236
252
python_interpreter = pip_attr .python_interpreter ,
237
253
python_interpreter_target = python_interpreter_target ,
238
254
srcs = pip_attr ._evaluate_markers_srcs ,
@@ -248,18 +264,14 @@ def _create_whl_repos(
248
264
requirements_osx = pip_attr .requirements_darwin ,
249
265
requirements_windows = pip_attr .requirements_windows ,
250
266
extra_pip_args = pip_attr .extra_pip_args ,
251
- platforms = sorted (config . platforms ), # here we only need keys
267
+ platforms = sorted (platforms ), # here we only need keys
252
268
python_version = full_version (
253
269
version = pip_attr .python_version ,
254
270
minor_mapping = minor_mapping ,
255
271
),
256
272
logger = logger ,
257
273
),
258
- platforms = _platforms (
259
- python_version = pip_attr .python_version ,
260
- minor_mapping = minor_mapping ,
261
- config = config ,
262
- ),
274
+ platforms = platforms ,
263
275
extra_pip_args = pip_attr .extra_pip_args ,
264
276
get_index_urls = get_index_urls ,
265
277
evaluate_markers = evaluate_markers ,
@@ -346,6 +358,16 @@ def _create_whl_repos(
346
358
))
347
359
348
360
whl_libraries [repo_name ] = repo .args
361
+ if "experimental_target_platforms" in repo .args :
362
+ whl_libraries [repo_name ] |= {
363
+ "experimental_target_platforms" : sorted ({
364
+ # TODO @aignas 2025-07-07: this should be solved in a better way
365
+ platforms [candidate ].triple .partition ("_" )[- 1 ]: None
366
+ for p in repo .args ["experimental_target_platforms" ]
367
+ for candidate in platforms
368
+ if candidate .endswith (p )
369
+ }),
370
+ }
349
371
whl_map .setdefault (whl .name , {})[repo .config_setting ] = repo_name
350
372
351
373
return struct (
@@ -434,14 +456,15 @@ def _configure(
434
456
arch_name ,
435
457
config_settings ,
436
458
env = {},
459
+ marker ,
437
460
whl_abi_tags ,
438
461
whl_platform_tags ,
439
462
override = False ):
440
463
"""Set the value in the config if the value is provided"""
441
464
config .setdefault ("platforms" , {})
442
465
443
466
if platform and (
444
- os_name or arch_name or config_settings or whl_abi_tags or whl_platform_tags or env
467
+ os_name or arch_name or config_settings or whl_abi_tags or whl_platform_tags or env or marker
445
468
):
446
469
if not override and config ["platforms" ].get (platform ):
447
470
return
@@ -455,6 +478,7 @@ def _configure(
455
478
"arch_name" : arch_name ,
456
479
"config_settings" : config_settings ,
457
480
"env" : env ,
481
+ "marker" : marker ,
458
482
"name" : platform .replace ("-" , "_" ).lower (),
459
483
"os_name" : os_name ,
460
484
"whl_abi_tags" : whl_abi_tags ,
@@ -470,7 +494,7 @@ def _configure(
470
494
else :
471
495
config ["platforms" ].pop (platform )
472
496
473
- def _plat (* , name , arch_name , os_name , config_settings = [], env = {}, whl_abi_tags = [], whl_platform_tags = []):
497
+ def _plat (* , name , arch_name , os_name , config_settings = [], env = {}, marker = "" , whl_abi_tags = [], whl_platform_tags = []):
474
498
# NOTE @aignas 2025-07-08: the least preferred is the first item in the list
475
499
if "any" not in whl_platform_tags :
476
500
# the lowest priority one needs to be the first one
@@ -490,6 +514,7 @@ def _plat(*, name, arch_name, os_name, config_settings = [], env = {}, whl_abi_t
490
514
# defaults for env
491
515
"implementation_name" : "cpython" ,
492
516
} | env ,
517
+ marker = marker ,
493
518
whl_abi_tags = whl_abi_tags ,
494
519
whl_platform_tags = whl_platform_tags ,
495
520
)
@@ -524,6 +549,7 @@ def build_config(
524
549
config_settings = tag .config_settings ,
525
550
env = tag .env ,
526
551
os_name = tag .os_name ,
552
+ marker = tag .marker ,
527
553
platform = platform ,
528
554
override = mod .is_root ,
529
555
whl_abi_tags = tag .whl_abi_tags ,
@@ -533,8 +559,6 @@ def build_config(
533
559
# attribute.
534
560
# * for index/downloader config. This includes all of those attributes for
535
561
# overrides, etc. Index overrides per platform could be also used here.
536
- # * for whl selection - selecting preferences of which `platform_tag`s we should use
537
- # for what. We could also model the `cp313t` freethreaded as separate platforms.
538
562
)
539
563
540
564
return struct (
@@ -918,6 +942,12 @@ Supported keys:
918
942
::::{note}
919
943
This is only used if the {envvar}`RULES_PYTHON_ENABLE_PIPSTAR` is enabled.
920
944
::::
945
+ """ ,
946
+ ),
947
+ "marker" : attr .string (
948
+ doc = """\
949
+ A marker which will be evaluated to disable the target platform for certain python versions. This
950
+ is especially useful when defining freethreaded platform variants.
921
951
""" ,
922
952
),
923
953
# The values for PEP508 env marker evaluation during the lock file parsing
0 commit comments