xref: /aosp_15_r20/external/bazelbuild-rules_python/python/private/pypi/whl_library_alias.bzl (revision 60517a1edbc8ecf509223e9af94a7adec7d736b8)
1# Copyright 2024 The Bazel Authors. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""whl_library aliases for multi_pip_parse."""
16
17load("//python/private:full_version.bzl", "full_version")
18load(":render_pkg_aliases.bzl", "NO_MATCH_ERROR_MESSAGE_TEMPLATE")
19
20def _whl_library_alias_impl(rctx):
21    rules_python = rctx.attr._rules_python_workspace.workspace_name
22    if rctx.attr.default_version:
23        default_repo_prefix = rctx.attr.version_map[rctx.attr.default_version]
24    else:
25        default_repo_prefix = None
26    version_map = rctx.attr.version_map.items()
27    build_content = ["# Generated by python/pip.bzl"]
28    for alias_name in ["pkg", "whl", "data", "dist_info"]:
29        build_content.append(_whl_library_render_alias_target(
30            alias_name = alias_name,
31            default_repo_prefix = default_repo_prefix,
32            minor_mapping = rctx.attr.minor_mapping,
33            rules_python = rules_python,
34            version_map = version_map,
35            wheel_name = rctx.attr.wheel_name,
36        ))
37    rctx.file("BUILD.bazel", "\n".join(build_content))
38
39def _whl_library_render_alias_target(
40        *,
41        alias_name,
42        default_repo_prefix,
43        minor_mapping,
44        rules_python,
45        version_map,
46        wheel_name):
47    alias = ["""\
48alias(
49    name = "{alias_name}",
50    actual = select({{""".format(alias_name = alias_name)]
51    for [python_version, repo_prefix] in version_map:
52        alias.append("""\
53        "@{rules_python}//python/config_settings:is_python_{full_python_version}": "{actual}",""".format(
54            full_python_version = full_version(version = python_version, minor_mapping = minor_mapping),
55            actual = "@{repo_prefix}{wheel_name}//:{alias_name}".format(
56                repo_prefix = repo_prefix,
57                wheel_name = wheel_name,
58                alias_name = alias_name,
59            ),
60            rules_python = rules_python,
61        ))
62    if default_repo_prefix:
63        default_actual = "@{repo_prefix}{wheel_name}//:{alias_name}".format(
64            repo_prefix = default_repo_prefix,
65            wheel_name = wheel_name,
66            alias_name = alias_name,
67        )
68        alias.append('        "//conditions:default": "{default_actual}",'.format(
69            default_actual = default_actual,
70        ))
71
72    alias.append("    },")  # Close select expression condition dict
73    if not default_repo_prefix:
74        supported_versions = sorted([python_version for python_version, _ in version_map])
75        alias.append('    no_match_error="""{}""",'.format(
76            NO_MATCH_ERROR_MESSAGE_TEMPLATE.format(
77                supported_versions = ", ".join(supported_versions),
78                rules_python = rules_python,
79            ),
80        ))
81    alias.append("    ),")  # Close the select expression
82    alias.append('    visibility = ["//visibility:public"],')
83    alias.append(")")  # Close the alias() expression
84    return "\n".join(alias)
85
86whl_library_alias = repository_rule(
87    _whl_library_alias_impl,
88    attrs = {
89        "default_version": attr.string(
90            mandatory = False,
91            doc = "Optional Python version in major.minor format, e.g. '3.10'." +
92                  "The Python version of the wheel to use when the versions " +
93                  "from `version_map` don't match. This allows the default " +
94                  "(version unaware) rules to match and select a wheel. If " +
95                  "not specified, then the default rules won't be able to " +
96                  "resolve a wheel and an error will occur.",
97        ),
98        "minor_mapping": attr.string_dict(mandatory = True),
99        "version_map": attr.string_dict(mandatory = True),
100        "wheel_name": attr.string(mandatory = True),
101        "_rules_python_workspace": attr.label(default = Label("//:WORKSPACE")),
102    },
103)
104