diff --git a/scripts/pylint/checkers/argparse-checker.py b/scripts/pylint/checkers/argparse-checker.py new file mode 100644 index 00000000000..fb197a9b787 --- /dev/null +++ b/scripts/pylint/checkers/argparse-checker.py @@ -0,0 +1,54 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations + +from pylint.checkers import BaseChecker + +import astroid +from astroid import nodes + +class ZephyrArgParseChecker(BaseChecker): + """Class implementing function checker for Zephyr.""" + + # The name defines a custom section of the config for this checker. + name = "zephyr-arg-parse" + + # Register messages emitted by the checker. + msgs = { + "E9901": ( + "Argument parser with abbreviations is disallowed", + "argument-parser-with-abbreviations", + "An ArgumentParser object must set `allow_abbrev=false` to disable " + "abbreviations and prevent issues with these being used by projects" + " and/or scripts." + ) + } + + # Function that looks at evert function call for ArgumentParser invocation + def visit_call(self, node: nodes.Call) -> None: + if isinstance(node.func, astroid.nodes.node_classes.Attribute) and \ + node.func.attrname == "ArgumentParser": + abbrev_disabled = False + + # Check that allow_abbrev is set and that the value is False + for keyword in node.keywords: + if keyword.arg == "allow_abbrev": + if not isinstance(keyword.value, astroid.nodes.node_classes.Const): + continue + if keyword.value.pytype() != "builtins.bool": + continue + if keyword.value.value is False: + abbrev_disabled = True + + if abbrev_disabled is False: + self.add_message( + "argument-parser-with-abbreviations", node=node + ) + + return () + +# This is called from pylint, hence PyLinter not being declared in this file +# pylint: disable=undefined-variable +def register(linter: PyLinter) -> None: + linter.register_checker(ZephyrArgParseChecker(linter))