xref: /aosp_15_r20/external/bazelbuild-rules_python/python/private/pypi/hub_repository.bzl (revision 60517a1edbc8ecf509223e9af94a7adec7d736b8)
1# Copyright 2023 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""
16
17load("//python/private:text_util.bzl", "render")
18load(
19    ":render_pkg_aliases.bzl",
20    "render_multiplatform_pkg_aliases",
21    "whl_alias",
22)
23
24_BUILD_FILE_CONTENTS = """\
25package(default_visibility = ["//visibility:public"])
26
27# Ensure the `requirements.bzl` source can be accessed by stardoc, since users load() from it
28exports_files(["requirements.bzl"])
29"""
30
31def _impl(rctx):
32    bzl_packages = rctx.attr.packages or rctx.attr.whl_map.keys()
33    aliases = render_multiplatform_pkg_aliases(
34        aliases = {
35            key: [whl_alias(**v) for v in json.decode(values)]
36            for key, values in rctx.attr.whl_map.items()
37        },
38        default_version = rctx.attr.default_version,
39        default_config_setting = "//_config:is_python_" + rctx.attr.default_version,
40        requirement_cycles = rctx.attr.groups,
41    )
42    for path, contents in aliases.items():
43        rctx.file(path, contents)
44
45    # NOTE: we are using the canonical name with the double '@' in order to
46    # always uniquely identify a repository, as the labels are being passed as
47    # a string and the resolution of the label happens at the call-site of the
48    # `requirement`, et al. macros.
49    macro_tmpl = "@@{name}//{{}}:{{}}".format(name = rctx.attr.name)
50
51    rctx.file("BUILD.bazel", _BUILD_FILE_CONTENTS)
52    rctx.template("requirements.bzl", rctx.attr._template, substitutions = {
53        "%%ALL_DATA_REQUIREMENTS%%": render.list([
54            macro_tmpl.format(p, "data")
55            for p in bzl_packages
56        ]),
57        "%%ALL_REQUIREMENTS%%": render.list([
58            macro_tmpl.format(p, "pkg")
59            for p in bzl_packages
60        ]),
61        "%%ALL_WHL_REQUIREMENTS_BY_PACKAGE%%": render.dict({
62            p: macro_tmpl.format(p, "whl")
63            for p in bzl_packages
64        }),
65        "%%MACRO_TMPL%%": macro_tmpl,
66    })
67
68hub_repository = repository_rule(
69    attrs = {
70        "default_version": attr.string(
71            mandatory = True,
72            doc = """\
73This is the default python version in the format of X.Y. This should match
74what is setup by the 'python' extension using the 'is_default = True'
75setting.""",
76        ),
77        "groups": attr.string_list_dict(
78            mandatory = False,
79        ),
80        "packages": attr.string_list(
81            mandatory = False,
82            doc = """\
83The list of packages that will be exposed via all_*requirements macros. Defaults to whl_map keys.
84""",
85        ),
86        "repo_name": attr.string(
87            mandatory = True,
88            doc = "The apparent name of the repo. This is needed because in bzlmod, the name attribute becomes the canonical name.",
89        ),
90        "whl_map": attr.string_dict(
91            mandatory = True,
92            doc = """\
93The wheel map where values are json.encoded strings of the whl_map constructed
94in the pip.parse tag class.
95""",
96        ),
97        "_template": attr.label(
98            default = ":requirements.bzl.tmpl.bzlmod",
99        ),
100    },
101    doc = """A rule for bzlmod mulitple pip repository creation. PRIVATE USE ONLY.""",
102    implementation = _impl,
103)
104