xref: /aosp_15_r20/external/bazelbuild-rules_python/python/private/py_console_script_binary.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"""
16Implementation for the macro to generate a console_script py_binary from an 'entry_points.txt' config.
17"""
18
19load("//python:py_binary.bzl", "py_binary")
20load(":py_console_script_gen.bzl", "py_console_script_gen")
21
22def _dist_info(pkg):
23    """Return the first candidate for the dist_info target label.
24
25    We cannot do `Label(pkg)` here because the string will be evaluated within
26    the context of the rules_python repo_mapping and it will fail because
27    rules_python does not know anything about the hub repos that the user has
28    available.
29
30    NOTE: Works with assuming the following label formats:
31        * @pypi//pylint
32        * @pypi//pylint:pkg
33        * Label("@pypi//pylint:pkg")
34        * Label("@pypi//pylint")
35    """
36
37    if type(pkg) == type(""):
38        label = native.package_relative_label(pkg)
39    else:
40        label = pkg
41
42    if hasattr(label, "same_package_label"):
43        return label.same_package_label("dist_info")
44    else:
45        # NOTE @aignas 2024-03-25: this is deprecated but kept for compatibility
46        return label.relative("dist_info")
47
48def py_console_script_binary(
49        *,
50        name,
51        pkg,
52        entry_points_txt = None,
53        script = None,
54        binary_rule = py_binary,
55        **kwargs):
56    """Generate a py_binary for a console_script entry_point.
57
58    Args:
59        name: [`target-name`] The name of the resulting target.
60        pkg: {any}`simple label` the package for which to generate the script.
61        entry_points_txt: optional [`label`], the entry_points.txt file to parse
62            for available console_script values. It may be a single file, or a
63            group of files, but must contain a file named `entry_points.txt`.
64            If not specified, defaults to the `dist_info` target in the same
65            package as the `pkg` Label.
66        script: [`str`], The console script name that the py_binary is going to be
67            generated for. Defaults to the normalized name attribute.
68        binary_rule: {any}`rule callable`, The rule/macro to use to instantiate
69            the target. It's expected to behave like {any}`py_binary`.
70            Defaults to {any}`py_binary`.
71        **kwargs: Extra parameters forwarded to `binary_rule`.
72    """
73    main = "rules_python_entry_point_{}.py".format(name)
74
75    if kwargs.pop("srcs", None):
76        fail("passing 'srcs' attribute to py_console_script_binary is unsupported")
77
78    py_console_script_gen(
79        name = "_{}_gen".format(name),
80        entry_points_txt = entry_points_txt or _dist_info(pkg),
81        out = main,
82        console_script = script,
83        console_script_guess = name,
84        visibility = ["//visibility:private"],
85    )
86
87    binary_rule(
88        name = name,
89        srcs = [main],
90        main = main,
91        deps = [pkg] + kwargs.pop("deps", []),
92        **kwargs
93    )
94