Skip to content

Commit f2e68cf

Browse files
committed
feat(pypi): incrementally build platform configuration
Before this PR the configuration for platforms would be built non-incrementally, making it harder for users to override particular attributes of the already configured ones. With this PR the new features introduced in bazel-contrib#3058 will be easier to override. Work towards bazel-contrib#2747
1 parent afa7686 commit f2e68cf

File tree

2 files changed

+128
-36
lines changed

2 files changed

+128
-36
lines changed

python/private/pypi/extension.bzl

Lines changed: 76 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -380,24 +380,90 @@ def _whl_repo(*, src, whl_library_args, is_multiple_versions, download_only, net
380380
def _configure(config, *, platform, os_name, arch_name, config_settings, env = {}, override = False):
381381
"""Set the value in the config if the value is provided"""
382382
config.setdefault("platforms", {})
383-
if platform:
383+
if platform and (os_name or arch_name or config_settings or env):
384384
if not override and config.get("platforms", {}).get(platform):
385385
return
386386

387387
for key in env:
388388
if key not in _SUPPORTED_PEP508_KEYS:
389389
fail("Unsupported key in the PEP508 environment: {}".format(key))
390390

391-
config["platforms"][platform] = struct(
392-
name = platform.replace("-", "_").lower(),
393-
os_name = os_name,
394-
arch_name = arch_name,
395-
config_settings = config_settings,
396-
env = env,
397-
)
391+
config["platforms"].setdefault(platform, {})
392+
for key, value in {
393+
"arch_name": arch_name,
394+
"config_settings": config_settings,
395+
"env": env,
396+
"name": platform.replace("-", "_").lower(),
397+
"os_name": os_name,
398+
}.items():
399+
if not value:
400+
continue
401+
402+
if not override and config.get(key):
403+
continue
404+
405+
config["platforms"][platform][key] = value
398406
else:
399407
config["platforms"].pop(platform)
400408

409+
def _plat(*, name, arch_name, os_name, config_settings = [], env = {}):
410+
return struct(
411+
name = name,
412+
arch_name = arch_name,
413+
os_name = os_name,
414+
config_settings = config_settings,
415+
env = env,
416+
)
417+
418+
def build_config(
419+
*,
420+
module_ctx,
421+
enable_pipstar):
422+
"""Parse 'configure' and 'default' extension tags
423+
424+
Args:
425+
module_ctx: {type}`module_ctx` module context.
426+
enable_pipstar: {type}`bool` a flag to enable dropping Python dependency for
427+
evaluation of the extension.
428+
429+
Returns:
430+
A struct with the configuration.
431+
"""
432+
defaults = {
433+
"platforms": {},
434+
}
435+
for mod in module_ctx.modules:
436+
if not (mod.is_root or mod.name == "rules_python"):
437+
continue
438+
439+
platform = None
440+
for tag in mod.tags.default:
441+
platform = tag.platform or platform
442+
_configure(
443+
defaults,
444+
arch_name = tag.arch_name,
445+
config_settings = tag.config_settings,
446+
env = tag.env,
447+
os_name = tag.os_name,
448+
platform = platform,
449+
override = mod.is_root,
450+
# TODO @aignas 2025-05-19: add more attr groups:
451+
# * for AUTH - the default `netrc` usage could be configured through a common
452+
# attribute.
453+
# * for index/downloader config. This includes all of those attributes for
454+
# overrides, etc. Index overrides per platform could be also used here.
455+
# * for whl selection - selecting preferences of which `platform_tag`s we should use
456+
# for what. We could also model the `cp313t` freethreaded as separate platforms.
457+
)
458+
459+
return struct(
460+
platforms = {
461+
name: _plat(**values)
462+
for name, values in defaults["platforms"].items()
463+
},
464+
enable_pipstar = enable_pipstar,
465+
)
466+
401467
def parse_modules(
402468
module_ctx,
403469
_fail = fail,
@@ -448,33 +514,7 @@ You cannot use both the additive_build_content and additive_build_content_file a
448514
srcs_exclude_glob = whl_mod.srcs_exclude_glob,
449515
)
450516

451-
defaults = {
452-
"enable_pipstar": enable_pipstar,
453-
"platforms": {},
454-
}
455-
for mod in module_ctx.modules:
456-
if not (mod.is_root or mod.name == "rules_python"):
457-
continue
458-
459-
for tag in mod.tags.default:
460-
_configure(
461-
defaults,
462-
arch_name = tag.arch_name,
463-
config_settings = tag.config_settings,
464-
env = tag.env,
465-
os_name = tag.os_name,
466-
platform = tag.platform,
467-
override = mod.is_root,
468-
# TODO @aignas 2025-05-19: add more attr groups:
469-
# * for AUTH - the default `netrc` usage could be configured through a common
470-
# attribute.
471-
# * for index/downloader config. This includes all of those attributes for
472-
# overrides, etc. Index overrides per platform could be also used here.
473-
# * for whl selection - selecting preferences of which `platform_tag`s we should use
474-
# for what. We could also model the `cp313t` freethreaded as separate platforms.
475-
)
476-
477-
config = struct(**defaults)
517+
config = build_config(module_ctx = module_ctx, enable_pipstar = enable_pipstar)
478518

479519
# TODO @aignas 2025-06-03: Merge override API with the builder?
480520
_overriden_whl_set = {}
@@ -651,6 +691,7 @@ You cannot use both the additive_build_content and additive_build_content_file a
651691
k: dict(sorted(args.items()))
652692
for k, args in sorted(whl_libraries.items())
653693
},
694+
config = config,
654695
)
655696

656697
def _pip_impl(module_ctx):

tests/pypi/extension/extension_tests.bzl

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
load("@rules_testing//lib:test_suite.bzl", "test_suite")
1818
load("@rules_testing//lib:truth.bzl", "subjects")
19-
load("//python/private/pypi:extension.bzl", "parse_modules") # buildifier: disable=bzl-visibility
19+
load("//python/private/pypi:extension.bzl", "build_config", "parse_modules") # buildifier: disable=bzl-visibility
2020
load("//python/private/pypi:parse_simpleapi_html.bzl", "parse_simpleapi_html") # buildifier: disable=bzl-visibility
2121
load("//python/private/pypi:whl_config_setting.bzl", "whl_config_setting") # buildifier: disable=bzl-visibility
2222

@@ -92,6 +92,18 @@ def _parse_modules(env, enable_pipstar = 0, **kwargs):
9292
),
9393
)
9494

95+
def _build_config(env, enable_pipstar = 0, **kwargs):
96+
return env.expect.that_struct(
97+
build_config(
98+
enable_pipstar = enable_pipstar,
99+
**kwargs
100+
),
101+
attrs = dict(
102+
platforms = subjects.dict,
103+
enable_pipstar = subjects.bool,
104+
),
105+
)
106+
95107
def _default(
96108
arch_name = None,
97109
config_settings = None,
@@ -1108,6 +1120,45 @@ optimum[onnxruntime-gpu]==1.17.1 ; sys_platform == 'linux'
11081120

11091121
_tests.append(_test_pipstar_platforms)
11101122

1123+
def _test_build_pipstar_platform(env):
1124+
config = _build_config(
1125+
env,
1126+
module_ctx = _mock_mctx(
1127+
_mod(
1128+
name = "rules_python",
1129+
default = [
1130+
_default(
1131+
platform = "myplat",
1132+
os_name = "linux",
1133+
arch_name = "x86_64",
1134+
),
1135+
_default(
1136+
config_settings = [
1137+
"@platforms//os:linux",
1138+
"@platforms//cpu:x86_64",
1139+
],
1140+
),
1141+
],
1142+
),
1143+
),
1144+
enable_pipstar = True,
1145+
)
1146+
config.enable_pipstar().equals(True)
1147+
config.platforms().contains_exactly({
1148+
"myplat": struct(
1149+
name = "myplat",
1150+
os_name = "linux",
1151+
arch_name = "x86_64",
1152+
config_settings = [
1153+
"@platforms//os:linux",
1154+
"@platforms//cpu:x86_64",
1155+
],
1156+
env = {},
1157+
),
1158+
})
1159+
1160+
_tests.append(_test_build_pipstar_platform)
1161+
11111162
def extension_test_suite(name):
11121163
"""Create the test suite.
11131164

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy