Skip to content

Commit 0b29ceb

Browse files
Integrate Ruff docstring linting for Arm public APIs
Add a RUFF_DOCS lintrunner target scoped to Arm public API files. Signed-off-by: Sebastian Larsson <sebastian.larsson@arm.com> Change-Id: I4285ff88f37997422391c4950a714934f58e2ad4
1 parent f512d7e commit 0b29ceb

15 files changed

Lines changed: 115 additions & 55 deletions

.lintrunner.toml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,41 @@ command = [
647647
'@{{PATHSFILE}}',
648648
]
649649

650+
[[linter]]
651+
code = 'RUFF_DOCS'
652+
include_patterns = [
653+
'backends/arm/__init__.py',
654+
'backends/arm/common/arm_compile_spec.py',
655+
'backends/arm/ethosu/**/*.py',
656+
'backends/arm/quantizer/__init__.py',
657+
'backends/arm/quantizer/arm_quantizer.py',
658+
'backends/arm/tosa/partitioner.py',
659+
'backends/arm/vgf/**/*.py',
660+
]
661+
exclude_patterns = [
662+
'third-party/**',
663+
'**/third-party/**',
664+
]
665+
command = [
666+
'python',
667+
'-m',
668+
'lintrunner_adapters',
669+
'run',
670+
'ruff_linter',
671+
'--config=pyproject.toml',
672+
'--',
673+
'@{{PATHSFILE}}',
674+
]
675+
init_command = [
676+
'python',
677+
'-m',
678+
'lintrunner_adapters',
679+
'run',
680+
'pip_init',
681+
'--dry-run={{DRYRUN}}',
682+
'--requirement=requirements-lintrunner.txt',
683+
]
684+
650685
[[linter]]
651686
code = 'DOCFORMATTER'
652687
include_patterns = ['backends/arm/**/*.py']

backends/arm/common/arm_compile_spec.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@
2828

2929
@dataclass(init=False)
3030
class ArmCompileSpec(ABC):
31+
"""Base compile specification for Arm backend targets."""
32+
3133
class DebugMode(Enum):
34+
"""Debug artifact formats emitted during Arm lowering."""
35+
3236
JSON = 1
3337
TOSA = 2
3438

@@ -251,8 +255,10 @@ def _set_preserve_io_quantization(self, enabled: bool) -> "ArmCompileSpec":
251255
return self
252256

253257
def _warn_if_redundant_preserve_io_quantization(self) -> None:
254-
"""Warn when preserve_io_quantization has no effect for INT-only
255-
specs.
258+
"""Warn when preserve_io_quantization has no effect.
259+
260+
INT-only specs already preserve IO quantization naturally.
261+
256262
"""
257263
if (
258264
self.preserve_io_quantization
@@ -266,8 +272,7 @@ def _warn_if_redundant_preserve_io_quantization(self) -> None:
266272
)
267273

268274
def _get_pass_pipeline_config(self) -> ArmPassPipelineConfig:
269-
"""Returns configuration that controls how the Arm pass pipeline should
270-
behave.
275+
"""Return the configuration for the Arm pass pipeline.
271276
272277
Subclasses may override to tweak defaults for specific targets.
273278
@@ -277,8 +282,7 @@ def _get_pass_pipeline_config(self) -> ArmPassPipelineConfig:
277282
return self._pipeline_config
278283

279284
def set_pass_pipeline_config(self, config: ArmPassPipelineConfig) -> None:
280-
"""Sets the configuration that controls how the Arm pass pipeline should
281-
behave. Subclasses may override to tweak defaults for specific targets.
285+
"""Set the configuration for the Arm pass pipeline.
282286
283287
Args:
284288
config: The custom ArmPassPipelineConfig to set.
@@ -296,18 +300,16 @@ def _create_default_pipeline_config(self) -> ArmPassPipelineConfig:
296300
return config
297301

298302
def _get_intermediate_path(self) -> str | None:
299-
"""Gets the path used for dumping intermediate results such as tosa and
300-
pte.
303+
"""Get the path used for dumping intermediate results.
301304
302305
Returns:
303-
Path where intermediate results are saved.
306+
Path where TOSA and PTE intermediate results are saved.
304307
305308
"""
306309
return self.path_for_intermediates
307310

308311
def dump_intermediate_artifacts_to(self, output_path: str | None):
309-
"""Sets a path for dumping intermediate results during such as tosa and
310-
pte.
312+
"""Set a path for dumping TOSA and PTE intermediate results.
311313
312314
Args:
313315
output_path: Path to dump intermediate results to.

backends/arm/ethosu/compile_spec.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
# LICENSE file in the root directory of this source tree.
55

66
from executorch.backends.arm.common.arm_compile_spec import ArmCompileSpec
7-
from executorch.backends.arm.common.pipeline_config import ( # noqa: unused
8-
ArmPassPipelineConfig,
9-
)
7+
from executorch.backends.arm.common.pipeline_config import ArmPassPipelineConfig
108
from executorch.backends.arm.tosa import ( # type: ignore[import-not-found]
119
TosaSpecification,
1210
)

backends/arm/quantizer/arm_quantizer.py

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ def get_cond_while_submodules_ao(
117117
only the ``while_loop`` cond function is processed explicitly there.
118118
119119
"""
120-
121120
if not apply_quantization:
122121
return get_cond_while_submodules(graph_module)
123122

@@ -156,6 +155,7 @@ def get_symmetric_quantization_config(
156155
act_qmax (int): Maximum activation quantization value.
157156
weight_qmin (int): Minimum weight quantization value.
158157
weight_qmax (int): Maximum weight quantization value.
158+
eps (float): Minimum scale value used by observers.
159159
160160
Returns:
161161
QuantizationConfig: Quantization settings for activations, weights, and
@@ -525,14 +525,17 @@ def __init__(
525525

526526
@property
527527
def tosa_spec(self):
528+
"""Return the TOSA specification used by the active quantizer."""
528529
return self.quantizer.tosa_spec
529530

530531
@property
531532
def compile_spec(self):
533+
"""Return the compile specification used by the active quantizer."""
532534
return self.quantizer.compile_spec
533535

534536
@property
535537
def global_config(self):
538+
"""Return the fallback quantization configuration."""
536539
return self.quantizer.global_config
537540

538541
@global_config.setter
@@ -546,6 +549,7 @@ def global_config(self, value: Optional[QuantizationConfig]) -> None:
546549

547550
@property
548551
def io_config(self):
552+
"""Return the input and output quantization configuration."""
549553
if isinstance(self.quantizer, _TOSAQuantizerV1):
550554
return self.quantizer.io_config
551555
else:
@@ -564,6 +568,7 @@ def io_config(self, value: Optional[QuantizationConfig]) -> None:
564568

565569
@property
566570
def module_type_config(self):
571+
"""Return quantization configuration overrides by module type."""
567572
if isinstance(self.quantizer, _TOSAQuantizerV1):
568573
return self.quantizer.module_type_config
569574
else:
@@ -584,6 +589,7 @@ def module_type_config(
584589

585590
@property
586591
def module_name_config(self):
592+
"""Return quantization configuration overrides by module name."""
587593
if isinstance(self.quantizer, _TOSAQuantizerV1):
588594
return getattr(self.quantizer, "module_name_config", {})
589595
else:
@@ -692,6 +698,7 @@ def set_node_finder(
692698
quantization_config (Optional[QuantizationConfig]): Configuration
693699
describing quantization settings for nodes matched by the provided
694700
NodeFinder. ``None`` indicates no quantization.
701+
node_finder (NodeFinder): Predicate used to select nodes.
695702
696703
"""
697704
if self.use_composable_quantizer:
@@ -757,14 +764,18 @@ def annotate(self, model: GraphModule) -> GraphModule:
757764
return self.quantizer.annotate(model)
758765

759766
def validate(self, model: GraphModule) -> None:
760-
"""Validate the quantization results. Currently, this includes:
761-
- Ensure tensor inputs to each operator live on the same device.
767+
"""Validate the quantization results.
768+
769+
Currently, this ensures tensor inputs to each operator live on the same
770+
device.
762771
763772
Args:
764773
model (GraphModule): GraphModule being validated.
774+
765775
Raises:
766776
ValueError: If tensor inputs for any operator span more than one
767777
device.
778+
768779
"""
769780
for node in model.graph.nodes:
770781
if node.op != "call_function":
@@ -809,8 +820,7 @@ def _quantize_with_submodules(
809820
is_qat: bool = False,
810821
fold_quantize: bool = True,
811822
):
812-
"""Quantizes a GraphModule in a way such that conditional submodules are
813-
handled properly.
823+
"""Quantize a GraphModule with conditional submodule handling.
814824
815825
Note: torchao's prepare_pt2e and convert_pt2e natively handle
816826
while_loop body_fn submodules, so we only manually process cond
@@ -823,8 +833,8 @@ def _quantize_with_submodules(
823833
model with submodules, at least one sample per code path is
824834
needed.
825835
is_qat (bool): Whether to do quantization aware training or not.
826-
fold_quantize (bool): Enables or disables constant folding when quantization
827-
is completed.
836+
fold_quantize (bool): Enables or disables constant folding when
837+
quantization is completed.
828838
829839
Returns:
830840
GraphModule: The quantized model.
@@ -949,7 +959,6 @@ def _set_disallow_tfa_for_nodes(self, model: GraphModule) -> None:
949959
quantized models.
950960
951961
"""
952-
953962
# First, set all nodes according to global config
954963
for node in model.graph.nodes:
955964
node.meta[DISALLOW_TFA_META_KEY] = self.global_config is None
@@ -1104,10 +1113,10 @@ def __init__(
11041113

11051114
@property
11061115
def quantizers(self) -> List[Quantizer]:
1107-
"""Returns the configured quantizers in order of precedence, ensuring
1108-
the global config and shared_qspec_quantizer are applied last.
1116+
"""Return the configured quantizers in order of precedence.
11091117
1110-
The returned list is a shallow copy; quantizer instances are shared.
1118+
The returned list is a shallow copy; quantizer instances are shared. The
1119+
global config and shared_qspec_quantizer are applied last.
11111120
11121121
"""
11131122
quantizers = self._quantizers.copy()
@@ -1119,9 +1128,7 @@ def quantizers(self) -> List[Quantizer]:
11191128

11201129
@quantizers.setter
11211130
def quantizers(self, value: List[Quantizer]) -> None:
1122-
"""Override of quantizers setter to allow for dynamic updating of
1123-
quantizers without accessing self._quantizers.
1124-
"""
1131+
"""Update quantizers without accessing self._quantizers directly."""
11251132
self._quantizers = value
11261133

11271134
def annotate(self, model):

backends/arm/tosa/partitioner.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,7 @@ def reject_partition(
155155

156156

157157
def _validate_partition(nodes: set[torch.fx.Node]) -> bool:
158-
"""Check whether a set of nodes can be extracted as a subgraph without
159-
cycles.
158+
"""Check whether a set of nodes can be extracted.
160159
161160
Perform a BFS from the external users of partition nodes. If any node
162161
reached by BFS is itself inside the partition, then extracting the
@@ -260,9 +259,7 @@ def __init__(
260259
self.intermediate_path = compile_spec._get_intermediate_path()
261260

262261
def register_custom_partition_op(self, op: torch._ops.OpOverload) -> None:
263-
"""Register a custom op to be considered supported by this
264-
partitioner.
265-
"""
262+
"""Register a custom op to be considered supported."""
266263
self._custom_partition_ops.add(op)
267264

268265
def _detag_boundary_nodes(
@@ -284,9 +281,10 @@ def _detag_boundary_nodes(
284281
tag: The delegation tag assigned to the partition.
285282
reporter: A reporter to log rejected nodes.
286283
module: The GraphModule containing the partition.
284+
detag_first_fp_node: Whether to de-tag the first floating-point
285+
node in a partition.
287286
288287
"""
289-
290288
# De-tag outermost q-nodes upwards and dq-nodes downwards.
291289
# De-tag if at least one input/output is not part of the partition.
292290
for node in module.graph.nodes:
@@ -320,9 +318,7 @@ def _detag_boundary_nodes(
320318
break
321319

322320
def _preserve_io_quantization_enabled(self) -> bool:
323-
"""Return True if IO quantization should be preserved from compile
324-
specs.
325-
"""
321+
"""Return True if compile specs preserve IO quantization."""
326322
for spec in self.delegation_spec.compile_specs:
327323
if spec.key != "preserve_io_quantization":
328324
continue
@@ -614,9 +610,10 @@ def ops_to_not_decompose( # noqa: C901
614610
}
615611

616612
def filter_fn(node: torch.fx.Node) -> bool:
617-
"""Filter function applied to ops in 'ops_to_not_decompose'. Returns
618-
True if the op should not be decomposed. If this function returns
619-
True, the partitioner *must* accept the node, or the lowering fails.
613+
"""Return True if an op should not be decomposed.
614+
615+
If this function returns True, the partitioner *must* accept the
616+
node, or the lowering fails.
620617
621618
Args:
622619
node (torch.fx.Node): FX node to evaluate.

backends/arm/vgf/model_converter.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2025 Arm Limited and/or its affiliates.
1+
# Copyright 2025-2026 Arm Limited and/or its affiliates.
22
#
33
# This source code is licensed under the BSD-style license found in the
44
# LICENSE file in the root directory of this source tree.
@@ -43,7 +43,6 @@ def model_converter_env() -> dict[str, str]:
4343

4444
def require_model_converter_binary() -> str:
4545
"""Return a usable model converter executable or raise a helpful error."""
46-
4746
binary = find_model_converter_binary()
4847
if binary is None:
4948
tried = ", ".join((MODEL_CONVERTER_BINARY, _MODEL_CONVERTER_FALLBACK_BINARY))

docs/source/backends/arm-ethos-u/arm-ethos-u-overview.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ Args:
6767
```python
6868
def EthosUCompileSpec.dump_intermediate_artifacts_to(self, output_path: str | None):
6969
```
70-
Sets a path for dumping intermediate results during such as tosa and
71-
pte.
70+
Set a path for dumping TOSA and PTE intermediate results.
7271

7372
Args:
7473
- **output_path**: Path to dump intermediate results to.
@@ -89,8 +88,7 @@ Args:
8988
```python
9089
def EthosUCompileSpec.set_pass_pipeline_config(self, config: executorch.backends.arm.common.pipeline_config.ArmPassPipelineConfig) -> None:
9190
```
92-
Sets the configuration that controls how the Arm pass pipeline should
93-
behave. Subclasses may override to tweak defaults for specific targets.
91+
Set the configuration for the Arm pass pipeline.
9492

9593
Args:
9694
- **config**: The custom ArmPassPipelineConfig to set.

docs/source/backends/arm-ethos-u/arm-ethos-u-partitioner.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,4 @@ Returns:
4949
```python
5050
def EthosUPartitioner.register_custom_partition_op(self, op: torch._ops.OpOverload) -> None:
5151
```
52-
Register a custom op to be considered supported by this
53-
partitioner.
52+
Register a custom op to be considered supported.

docs/source/backends/arm-ethos-u/arm-ethos-u-quantization.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ Args:
9292
- **quantization_config (Optional[QuantizationConfig])**: Configuration
9393
describing quantization settings for nodes matched by the provided
9494
NodeFinder. ``None`` indicates no quantization.
95+
- **node_finder (NodeFinder)**: Predicate used to select nodes.
9596

9697
```python
9798
def EthosUQuantizer.set_node_name(self, node_name: 'str', quantization_config: 'Optional[QuantizationConfig]') -> 'TOSAQuantizer':

docs/source/backends/arm-vgf/arm-vgf-overview.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ Args:
5858
```python
5959
def VgfCompileSpec.dump_intermediate_artifacts_to(self, output_path: str | None):
6060
```
61-
Sets a path for dumping intermediate results during such as tosa and
62-
pte.
61+
Set a path for dumping TOSA and PTE intermediate results.
6362

6463
Args:
6564
- **output_path**: Path to dump intermediate results to.
@@ -80,8 +79,7 @@ Args:
8079
```python
8180
def VgfCompileSpec.set_pass_pipeline_config(self, config: executorch.backends.arm.common.pipeline_config.ArmPassPipelineConfig) -> None:
8281
```
83-
Sets the configuration that controls how the Arm pass pipeline should
84-
behave. Subclasses may override to tweak defaults for specific targets.
82+
Set the configuration for the Arm pass pipeline.
8583

8684
Args:
8785
- **config**: The custom ArmPassPipelineConfig to set.

0 commit comments

Comments
 (0)