blob: 53d1cad5f077c30babb35da1eb079afdeaf5a292 [file] [log] [blame] [edit]
# Copyright 2023 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
load("@bazel_features//:features.bzl", "bazel_features")
visibility([
"//tests/bzlmod/...",
])
# structs have certain built-in methods or attributes that should not
# be overwritten. Load these by calling `dir` on an empty struct.
# e.g. ["to_proto", "to_json"]
_STRUCT_PROTECTED_ATTRIBUTES = dir(struct())
def drop_nones(dict):
"""Drop entries with None values from a dictionary.
Args:
dict: A dictionary.
Returns:
A new dictionary with the same keys as dict, but with entries with
None values removed.
"""
return {k: v for k, v in dict.items() if v != None}
def format_rule_call(_kind, **attrs):
"""Format a rule call.
Args:
_kind: The kind of the rule.
attrs: The attributes of the rule. The attributes are sorted by name,
except for the "name" attribute, which is always first. None
values are ignored.
Returns:
A string representing the rule call.
"""
lines = [_kind + "("]
for attr, value in sorted(attrs.items(), key = _attrs_sort_key):
if value == None:
continue
lines.append(" {} = {},".format(attr, repr(value)))
lines.append(")")
return "\n".join(lines)
def _attrs_sort_key(entry):
"""Sort key for attributes.
Attributes are sorted by name, except for the "name" attribute, which is
always first.
Args:
entry: A tuple of (attribute name, attribute value).
Returns:
An opaque sort key.
"""
attr, _ = entry
if attr == "name":
# Sort "name" first.
return ""
return attr
def get_directive_value(directives, key):
"""Get the value of a directive.
Args:
directives: A list of directives.
key: The key of the directive.
Returns:
The value of the last directive, or None if the directive is not
present.
"""
prefix = "gazelle:" + key + " "
value = None
for directive in directives:
if directive.startswith(prefix):
# Treat "gazelle:key value" the same as "gazelle:key value".
value = directive[len(prefix):].lstrip()
return value
def with_replaced_or_new_fields(_struct, **replacements):
"""Provides a shallow copy of a structure with replacements and/or new fields
Args:
_struct: structure to shallow copy.
**replacements: kwargs for fields to either replace or add to the new struct.
Returns:
The resulting updated structure.
"""
new_struct_assignments = {
key: getattr(_struct, key)
for key in dir(_struct)
if key not in _STRUCT_PROTECTED_ATTRIBUTES
}
# Overwrite existing fields and add new ones.
for key, value in replacements.items():
new_struct_assignments[key] = value
return struct(**new_struct_assignments)
def extension_metadata(
module_ctx,
*,
root_module_direct_deps = None,
root_module_direct_dev_deps = None,
reproducible = False):
if not hasattr(module_ctx, "extension_metadata"):
return None
metadata_kwargs = {}
if bazel_features.external_deps.extension_metadata_has_reproducible:
metadata_kwargs["reproducible"] = reproducible
return module_ctx.extension_metadata(
root_module_direct_deps = root_module_direct_deps,
root_module_direct_dev_deps = root_module_direct_dev_deps,
**metadata_kwargs
)