forked from RustPython/RustPython
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcheck_redundant_patches.py
More file actions
92 lines (71 loc) · 2.37 KB
/
check_redundant_patches.py
File metadata and controls
92 lines (71 loc) · 2.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#!/usr/bin/env python
import argparse
import ast
import glob
import os
import pathlib
import sys
ROOT = pathlib.Path(__file__).parents[1]
TEST_DIR = ROOT / "Lib" / "test"
IS_GH_CI = "GITHUB_ACTIONS" in os.environ
def build_argparser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(prog="check_redundant_patches")
parser.add_argument(
"patterns",
nargs="*",
default=[f"{TEST_DIR}/**/*.py"],
help="Glob patterns (e.g. foo/bar/**.py a/b/file.py)",
)
return parser
def iter_files(patterns: list[str]):
seen = set()
for pattern in set(patterns):
matches = glob.glob(pattern, recursive=True)
for path in matches:
if path in seen:
continue
seen.add(path)
yield path
def main(patterns: list[str]):
exit_status = 0
for file in map(pathlib.Path, iter_files(patterns)):
if file.is_dir():
continue
try:
contents = file.read_text(encoding="utf-8")
except UnicodeDecodeError:
continue
try:
tree = ast.parse(contents)
except SyntaxError:
continue
cls_name = None
for node in ast.walk(tree):
if isinstance(node, ast.ClassDef):
cls_name = node.name
if not isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
continue
name = node.name
if not name.startswith("test"):
continue
if node.decorator_list:
continue
func_code = ast.unparse(node.body)
if func_code in (
f"await super().{name}()",
f"return await super().{name}()",
f"return super().{name}()",
f"super().{name}()",
):
exit_status += 1
lineno = node.lineno
msg = f"{file}:{lineno}:{cls_name}.{name} is a test patch that can be safely removed"
if IS_GH_CI:
end_lineno = node.end_lineno
msg = f"::error file={file},line={lineno},endLine={end_lineno},title=Redundant Test Patch::{msg}"
print(msg, file=sys.stderr)
return exit_status
if __name__ == "__main__":
parser = build_argparser()
args = parser.parse_args()
exit(main(args.patterns))