Skip to content

Commit

Permalink
Fix docstring lints as reported by internal linter. (#180)
Browse files Browse the repository at this point in the history
  • Loading branch information
reventlov authored Sep 20, 2024
1 parent b545db0 commit 800bd4a
Show file tree
Hide file tree
Showing 17 changed files with 265 additions and 153 deletions.
70 changes: 48 additions & 22 deletions compiler/back_end/cpp/header_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ class Config(NamedTuple):


def _get_namespace_components(namespace):
"""Gets the components of a C++ namespace
"""Gets the components of a C++ namespace.
Examples:
"::some::name::detail" -> ["some", "name", "detail"]
Expand Down Expand Up @@ -1339,10 +1339,12 @@ def _generate_structure_definition(type_ir, ir, config: Config):
Arguments:
type_ir: The IR for the struct definition.
ir: The full IR; used for type lookups.
config: The code generation configuration to use.
Returns:
A tuple of: (forward declaration for classes, class bodies, method bodies),
suitable for insertion into the appropriate places in the generated header.
A tuple of: (forward declaration for classes, class bodies, method
bodies), suitable for insertion into the appropriate places in the
generated header.
"""
subtype_bodies, subtype_forward_declarations, subtype_method_definitions = (
_generate_subtype_definitions(type_ir, ir, config)
Expand Down Expand Up @@ -1530,10 +1532,17 @@ def _generate_structure_definition(type_ir, ir, config: Config):
def _split_enum_case_values_into_spans(enum_case_value):
"""Yields spans containing each enum case in an enum_case attribute value.
Each span is of the form (start, end), which is the start and end position
relative to the beginning of the enum_case_value string. To keep the grammar
of this attribute simple, this only splits on delimiters and trims whitespace
for each case.
Arguments:
enum_case_value: the value of the `enum_case` attribute to be parsed.
Returns:
An iterator over spans, where each span covers one enum case name.
Each span is a half-open range of the form [start, end), which is the
start and end position relative to the beginning of the enum_case_value
string. The name can be retrieved with `enum_case_value[start:end]`.
To keep the grammar of this attribute simple, this only splits on
delimiters and trims whitespace for each case.
Example: 'SHOUTY_CASE, kCamelCase' -> [(0, 11), (13, 23)]"""
# Scan the string from left to right, finding commas and trimming whitespace.
Expand Down Expand Up @@ -1568,6 +1577,12 @@ def _split_enum_case_values_into_spans(enum_case_value):
def _split_enum_case_values(enum_case_value):
"""Returns all enum cases in an enum case value.
Arguments:
enum_case_value: the value of the enum case attribute to parse.
Returns:
All enum case names from `enum_case_value`.
Example: 'SHOUTY_CASE, kCamelCase' -> ['SHOUTY_CASE', 'kCamelCase']"""
return [
enum_case_value[start:end]
Expand All @@ -1576,7 +1591,7 @@ def _split_enum_case_values(enum_case_value):


def _get_enum_value_names(enum_value):
"""Determines one or more enum names based on attributes"""
"""Determines one or more enum names based on attributes."""
cases = ["SHOUTY_CASE"]
name = enum_value.name.name.text
if enum_case := ir_util.get_attribute(
Expand Down Expand Up @@ -1698,14 +1713,16 @@ def _propagate_defaults(ir, targets, ancestors, add_fn):
Traverses the IR to propagate default values to target nodes.
Arguments:
targets: A list of target IR types to add attributes to.
ancestors: Ancestor types which may contain the default values.
add_fn: Function to add the attribute. May use any parameter available in
fast_traverse_ir_top_down actions as well as `defaults` containing the
default attributes set by ancestors.
ir: The IR to process.
targets: A list of target IR types to add attributes to.
ancestors: Ancestor types which may contain the default values.
add_fn: Function to add the attribute. May use any parameter available
in fast_traverse_ir_top_down actions as well as `defaults`
containing the
default attributes set by ancestors.
Returns:
None
None
"""
traverse_ir.fast_traverse_ir_top_down(
ir,
Expand All @@ -1719,14 +1736,19 @@ def _propagate_defaults(ir, targets, ancestors, add_fn):


def _offset_source_location_column(source_location, offset):
"""Adds offsets from the start column of the supplied source location
"""Adds offsets from the start column of the supplied source location.
Returns a new source location with all of the same properties as the provided
source location, but with the columns modified by offsets from the original
start column.
Arguments:
source_location: the initial source location
offset: a tuple of (start, end), which are the offsets relative to
source_location.start.column to set the new start.column and
end.column.
Offset should be a tuple of (start, end), which are the offsets relative to
source_location.start.column to set the new start.column and end.column."""
Returns:
A new source location with all of the same properties as the provided
source location, but with the columns modified by offsets from the
original start column.
"""

new_location = ir_data_utils.copy(source_location)
new_location.start.column = source_location.start.column + offset[0]
Expand Down Expand Up @@ -1863,8 +1885,12 @@ def _verify_attribute_values(ir):
def _propagate_defaults_and_verify_attributes(ir):
"""Verify attributes and ensure defaults are set when not overridden.
Returns a list of errors if there are errors present, or an empty list if
verification completed successfully."""
Arguments:
ir: The IR to process.
Returns:
A list of errors if there are errors present, or an empty list if
verification completed successfully."""
if errors := attribute_util.check_attributes_in_ir(
ir,
back_end="cpp",
Expand Down
2 changes: 1 addition & 1 deletion compiler/back_end/util/code_template_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class ParseTemplatesTest(unittest.TestCase):
"""Tests for code_template.parse_templates."""

def assertTemplatesEqual(self, expected, actual): # pylint:disable=invalid-name
"""Compares the results of a parse_templates"""
"""Compares the results of a parse_templates."""
# Extract the name and template from the result tuple
actual = {k: v.template for k, v in actual._asdict().items()}
self.assertEqual(expected, actual)
Expand Down
1 change: 1 addition & 0 deletions compiler/front_end/attribute_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@


def _valid_back_ends(attr, module_source_file):
"""Checks that `attr` holds a valid list of back end specifiers."""
if not re.match(
r"^(?:\s*[a-z][a-z0-9_]*\s*(?:,\s*[a-z][a-z0-9_]*\s*)*,?)?\s*$",
attr.value.string_constant.text,
Expand Down
1 change: 1 addition & 0 deletions compiler/front_end/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ def _check_physical_type_requirements(


def _check_allowed_in_bits(type_ir, type_definition, source_file_name, ir, errors):
"""Verifies that atomic fields have types that are allowed in `bits`."""
if not type_ir.HasField("atomic_type"):
return
referenced_type_definition = ir_util.find_object(type_ir.atomic_type.reference, ir)
Expand Down
7 changes: 4 additions & 3 deletions compiler/front_end/dependency_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@
def _add_reference_to_dependencies(
reference, dependencies, name, source_file_name, errors
):
"""Adds the specified `reference` to the `dependencies` set."""
if reference.canonical_name.object_path[0] in {
"$is_statically_sized",
"$static_size_in_bits",
"$next",
}:
# This error is a bit opaque, but given that the compiler used to crash on
# this case -- for a couple of years -- and no one complained, it seems
# safe to assume that this is a rare error.
# This error is a bit opaque, but given that the compiler used to crash
# on this case -- for a couple of years -- and no one complained, it
# seems safe to assume that this is a rare error.
errors.append(
[
error.error(
Expand Down
5 changes: 5 additions & 0 deletions compiler/front_end/format_emb.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ def _type(struct, name, colon, comment, eol, body):
" type-definition* struct-field-block Dedent"
)
def _structure_body(indent, docs, attributes, type_definitions, fields, dedent, config):
"""Formats a structure (`bits` or `struct`) body."""
del indent, dedent # Unused.
spacing = [_Row("field-separator")] if _should_add_blank_lines(fields) else []
columnized_fields = _columnize(fields, config.indent_width, indent_columns=2)
Expand Down Expand Up @@ -609,6 +610,7 @@ def _field_body(indent, docs, attributes, dedent):
' field-location "bits" ":" Comment? eol anonymous-bits-body'
)
def _inline_bits(location, bits, colon, comment, eol, body):
"""Formats an inline `bits` definition."""
# Even though an anonymous bits field technically defines a new, anonymous
# type, conceptually it's more like defining a bunch of fields on the
# surrounding type, so it is treated as an inline list of blocks, instead of
Expand Down Expand Up @@ -1017,6 +1019,7 @@ def _concatenate(*elements):
@_formats("or-expression-right -> or-operator comparison-expression")
@_formats("and-expression-right -> and-operator comparison-expression")
def _concatenate_with_prefix_spaces(*elements):
"""Concatenates non-empty `elements` with leading spaces."""
return "".join(" " + element for element in elements if element)


Expand All @@ -1032,10 +1035,12 @@ def _concatenate_with_prefix_spaces(*elements):
)
@_formats('parameter-definition-list-tail -> "," parameter-definition')
def _concatenate_with_spaces(*elements):
"""Concatenates non-empty `elements` with spaces between."""
return _concatenate_with(" ", *elements)


def _concatenate_with(joiner, *elements):
"""Concatenates non-empty `elements` with `joiner` between."""
return joiner.join(element for element in elements if element)


Expand Down
17 changes: 9 additions & 8 deletions compiler/front_end/lr1.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,17 @@ class Item(
):
"""An Item is an LR(1) Item: a production, a cursor location, and a terminal.
An Item represents a partially-parsed production, and a lookahead symbol. The
position of the dot indicates what portion of the production has been parsed.
Generally, Items are an internal implementation detail, but they can be useful
elsewhere, particularly for debugging.
An Item represents a partially-parsed production, and a lookahead symbol.
The position of the dot indicates what portion of the production has been
parsed. Generally, Items are an internal implementation detail, but they
can be useful elsewhere, particularly for debugging.
Attributes:
production: The Production this Item covers.
dot: The index of the "dot" in production's rhs.
terminal: The terminal lookahead symbol that follows the production in the
input stream.
production: The Production this Item covers.
dot: The index of the "dot" in production's rhs.
terminal: The terminal lookahead symbol that follows the production in
the input stream.
next_symbol: The lookahead symbol.
"""

def __str__(self):
Expand Down
7 changes: 5 additions & 2 deletions compiler/front_end/module_ir.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ def _attribute(
attribute_value,
close_bracket,
):
"""Assembles an attribute IR node."""
del open_bracket, colon, close_bracket # Unused.
if context_specifier.list:
return ir_data.Attribute(
Expand Down Expand Up @@ -460,14 +461,15 @@ def _expression(expression):
' ":" logical-expression'
)
def _choice_expression(condition, question, if_true, colon, if_false):
"""Constructs an IR node for a choice operator (`?:`) expression."""
location = parser_types.make_location(
condition.source_location.start, if_false.source_location.end
)
operator_location = parser_types.make_location(
question.source_location.start, colon.source_location.end
)
# The function_name is a bit weird, but should suffice for any error messages
# that might need it.
# The function_name is a bit weird, but should suffice for any error
# messages that might need it.
return ir_data.Expression(
function=ir_data.Function(
function=ir_data.FunctionMapping.CHOICE,
Expand Down Expand Up @@ -1284,6 +1286,7 @@ def _enum_body(indent, docs, attributes, values, dedent):
def _enum_value(
name, equals, expression, attribute, documentation, comment, newline, body
):
"""Constructs an IR node for an enum value statement (`NAME = value`)."""
del equals, comment, newline # Unused.
result = ir_data.EnumValue(
name=name,
Expand Down
1 change: 1 addition & 0 deletions compiler/front_end/synthetics.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ def _add_size_virtuals(structure, type_definition):
def _maybe_replace_next_keyword_in_expression(
expression_ir, last_location, source_file_name, errors
):
"""Replaces the `$next` keyword in an expression."""
if not expression_ir.HasField("builtin_reference"):
return
if (
Expand Down
1 change: 1 addition & 0 deletions compiler/front_end/type_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ def _type_check_constant_reference(expression, source_file_name, ir, errors):


def _type_check_operation(expression, source_file_name, ir, errors):
"""Type checks a function or operator expression."""
for arg in expression.function.args:
_type_check_expression(arg, source_file_name, ir, errors)
function = expression.function.function
Expand Down
38 changes: 20 additions & 18 deletions compiler/util/attribute_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,22 +323,24 @@ def _check_attributes(
):
"""Performs basic checks on the given list of attributes.
Checks the given attribute_list for duplicates, unknown attributes, attributes
with incorrect type, and attributes whose values are not constant.
Checks the given attribute_list for duplicates, unknown attributes,
attributes with incorrect type, and attributes whose values are not
constant.
Arguments:
attribute_list: An iterable of ir_data.Attribute.
back_end: The qualifier for attributes to check, or None.
attribute_specs: A dict of attribute names to _Attribute structures
specifying the allowed attributes.
context_name: A name for the context of these attributes, such as "struct
'Foo'" or "module 'm.emb'". Used in error messages.
module_source_file: The value of module.source_file_name from the module
containing 'attribute_list'. Used in error messages.
attribute_list: An iterable of ir_data.Attribute.
types: A map of attribute types to validators.
back_end: The qualifier for attributes to check, or None.
attribute_specs: A dict of attribute names to _Attribute structures
specifying the allowed attributes.
context_name: A name for the context of these attributes, such as
"struct 'Foo'" or "module 'm.emb'". Used in error messages.
module_source_file: The value of module.source_file_name from the module
containing 'attribute_list'. Used in error messages.
Returns:
A list of lists of error.Errors. An empty list indicates no errors were
found.
A list of lists of error.Errors. An empty list indicates no errors were
found.
"""
if attribute_specs is None:
attribute_specs = []
Expand Down Expand Up @@ -395,17 +397,17 @@ def _check_attributes(


def gather_default_attributes(obj, defaults):
"""Gathers default attributes for an IR object
"""Gathers default attributes for an IR object.
This is designed to be able to be used as-is as an incidental action in an IR
traversal to accumulate defaults for child nodes.
This is designed to be able to be used as-is as an incidental action in an
IR traversal to accumulate defaults for child nodes.
Arguments:
defaults: A dict of `{ "defaults": { attr.name.text: attr } }`
defaults: A dict of `{ "defaults": { attr.name.text: attr } }`
Returns:
A dict of `{ "defaults": { attr.name.text: attr } }` with any defaults
provided by `obj` added/overridden.
A dict of `{ "defaults": { attr.name.text: attr } }` with any defaults
provided by `obj` added/overridden.
"""
defaults = defaults.copy()
for attr in obj.attribute:
Expand Down
10 changes: 7 additions & 3 deletions compiler/util/ir_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ def HasField(self, name): # pylint:disable=invalid-name
def WhichOneof(self, oneof_name): # pylint:disable=invalid-name
"""Indicates which field has been set for the oneof value.
Returns None if no field has been set.
Args:
oneof_name: the name of the oneof construct to test.
Returns: the field name, or None if no field has been set.
"""
for field_name, oneof in self.field_specs.oneof_mappings:
if oneof == oneof_name and self.HasField(field_name):
Expand Down Expand Up @@ -207,7 +210,7 @@ class NumericConstant(Message):


class FunctionMapping(int, enum.Enum):
"""Enum of supported function types"""
"""Enum of supported function types."""

UNKNOWN = 0
ADDITION = 1
Expand Down Expand Up @@ -823,8 +826,9 @@ class RuntimeParameter(Message):


class AddressableUnit(int, enum.Enum):
"""The "addressable unit" is the size of the smallest unit that can be read
"""The 'atom size' for a structure.
The "addressable unit" is the size of the smallest unit that can be read
from the backing store that this type expects. For `struct`s, this is
BYTE; for `enum`s and `bits`, this is BIT, and for `external`s it depends
on the specific type
Expand Down
Loading

0 comments on commit 800bd4a

Please sign in to comment.