refactor: use bazel-skylib for creating hub repo aliases (#1855)
With this PR the code becomes more maintainable and easier to inspect.
Since bazel-skylib is already a dependency of rules_python, this is
a backwards compatible change.
Skipping the CHANGELOG notes because it should not be an externally
visible change.
Work towards #735.
diff --git a/python/private/render_pkg_aliases.bzl b/python/private/render_pkg_aliases.bzl
index e38f133..5851baf 100644
--- a/python/private/render_pkg_aliases.bzl
+++ b/python/private/render_pkg_aliases.bzl
@@ -42,7 +42,8 @@
*,
name,
default_version,
- aliases):
+ aliases,
+ **kwargs):
"""Render an alias for common targets."""
if len(aliases) == 1 and not aliases[0].version:
alias = aliases[0]
@@ -56,27 +57,36 @@
# whls that are based on a specific version of Python.
selects = {}
no_match_error = "_NO_MATCH_ERROR"
- default = None
for alias in sorted(aliases, key = lambda x: x.version):
actual = "@{repo}//:{name}".format(repo = alias.repo, name = name)
- selects[alias.config_setting] = actual
+ selects.setdefault(actual, []).append(alias.config_setting)
if alias.version == default_version:
- default = actual
+ selects[actual].append("//conditions:default")
no_match_error = None
- if default:
- selects["//conditions:default"] = default
-
return render.alias(
name = name,
actual = render.select(
- selects,
+ {
+ tuple(sorted(
+ conditions,
+ # Group `is_python` and other conditions for easier reading
+ # when looking at the generated files.
+ key = lambda condition: ("is_python" not in condition, condition),
+ )): target
+ for target, conditions in sorted(selects.items())
+ },
no_match_error = no_match_error,
+ # This key_repr is used to render selects.with_or keys
+ key_repr = lambda x: repr(x[0]) if len(x) == 1 else render.tuple(x),
+ name = "selects.with_or",
),
+ **kwargs
)
def _render_common_aliases(*, name, aliases, default_version = None):
lines = [
+ """load("@bazel_skylib//lib:selects.bzl", "selects")""",
"""package(default_visibility = ["//visibility:public"])""",
]
diff --git a/python/private/text_util.bzl b/python/private/text_util.bzl
index 78f62be..dade9cb 100644
--- a/python/private/text_util.bzl
+++ b/python/private/text_util.bzl
@@ -35,18 +35,18 @@
")",
])
-def _render_dict(d, *, value_repr = repr):
+def _render_dict(d, *, key_repr = repr, value_repr = repr):
return "\n".join([
"{",
_indent("\n".join([
- "{}: {},".format(repr(k), value_repr(v))
+ "{}: {},".format(key_repr(k), value_repr(v))
for k, v in d.items()
])),
"}",
])
-def _render_select(selects, *, no_match_error = None, value_repr = repr):
- dict_str = _render_dict(selects, value_repr = value_repr) + ","
+def _render_select(selects, *, no_match_error = None, key_repr = repr, value_repr = repr, name = "select"):
+ dict_str = _render_dict(selects, key_repr = key_repr, value_repr = value_repr) + ","
if no_match_error:
args = "\n".join([
@@ -62,7 +62,7 @@
"",
])
- return "select({})".format(args)
+ return "{}({})".format(name, args)
def _render_list(items):
if not items:
@@ -80,10 +80,27 @@
"]",
])
+def _render_tuple(items, *, value_repr = repr):
+ if not items:
+ return "tuple()"
+
+ if len(items) == 1:
+ return "({},)".format(value_repr(items[0]))
+
+ return "\n".join([
+ "(",
+ _indent("\n".join([
+ "{},".format(value_repr(item))
+ for item in items
+ ])),
+ ")",
+ ])
+
render = struct(
alias = _render_alias,
dict = _render_dict,
indent = _indent,
list = _render_list,
select = _render_select,
+ tuple = _render_tuple,
)
diff --git a/tests/pip_hub_repository/render_pkg_aliases/render_pkg_aliases_test.bzl b/tests/pip_hub_repository/render_pkg_aliases/render_pkg_aliases_test.bzl
index c61e5ef..ddc9da7 100644
--- a/tests/pip_hub_repository/render_pkg_aliases/render_pkg_aliases_test.bzl
+++ b/tests/pip_hub_repository/render_pkg_aliases/render_pkg_aliases_test.bzl
@@ -65,6 +65,8 @@
want_key = "foo/BUILD.bazel"
want_content = """\
+load("@bazel_skylib//lib:selects.bzl", "selects")
+
package(default_visibility = ["//visibility:public"])
alias(
@@ -108,6 +110,8 @@
want_key = "bar_baz/BUILD.bazel"
want_content = """\
+load("@bazel_skylib//lib:selects.bzl", "selects")
+
package(default_visibility = ["//visibility:public"])
alias(
@@ -117,40 +121,48 @@
alias(
name = "pkg",
- actual = select(
+ actual = selects.with_or(
{
- "//:my_config_setting": "@pypi_32_bar_baz//:pkg",
- "//conditions:default": "@pypi_32_bar_baz//:pkg",
+ (
+ "//:my_config_setting",
+ "//conditions:default",
+ ): "@pypi_32_bar_baz//:pkg",
},
),
)
alias(
name = "whl",
- actual = select(
+ actual = selects.with_or(
{
- "//:my_config_setting": "@pypi_32_bar_baz//:whl",
- "//conditions:default": "@pypi_32_bar_baz//:whl",
+ (
+ "//:my_config_setting",
+ "//conditions:default",
+ ): "@pypi_32_bar_baz//:whl",
},
),
)
alias(
name = "data",
- actual = select(
+ actual = selects.with_or(
{
- "//:my_config_setting": "@pypi_32_bar_baz//:data",
- "//conditions:default": "@pypi_32_bar_baz//:data",
+ (
+ "//:my_config_setting",
+ "//conditions:default",
+ ): "@pypi_32_bar_baz//:data",
},
),
)
alias(
name = "dist_info",
- actual = select(
+ actual = selects.with_or(
{
- "//:my_config_setting": "@pypi_32_bar_baz//:dist_info",
- "//conditions:default": "@pypi_32_bar_baz//:dist_info",
+ (
+ "//:my_config_setting",
+ "//conditions:default",
+ ): "@pypi_32_bar_baz//:dist_info",
},
),
)"""
@@ -178,6 +190,8 @@
want_key = "bar_baz/BUILD.bazel"
want_content = """\
+load("@bazel_skylib//lib:selects.bzl", "selects")
+
package(default_visibility = ["//visibility:public"])
_NO_MATCH_ERROR = \"\"\"\\
@@ -206,7 +220,7 @@
alias(
name = "pkg",
- actual = select(
+ actual = selects.with_or(
{
"@@//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:pkg",
"@@//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:pkg",
@@ -217,7 +231,7 @@
alias(
name = "whl",
- actual = select(
+ actual = selects.with_or(
{
"@@//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:whl",
"@@//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:whl",
@@ -228,7 +242,7 @@
alias(
name = "data",
- actual = select(
+ actual = selects.with_or(
{
"@@//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:data",
"@@//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:data",
@@ -239,7 +253,7 @@
alias(
name = "dist_info",
- actual = select(
+ actual = selects.with_or(
{
"@@//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:dist_info",
"@@//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:dist_info",
@@ -273,6 +287,8 @@
want_key = "bar_baz/BUILD.bazel"
want_content = """\
+load("@bazel_skylib//lib:selects.bzl", "selects")
+
package(default_visibility = ["//visibility:public"])
_NO_MATCH_ERROR = \"\"\"\\
@@ -301,7 +317,7 @@
alias(
name = "pkg",
- actual = select(
+ actual = selects.with_or(
{
"@@//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:pkg",
"@@//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:pkg",
@@ -312,7 +328,7 @@
alias(
name = "whl",
- actual = select(
+ actual = selects.with_or(
{
"@@//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:whl",
"@@//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:whl",
@@ -323,7 +339,7 @@
alias(
name = "data",
- actual = select(
+ actual = selects.with_or(
{
"@@//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:data",
"@@//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:data",
@@ -334,7 +350,7 @@
alias(
name = "dist_info",
- actual = select(
+ actual = selects.with_or(
{
"@@//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:dist_info",
"@@//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:dist_info",
diff --git a/tests/private/text_util/render_tests.bzl b/tests/private/text_util/render_tests.bzl
index 7c3dddf..14967a9 100644
--- a/tests/private/text_util/render_tests.bzl
+++ b/tests/private/text_util/render_tests.bzl
@@ -54,6 +54,25 @@
_tests.append(_test_render_alias)
+def _test_render_tuple_dict(env):
+ got = render.dict(
+ {
+ ("foo", "bar"): "baz",
+ ("foo",): "bar",
+ },
+ key_repr = render.tuple,
+ )
+ env.expect.that_str(got).equals("""\
+{
+ (
+ "foo",
+ "bar",
+ ): "baz",
+ ("foo",): "bar",
+}""")
+
+_tests.append(_test_render_tuple_dict)
+
def render_test_suite(name):
"""Create the test suite.