Skip to content

Commit 47e81a1

Browse files
committed
refactor: create group aliases
1 parent a7de3d4 commit 47e81a1

File tree

5 files changed

+256
-312
lines changed

5 files changed

+256
-312
lines changed

examples/bzlmod/MODULE.bazel.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

python/private/pypi/pkg_aliases.bzl

Lines changed: 85 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,66 @@
1616
1717
This is used in bzlmod and non-bzlmod setups."""
1818

19+
load("//python/private:text_util.bzl", "render")
1920
load(
2021
":labels.bzl",
2122
"DATA_LABEL",
2223
"DIST_INFO_LABEL",
23-
#"PY_LIBRARY_IMPL_LABEL",
24+
"PY_LIBRARY_IMPL_LABEL",
2425
"PY_LIBRARY_PUBLIC_LABEL",
25-
#"WHEEL_FILE_IMPL_LABEL",
26+
"WHEEL_FILE_IMPL_LABEL",
2627
"WHEEL_FILE_PUBLIC_LABEL",
2728
)
2829

30+
_NO_MATCH_ERROR_TEMPLATE = """\
31+
No matching wheel for current configuration's Python version.
32+
33+
The current build configuration's Python version doesn't match any of the Python
34+
wheels available for this wheel. This wheel supports the following Python
35+
configuration settings:
36+
{config_settings}
37+
38+
To determine the current configuration's Python version, run:
39+
`bazel config <config id>` (shown further below)
40+
and look for
41+
{rules_python}//python/config_settings:python_version
42+
43+
If the value is missing, then the "default" Python version is being used,
44+
which has a "null" version value and will not match version constraints.
45+
"""
46+
47+
def _no_match_error(actual):
48+
if type(actual) != type({}):
49+
return None
50+
51+
if "//conditions:default" in actual:
52+
return None
53+
54+
return _NO_MATCH_ERROR_TEMPLATE.format(
55+
config_settings = render.indent(
56+
"\n".join(sorted(actual.keys())),
57+
).lstrip(),
58+
rules_python = "rules_python",
59+
)
60+
2961
def pkg_aliases(
3062
*,
3163
name,
3264
actual,
33-
native = native):
65+
group_name = None,
66+
extra_aliases = None,
67+
native = native,
68+
select = select):
3469
"""Create aliases for an actual package.
3570
3671
Args:
3772
name: {type}`str` The name of the package.
38-
actual: {type}`dict[Label, str]` The config settings for the package
73+
actual: {type}`dict[Label, str] | str` The config settings for the package
3974
mapping to repositories.
40-
native: {type}`struct` used in unit tests
75+
group_name: {type}`str` The group name that the pkg belongs to.
76+
extra_aliases: {type}`list[str]` The extra aliases to be created.
77+
native: {type}`struct` used in unit tests.
78+
select: {type}`select` used in unit tests.
4179
"""
4280
_ = actual # buildifier: @unused
4381
native.alias(
@@ -46,25 +84,52 @@ def pkg_aliases(
4684
)
4785

4886
target_names = {
87+
PY_LIBRARY_PUBLIC_LABEL: PY_LIBRARY_IMPL_LABEL if group_name else PY_LIBRARY_PUBLIC_LABEL,
88+
WHEEL_FILE_PUBLIC_LABEL: WHEEL_FILE_IMPL_LABEL if group_name else WHEEL_FILE_PUBLIC_LABEL,
89+
DATA_LABEL: DATA_LABEL,
90+
DIST_INFO_LABEL: DIST_INFO_LABEL,
91+
} | {
4992
x: x
50-
for x in [
51-
PY_LIBRARY_PUBLIC_LABEL,
52-
WHEEL_FILE_PUBLIC_LABEL,
53-
DATA_LABEL,
54-
DIST_INFO_LABEL,
55-
]
93+
for x in extra_aliases or []
5694
}
95+
no_match_error = _no_match_error(actual)
5796

58-
if type(actual) == type({}):
59-
fail("TODO")
97+
for name, target_name in target_names.items():
98+
if type(actual) == type(""):
99+
_actual = "@{repo}//:{target_name}".format(
100+
repo = actual,
101+
target_name = name,
102+
)
103+
elif type(actual) == type({}):
104+
_actual = select(
105+
{
106+
config_setting: "@{repo}//:{target_name}".format(
107+
repo = repo,
108+
target_name = name,
109+
)
110+
for config_setting, repo in actual.items()
111+
},
112+
no_match_error = no_match_error,
113+
)
114+
else:
115+
fail("BUG: should have a dictionary or a string")
60116

61-
repo = actual
117+
kwargs = {}
118+
if target_name.startswith("_"):
119+
kwargs["visibility"] = ["//_groups:__subpackages__"]
62120

63-
for name, target_name in target_names.items():
64121
native.alias(
65-
name = name,
66-
actual = "@{repo}//:{target_name}".format(
67-
repo = repo,
68-
target_name = target_name,
69-
),
122+
name = target_name,
123+
actual = _actual,
124+
**kwargs
125+
)
126+
127+
if group_name:
128+
native.alias(
129+
name = PY_LIBRARY_PUBLIC_LABEL,
130+
actual = "//_groups:{}_pkg".format(group_name),
131+
)
132+
native.alias(
133+
name = WHEEL_FILE_PUBLIC_LABEL,
134+
actual = "//_groups:{}_whl".format(group_name),
70135
)

python/private/pypi/render_pkg_aliases.bzl

Lines changed: 10 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,6 @@ load(
2222
":generate_group_library_build_bazel.bzl",
2323
"generate_group_library_build_bazel",
2424
) # buildifier: disable=bzl-visibility
25-
load(
26-
":labels.bzl",
27-
"DATA_LABEL",
28-
"DIST_INFO_LABEL",
29-
"PY_LIBRARY_IMPL_LABEL",
30-
"PY_LIBRARY_PUBLIC_LABEL",
31-
"WHEEL_FILE_IMPL_LABEL",
32-
"WHEEL_FILE_PUBLIC_LABEL",
33-
)
3425
load(":parse_whl_name.bzl", "parse_whl_name")
3526
load(":whl_target_platforms.bzl", "whl_target_platforms")
3627

@@ -70,124 +61,38 @@ If the value is missing, then the "default" Python version is being used,
7061
which has a "null" version value and will not match version constraints.
7162
"""
7263

73-
def _render_whl_library_alias(
74-
*,
75-
name,
76-
aliases,
77-
target_name,
78-
**kwargs):
79-
"""Render an alias for common targets."""
80-
if len(aliases) == 1 and not aliases[0].version:
81-
return ""
82-
83-
# Create the alias repositories which contains different select
84-
# statements These select statements point to the different pip
85-
# whls that are based on a specific version of Python.
86-
selects = {}
87-
no_match_error = "_NO_MATCH_ERROR"
88-
for alias in sorted(aliases, key = lambda x: x.version):
89-
actual = "@{repo}//:{name}".format(repo = alias.repo, name = target_name)
90-
selects.setdefault(actual, []).append(alias.config_setting)
91-
92-
return render.alias(
93-
name = name,
94-
actual = render.select(
95-
{
96-
tuple(sorted(
97-
conditions,
98-
# Group `is_python` and other conditions for easier reading
99-
# when looking at the generated files.
100-
key = lambda condition: ("is_python" not in condition, condition),
101-
)): target
102-
for target, conditions in sorted(selects.items())
103-
},
104-
no_match_error = no_match_error,
105-
# This key_repr is used to render selects.with_or keys
106-
key_repr = lambda x: repr(x[0]) if len(x) == 1 else render.tuple(x),
107-
name = "selects.with_or",
108-
),
109-
**kwargs
110-
)
64+
def _render_pkg_aliases(name, actual, group_name, extra_aliases):
65+
if len(actual) == 1 and None in actual:
66+
actual = repr(actual.values()[0])
67+
else:
68+
actual = render.indent(render.dict(actual)).lstrip()
11169

112-
def _render_pkg_aliases(name, actual):
113-
actual = actual.values()[0] if len(actual) == 1 and None in actual else ":pkg"
11470
return """\
11571
pkg_aliases(
11672
name = "{name}",
11773
actual = {actual},
118-
)""".format(name = name, actual = repr(actual))
74+
group_name = {group_name},
75+
extra_aliases = {extra_aliases},
76+
)""".format(name = name, actual = actual, group_name = repr(group_name), extra_aliases = repr(extra_aliases))
11977

12078
def _render_common_aliases(*, name, aliases, extra_aliases = [], group_name = None):
12179
lines = [
12280
"""\
123-
load("@bazel_skylib//lib:selects.bzl", "selects")
12481
load("@rules_python//python/private/pypi:pkg_aliases.bzl", "pkg_aliases")""",
12582
"""package(default_visibility = ["//visibility:public"])""",
12683
]
12784

128-
config_settings = None
129-
if aliases:
130-
config_settings = sorted([v.config_setting for v in aliases if v.config_setting])
131-
132-
if config_settings:
133-
error_msg = NO_MATCH_ERROR_MESSAGE_TEMPLATE_V2.format(
134-
config_settings = render.indent(
135-
"\n".join(config_settings),
136-
).lstrip(),
137-
rules_python = "rules_python",
138-
)
139-
140-
lines.append("_NO_MATCH_ERROR = \"\"\"\\\n{error_msg}\"\"\"".format(
141-
error_msg = error_msg,
142-
))
143-
14485
lines.append(
14586
_render_pkg_aliases(
14687
name = name,
14788
actual = {
14889
a.config_setting: a.repo
14990
for a in aliases
15091
},
92+
group_name = group_name,
93+
extra_aliases = extra_aliases,
15194
),
15295
)
153-
lines.extend(
154-
[
155-
line
156-
for line in [
157-
_render_whl_library_alias(
158-
name = name,
159-
aliases = aliases,
160-
target_name = target_name,
161-
visibility = ["//_groups:__subpackages__"] if name.startswith("_") else None,
162-
)
163-
for target_name, name in (
164-
{
165-
PY_LIBRARY_PUBLIC_LABEL: PY_LIBRARY_IMPL_LABEL if group_name else PY_LIBRARY_PUBLIC_LABEL,
166-
WHEEL_FILE_PUBLIC_LABEL: WHEEL_FILE_IMPL_LABEL if group_name else WHEEL_FILE_PUBLIC_LABEL,
167-
DATA_LABEL: DATA_LABEL,
168-
DIST_INFO_LABEL: DIST_INFO_LABEL,
169-
} | {
170-
x: x
171-
for x in extra_aliases
172-
}
173-
).items()
174-
]
175-
if line
176-
],
177-
)
178-
if group_name:
179-
lines.extend(
180-
[
181-
render.alias(
182-
name = "pkg",
183-
actual = repr("//_groups:{}_pkg".format(group_name)),
184-
),
185-
render.alias(
186-
name = "whl",
187-
actual = repr("//_groups:{}_whl".format(group_name)),
188-
),
189-
],
190-
)
19196

19297
return "\n\n".join(lines)
19398

0 commit comments

Comments
 (0)