diff options
Diffstat (limited to 'test/sanity/code-smell/required-and-default-attributes.py')
-rw-r--r-- | test/sanity/code-smell/required-and-default-attributes.py | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/test/sanity/code-smell/required-and-default-attributes.py b/test/sanity/code-smell/required-and-default-attributes.py index 900829dce7..7b1c89f9b8 100644 --- a/test/sanity/code-smell/required-and-default-attributes.py +++ b/test/sanity/code-smell/required-and-default-attributes.py @@ -1,19 +1,25 @@ from __future__ import annotations -import re +import ast +import pathlib import sys -def main(): - for path in sys.argv[1:] or sys.stdin.read().splitlines(): - with open(path, 'r') as path_fd: - for line, text in enumerate(path_fd.readlines()): - match = re.search(r'(FieldAttribute.*(default|required).*(default|required))', text) +class CallVisitor(ast.NodeVisitor): + def __init__(self, path: str) -> None: + self.path = path + + def visit_Call(self, node: ast.Call) -> None: + if isinstance(node.func, ast.Name) and node.func.id.endswith("FieldAttribute"): + if len([kw for kw in node.keywords if kw.arg in ("default", "required")]) > 1: + print(f"{self.path}:{node.lineno}:{node.col_offset}: use only one of `default` or `required` with `{node.func.id}`") - if match: - print('%s:%d:%d: use only one of `default` or `required` with `FieldAttribute`' % ( - path, line + 1, match.start(1) + 1)) + +def main() -> None: + for path in sys.argv[1:] or sys.stdin.read().splitlines(): + tree = ast.parse(pathlib.Path(path).read_text(), path) + CallVisitor(path).visit(tree) -if __name__ == '__main__': +if __name__ == "__main__": main() |