mirror of
https://github.com/pre-commit/pre-commit-hooks.git
synced 2026-03-29 10:16:52 +00:00
94 lines
2.6 KiB
Python
94 lines
2.6 KiB
Python
from __future__ import annotations
|
|
|
|
import argparse
|
|
import ast
|
|
import traceback
|
|
from typing import NamedTuple
|
|
from typing import Sequence
|
|
|
|
|
|
DEBUG_STATEMENTS = {
|
|
"ipdb",
|
|
"pdb",
|
|
"pdbr",
|
|
"pudb",
|
|
"pydevd_pycharm",
|
|
"q",
|
|
"rdb",
|
|
"rpdb",
|
|
"wdb",
|
|
}
|
|
|
|
|
|
class Debug(NamedTuple):
|
|
line: int
|
|
col: int
|
|
name: str
|
|
reason: str
|
|
|
|
|
|
class DebugStatementParser(ast.NodeVisitor):
|
|
def __init__(self) -> None:
|
|
self.breakpoints: list[Debug] = []
|
|
|
|
def visit_Import(self, node: ast.Import) -> None:
|
|
for name in node.names:
|
|
if name.name in DEBUG_STATEMENTS:
|
|
st = Debug(node.lineno, node.col_offset, name.name, "imported")
|
|
self.breakpoints.append(st)
|
|
|
|
def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
|
|
if node.module in DEBUG_STATEMENTS:
|
|
st = Debug(node.lineno, node.col_offset, node.module, "imported")
|
|
self.breakpoints.append(st)
|
|
|
|
def visit_Call(self, node: ast.Call) -> None:
|
|
"""python3.7+ breakpoint() and __import__"""
|
|
if isinstance(node.func, ast.Name):
|
|
if node.func.id == "breakpoint":
|
|
st = Debug(node.lineno, node.col_offset, node.func.id, "called")
|
|
self.breakpoints.append(st)
|
|
if (
|
|
node.func.id == "__import__"
|
|
and isinstance(node.args[0], ast.Constant)
|
|
and len(node.args) > 0
|
|
and node.args[0].value in DEBUG_STATEMENTS
|
|
):
|
|
st = Debug(node.lineno, node.col_offset, node.args[0].value, "imported")
|
|
self.breakpoints.append(st)
|
|
self.generic_visit(node)
|
|
|
|
|
|
def check_file(filename: str) -> int:
|
|
try:
|
|
with open(filename, "rb") as f:
|
|
ast_obj = ast.parse(f.read(), filename=filename)
|
|
except SyntaxError:
|
|
print(f"{filename} - Could not parse ast")
|
|
print()
|
|
print("\t" + traceback.format_exc().replace("\n", "\n\t"))
|
|
print()
|
|
return 1
|
|
|
|
visitor = DebugStatementParser()
|
|
visitor.visit(ast_obj)
|
|
|
|
for bp in visitor.breakpoints:
|
|
print(f"{filename}:{bp.line}:{bp.col}: {bp.name} {bp.reason}")
|
|
|
|
return int(bool(visitor.breakpoints))
|
|
|
|
|
|
def main(argv: Sequence[str] | None = None) -> int:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("filenames", nargs="*", help="Filenames to run")
|
|
args = parser.parse_args(argv)
|
|
|
|
retv = 0
|
|
for filename in args.filenames:
|
|
retv |= check_file(filename)
|
|
return retv
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|