xref: /aosp_15_r20/external/bazelbuild-rules_python/python/private/util.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"""Functionality shared by multiple pieces of code."""
16
17load("@bazel_skylib//lib:types.bzl", "types")
18
19def copy_propagating_kwargs(from_kwargs, into_kwargs = None):
20    """Copies args that must be compatible between two targets with a dependency relationship.
21
22    This is intended for when one target depends on another, so they must have
23    compatible settings such as `testonly` and `compatible_with`. This usually
24    happens when a macro generates multiple targets, some of which depend
25    on one another, so their settings must be compatible.
26
27    Args:
28        from_kwargs: keyword args dict whose common kwarg will be copied.
29        into_kwargs: optional keyword args dict that the values from `from_kwargs`
30            will be copied into. The values in this dict will take precedence
31            over the ones in `from_kwargs` (i.e., if this has `testonly` already
32            set, then it won't be overwritten).
33            NOTE: THIS WILL BE MODIFIED IN-PLACE.
34
35    Returns:
36        Keyword args to use for the depender target derived from the dependency
37        target. If `into_kwargs` was passed in, then that same object is
38        returned; this is to facilitate easy `**` expansion.
39    """
40    if into_kwargs == None:
41        into_kwargs = {}
42
43    # Include tags because people generally expect tags to propagate.
44    for attr in ("testonly", "tags", "compatible_with", "restricted_to"):
45        if attr in from_kwargs and attr not in into_kwargs:
46            into_kwargs[attr] = from_kwargs[attr]
47    return into_kwargs
48
49# The implementation of the macros and tagging mechanism follows the example
50# set by rules_cc and rules_java.
51
52_MIGRATION_TAG = "__PYTHON_RULES_MIGRATION_DO_NOT_USE_WILL_BREAK__"
53
54def add_migration_tag(attrs):
55    """Add a special tag to `attrs` to aid migration off native rles.
56
57    Args:
58        attrs: dict of keyword args. The `tags` key will be modified in-place.
59
60    Returns:
61        The same `attrs` object, but modified.
62    """
63    add_tag(attrs, _MIGRATION_TAG)
64    return attrs
65
66def add_tag(attrs, tag):
67    """Adds `tag` to `attrs["tags"]`.
68
69    Args:
70        attrs: dict of keyword args. It is modified in place.
71        tag: str, the tag to add.
72    """
73    if "tags" in attrs and attrs["tags"] != None:
74        tags = attrs["tags"]
75
76        # Preserve the input type: this allows a test verifying the underlying
77        # rule can accept the tuple for the tags argument.
78        if types.is_tuple(tags):
79            attrs["tags"] = tags + (tag,)
80        else:
81            # List concatenation is necessary because the original value
82            # may be a frozen list.
83            attrs["tags"] = tags + [tag]
84    else:
85        attrs["tags"] = [tag]
86
87IS_BAZEL_7_OR_HIGHER = hasattr(native, "starlark_doc_extract")
88
89# Bazel 5.4 has a bug where every access of testing.ExecutionInfo is a
90# different object that isn't equal to any other. This is fixed in bazel 6+.
91IS_BAZEL_6_OR_HIGHER = testing.ExecutionInfo == testing.ExecutionInfo
92
93_marker_rule_to_detect_bazel_6_4_or_higher = rule(implementation = lambda ctx: None)
94
95# Bazel 6.4 and higher have a bug fix where rule names show up in the str()
96# of a rule. See
97# https://github.com/bazelbuild/bazel/commit/002490b9a2376f0b2ea4a37102c5e94fc50a65ba
98# https://github.com/bazelbuild/bazel/commit/443cbcb641e17f7337ccfdecdfa5e69bc16cae55
99# This technique is done instead of using native.bazel_version because,
100# under stardoc, the native.bazel_version attribute is entirely missing, which
101# prevents doc generation from being able to correctly generate docs.
102IS_BAZEL_6_4_OR_HIGHER = "_marker_rule_to_detect_bazel_6_4_or_higher" in str(
103    _marker_rule_to_detect_bazel_6_4_or_higher,
104)
105