Skip to content

Commit b8d6fa3

Browse files
aignasrickeylev
andauthored
feat(pypi): pip.defaults API for customizing repo selection 2/n (bazel-contrib#2988)
WIP: stacked on bazel-contrib#2987 This is adding `constraint_values` attribute to `pip.configure` and is threading it all the way down to the generation of `BUILD.bazel` file of for config settings used in the hub repository. Out of scope: - Passing `flag_values` or target settings. I am torn about it - doing it in this PR would flesh out the design more, but at the same time it might become harder to review. - `whl_target_platforms` and `select_whls` is still unchanged, not sure if it is related to this attribute addition. Work towards bazel-contrib#2747 Work towards bazel-contrib#2548 Work towards bazel-contrib#260 --------- Co-authored-by: Richard Levasseur <[email protected]>
1 parent 5b1db07 commit b8d6fa3

File tree

9 files changed

+140
-42
lines changed

9 files changed

+140
-42
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ END_UNRELEASED_TEMPLATE
6464
### Added
6565
* (pypi) To configure the environment for `requirements.txt` evaluation, use the newly added
6666
developer preview of the `pip.default` tag class. Only `rules_python` and root modules can use
67-
this feature.
67+
this feature. You can also configure `constraint_values` using `pip.default`.
6868

6969
{#v0-0-0-removed}
7070
### Removed

python/private/pypi/config_settings.bzl

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ def config_settings(
111111
glibc_versions = [],
112112
muslc_versions = [],
113113
osx_versions = [],
114-
target_platforms = [],
115114
name = None,
115+
platform_constraint_values = {},
116116
**kwargs):
117117
"""Generate all of the pip config settings.
118118
@@ -126,31 +126,28 @@ def config_settings(
126126
configure config settings for.
127127
osx_versions (list[str]): The list of OSX OS versions to configure
128128
config settings for.
129-
target_platforms (list[str]): The list of "{os}_{cpu}" for deriving
130-
constraint values for each condition.
129+
platform_constraint_values: {type}`dict[str, list[str]]` the constraint
130+
values to use instead of the default ones. Key are platform names
131+
(a human-friendly platform string). Values are lists of
132+
`constraint_value` label strings.
131133
**kwargs: Other args passed to the underlying implementations, such as
132134
{obj}`native`.
133135
"""
134136

135137
glibc_versions = [""] + glibc_versions
136138
muslc_versions = [""] + muslc_versions
137139
osx_versions = [""] + osx_versions
138-
target_platforms = [("", ""), ("osx", "universal2")] + [
139-
t.split("_", 1)
140-
for t in target_platforms
141-
]
140+
target_platforms = {
141+
"": [],
142+
# TODO @aignas 2025-06-15: allowing universal2 and platform specific wheels in one
143+
# closure is making things maybe a little bit too complicated.
144+
"osx_universal2": ["@platforms//os:osx"],
145+
} | platform_constraint_values
142146

143147
for python_version in python_versions:
144-
for os, cpu in target_platforms:
145-
constraint_values = []
146-
suffix = ""
147-
if os:
148-
constraint_values.append("@platforms//os:" + os)
149-
suffix += "_" + os
150-
if cpu:
151-
suffix += "_" + cpu
152-
if cpu != "universal2":
153-
constraint_values.append("@platforms//cpu:" + cpu)
148+
for platform_name, constraint_values in target_platforms.items():
149+
suffix = "_{}".format(platform_name) if platform_name else ""
150+
os, _, cpu = platform_name.partition("_")
154151

155152
_dist_config_settings(
156153
suffix = suffix,

python/private/pypi/extension.bzl

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ def _whl_repo(*, src, whl_library_args, is_multiple_versions, download_only, net
372372
),
373373
)
374374

375-
def _configure(config, *, platform, os_name, arch_name, override = False, env = {}):
375+
def _configure(config, *, platform, os_name, arch_name, constraint_values, env = {}, override = False):
376376
"""Set the value in the config if the value is provided"""
377377
config.setdefault("platforms", {})
378378
if platform:
@@ -387,6 +387,7 @@ def _configure(config, *, platform, os_name, arch_name, override = False, env =
387387
name = platform.replace("-", "_").lower(),
388388
os_name = os_name,
389389
arch_name = arch_name,
390+
constraint_values = constraint_values,
390391
env = env,
391392
)
392393
else:
@@ -413,6 +414,10 @@ def _create_config(defaults):
413414
arch_name = cpu,
414415
os_name = "linux",
415416
platform = "linux_{}".format(cpu),
417+
constraint_values = [
418+
"@platforms//os:linux",
419+
"@platforms//cpu:{}".format(cpu),
420+
],
416421
env = {"platform_version": "0"},
417422
)
418423
for cpu in [
@@ -424,17 +429,25 @@ def _create_config(defaults):
424429
arch_name = cpu,
425430
# We choose the oldest non-EOL version at the time when we release `rules_python`.
426431
# See https://endoflife.date/macos
427-
env = {"platform_version": "14.0"},
428432
os_name = "osx",
429433
platform = "osx_{}".format(cpu),
434+
constraint_values = [
435+
"@platforms//os:osx",
436+
"@platforms//cpu:{}".format(cpu),
437+
],
438+
env = {"platform_version": "14.0"},
430439
)
431440

432441
_configure(
433442
defaults,
434443
arch_name = "x86_64",
435-
env = {"platform_version": "0"},
436444
os_name = "windows",
437445
platform = "windows_x86_64",
446+
constraint_values = [
447+
"@platforms//os:windows",
448+
"@platforms//cpu:x86_64",
449+
],
450+
env = {"platform_version": "0"},
438451
)
439452
return struct(**defaults)
440453

@@ -500,6 +513,7 @@ You cannot use both the additive_build_content and additive_build_content_file a
500513
_configure(
501514
defaults,
502515
arch_name = tag.arch_name,
516+
constraint_values = tag.constraint_values,
503517
env = tag.env,
504518
os_name = tag.os_name,
505519
platform = tag.platform,
@@ -679,6 +693,13 @@ You cannot use both the additive_build_content and additive_build_content_file a
679693
}
680694
for hub_name, extra_whl_aliases in extra_aliases.items()
681695
},
696+
platform_constraint_values = {
697+
hub_name: {
698+
platform_name: sorted([str(Label(cv)) for cv in p.constraint_values])
699+
for platform_name, p in config.platforms.items()
700+
}
701+
for hub_name in hub_whl_map
702+
},
682703
whl_libraries = {
683704
k: dict(sorted(args.items()))
684705
for k, args in sorted(whl_libraries.items())
@@ -769,6 +790,7 @@ def _pip_impl(module_ctx):
769790
for key, values in whl_map.items()
770791
},
771792
packages = mods.exposed_packages.get(hub_name, []),
793+
platform_constraint_values = mods.platform_constraint_values.get(hub_name, {}),
772794
groups = mods.hub_group_map.get(hub_name),
773795
)
774796

@@ -788,6 +810,12 @@ The CPU architecture name to be used.
788810
:::{note}
789811
Either this or {attr}`env` `platform_machine` key should be specified.
790812
:::
813+
""",
814+
),
815+
"constraint_values": attr.label_list(
816+
mandatory = True,
817+
doc = """\
818+
The constraint_values to use in select statements.
791819
""",
792820
),
793821
"os_name": attr.string(

python/private/pypi/hub_repository.bzl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def _impl(rctx):
3434
},
3535
extra_hub_aliases = rctx.attr.extra_hub_aliases,
3636
requirement_cycles = rctx.attr.groups,
37+
platform_constraint_values = rctx.attr.platform_constraint_values,
3738
)
3839
for path, contents in aliases.items():
3940
rctx.file(path, contents)
@@ -83,6 +84,10 @@ hub_repository = repository_rule(
8384
The list of packages that will be exposed via all_*requirements macros. Defaults to whl_map keys.
8485
""",
8586
),
87+
"platform_constraint_values": attr.string_list_dict(
88+
doc = "The constraint values for each platform name. The values are string canonical string Label representations",
89+
mandatory = False,
90+
),
8691
"repo_name": attr.string(
8792
mandatory = True,
8893
doc = "The apparent name of the repo. This is needed because in bzlmod, the name attribute becomes the canonical name.",

python/private/pypi/render_pkg_aliases.bzl

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,14 @@ def _major_minor_versions(python_versions):
155155
# Use a dict as a simple set
156156
return sorted({_major_minor(v): None for v in python_versions})
157157

158-
def render_multiplatform_pkg_aliases(*, aliases, **kwargs):
158+
def render_multiplatform_pkg_aliases(*, aliases, platform_constraint_values = {}, **kwargs):
159159
"""Render the multi-platform pkg aliases.
160160
161161
Args:
162162
aliases: dict[str, list(whl_config_setting)] A list of aliases that will be
163163
transformed from ones having `filename` to ones having `config_setting`.
164+
platform_constraint_values: {type}`dict[str, list[str]]` contains all of the
165+
target platforms and their appropriate `constraint_values`.
164166
**kwargs: extra arguments passed to render_pkg_aliases.
165167
166168
Returns:
@@ -187,18 +189,22 @@ def render_multiplatform_pkg_aliases(*, aliases, **kwargs):
187189
muslc_versions = flag_versions.get("muslc_versions", []),
188190
osx_versions = flag_versions.get("osx_versions", []),
189191
python_versions = _major_minor_versions(flag_versions.get("python_versions", [])),
190-
target_platforms = flag_versions.get("target_platforms", []),
192+
platform_constraint_values = platform_constraint_values,
191193
visibility = ["//:__subpackages__"],
192194
)
193195
return contents
194196

195-
def _render_config_settings(**kwargs):
197+
def _render_config_settings(platform_constraint_values, **kwargs):
196198
return """\
197199
load("@rules_python//python/private/pypi:config_settings.bzl", "config_settings")
198200
199201
{}""".format(render.call(
200202
"config_settings",
201203
name = repr("config_settings"),
204+
platform_constraint_values = render.dict(
205+
platform_constraint_values,
206+
value_repr = render.list,
207+
),
202208
**_repr_dict(value_repr = render.list, **kwargs)
203209
))
204210

tests/pypi/config_settings/config_settings_tests.bzl

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -657,13 +657,34 @@ def config_settings_test_suite(name): # buildifier: disable=function-docstring
657657
glibc_versions = [(2, 14), (2, 17)],
658658
muslc_versions = [(1, 1)],
659659
osx_versions = [(10, 9), (11, 0)],
660-
target_platforms = [
661-
"windows_x86_64",
662-
"windows_aarch64",
663-
"linux_x86_64",
664-
"linux_ppc",
665-
"linux_aarch64",
666-
"osx_x86_64",
667-
"osx_aarch64",
668-
],
660+
platform_constraint_values = {
661+
"linux_aarch64": [
662+
"@platforms//cpu:aarch64",
663+
"@platforms//os:linux",
664+
],
665+
"linux_ppc": [
666+
"@platforms//cpu:ppc",
667+
"@platforms//os:linux",
668+
],
669+
"linux_x86_64": [
670+
"@platforms//cpu:x86_64",
671+
"@platforms//os:linux",
672+
],
673+
"osx_aarch64": [
674+
"@platforms//cpu:aarch64",
675+
"@platforms//os:osx",
676+
],
677+
"osx_x86_64": [
678+
"@platforms//cpu:x86_64",
679+
"@platforms//os:osx",
680+
],
681+
"windows_aarch64": [
682+
"@platforms//cpu:aarch64",
683+
"@platforms//os:windows",
684+
],
685+
"windows_x86_64": [
686+
"@platforms//cpu:x86_64",
687+
"@platforms//os:windows",
688+
],
689+
},
669690
)

tests/pypi/extension/extension_tests.bzl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,10 @@ def _test_pipstar_platforms(env):
10511051
default = [
10521052
_default(
10531053
platform = "{}_{}".format(os, cpu),
1054+
constraint_values = [
1055+
"@platforms//os:{}".format(os),
1056+
"@platforms//cpu:{}".format(cpu),
1057+
],
10541058
)
10551059
for os, cpu in [
10561060
("linux", "x86_64"),

tests/pypi/pkg_aliases/pkg_aliases_test.bzl

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -419,10 +419,16 @@ def _test_config_settings_exist_legacy(env):
419419
alias = _mock_alias(available_config_settings),
420420
config_setting = _mock_config_setting(available_config_settings),
421421
),
422-
target_platforms = [
423-
"linux_aarch64",
424-
"linux_x86_64",
425-
],
422+
platform_constraint_values = {
423+
"linux_aarch64": [
424+
"@platforms//cpu:aarch64",
425+
"@platforms//os:linux",
426+
],
427+
"linux_x86_64": [
428+
"@platforms//cpu:x86_64",
429+
"@platforms//os:linux",
430+
],
431+
},
426432
)
427433

428434
got_aliases = multiplatform_whl_aliases(
@@ -448,19 +454,39 @@ def _test_config_settings_exist(env):
448454
"any": {},
449455
"macosx_11_0_arm64": {
450456
"osx_versions": [(11, 0)],
451-
"target_platforms": ["osx_aarch64"],
457+
"platform_constraint_values": {
458+
"osx_aarch64": [
459+
"@platforms//cpu:aarch64",
460+
"@platforms//os:osx",
461+
],
462+
},
452463
},
453464
"manylinux_2_17_x86_64": {
454465
"glibc_versions": [(2, 17), (2, 18)],
455-
"target_platforms": ["linux_x86_64"],
466+
"platform_constraint_values": {
467+
"linux_x86_64": [
468+
"@platforms//cpu:x86_64",
469+
"@platforms//os:linux",
470+
],
471+
},
456472
},
457473
"manylinux_2_18_x86_64": {
458474
"glibc_versions": [(2, 17), (2, 18)],
459-
"target_platforms": ["linux_x86_64"],
475+
"platform_constraint_values": {
476+
"linux_x86_64": [
477+
"@platforms//cpu:x86_64",
478+
"@platforms//os:linux",
479+
],
480+
},
460481
},
461482
"musllinux_1_1_aarch64": {
462483
"muslc_versions": [(1, 2), (1, 1), (1, 0)],
463-
"target_platforms": ["linux_aarch64"],
484+
"platform_constraint_values": {
485+
"linux_aarch64": [
486+
"@platforms//cpu:aarch64",
487+
"@platforms//os:linux",
488+
],
489+
},
464490
},
465491
}.items():
466492
aliases = {

tests/pypi/render_pkg_aliases/render_pkg_aliases_test.bzl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ def _test_bzlmod_aliases(env):
9393
},
9494
},
9595
extra_hub_aliases = {"bar_baz": ["foo"]},
96+
platform_constraint_values = {
97+
"linux_x86_64": [
98+
"@platforms//os:linux",
99+
"@platforms//cpu:x86_64",
100+
],
101+
},
96102
)
97103

98104
want_key = "bar_baz/BUILD.bazel"
@@ -130,8 +136,13 @@ load("@rules_python//python/private/pypi:config_settings.bzl", "config_settings"
130136
131137
config_settings(
132138
name = "config_settings",
139+
platform_constraint_values = {
140+
"linux_x86_64": [
141+
"@platforms//os:linux",
142+
"@platforms//cpu:x86_64",
143+
],
144+
},
133145
python_versions = ["3.2"],
134-
target_platforms = ["linux_x86_64"],
135146
visibility = ["//:__subpackages__"],
136147
)""",
137148
)

0 commit comments

Comments
 (0)