Skip to content

Instantly share code, notes, and snippets.

@lmmx
Last active October 23, 2022 13:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lmmx/a931c50d7076e1a941c295db453baafd to your computer and use it in GitHub Desktop.
Save lmmx/a931c50d7076e1a941c295db453baafd to your computer and use it in GitHub Desktop.
Demo of overriding the function definition check in PyFlakes via subclass method, adapted from https://github.com/PyCQA/pyflakes/blob/master/pyflakes/api.py
import ast
from pyflakes import checker, reporter
class CheckerSnooper(checker.Checker):
verbose: bool
def __init__(self, *args, **kwargs):
self.verbose = kwargs.pop("verbose", False)
super().__init__(*args, **kwargs)
def FUNCTIONDEF(self, node):
super().FUNCTIONDEF(node)
line_range = f"{node.lineno}-{node.end_lineno}"
info = f"{type(node).__name__} {node.name!r} ({line_range=})"
setattr(node, "depth", self.get_ancestors(node, count=True))
if self.verbose:
print(f"{info} depth={node.depth} -> {node.returns.id}")
def get_ancestors(self, node, count=False) -> int:
ancestors = []
while parent := self.getParent(node):
if count and hasattr(node, "depth"):
return node.depth + len(ancestors)
ancestors.append(parent)
if parent is self.root:
return len(ancestors) if count else ancestors
node = parent
def parse(codestring, filename="", verbose=False) -> CheckerSnooper | None:
report = reporter._makeDefaultReporter()
try:
tree = ast.parse(codestring, filename=filename)
except SyntaxError as e:
report.syntaxError(filename, e.args[0], e.lineno, e.offset, e.text)
except Exception:
report.unexpectedError(filename, "problem decoding source")
else:
w = CheckerSnooper(tree, filename=filename, verbose=verbose)
w.messages.sort(key=lambda m: m.lineno)
if verbose:
for m in w.messages:
print(
f"• {type(m).__name__} {list(m.message_args)}",
f"L{m.lineno} col {m.col} in {filename or 'STDIN'}",
)
return w
return None
codestring = """
def DummyFunction(a: int) -> int:
class InnerClass():
def dummy_inner_class_method() -> int:
x = 2
return 1
return a + InnerClass().dummy_inner_class_method()
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment