[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/RustPython/RustPython/main/scripts/check_redundant_patches.py [Back]  [Original]

#!/usr/bin/env python3
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))

Web Proxy Viewer  |  New URL  |  Original Page