|
import ast |
|
import linecache |
|
from pathlib import Path |
|
|
|
|
|
root_path = Path('.') |
|
files = root_path.glob('**/*.py') |
|
|
|
class SuperVisitor(ast.NodeVisitor): |
|
def __init__(self, filename, *args, **kwargs): |
|
super().__init__(*args, **kwargs) |
|
self.filename = filename |
|
self.current_class_name = None |
|
self.interesting_super_lines = [] |
|
|
|
def visit_ClassDef(self, node): |
|
self.current_class_name = node.name |
|
|
|
for child_node in node.body: |
|
self.generic_visit(child_node) |
|
|
|
self.current_class_name = None |
|
|
|
return node |
|
|
|
def visit_Call(self, node): |
|
if ( |
|
self.current_class_name |
|
and hasattr(node, 'func') |
|
and getattr(node.func, 'id', None) == 'super' |
|
and hasattr(node, 'args') |
|
and len(node.args) == 2 |
|
): |
|
class_name_arg, self_arg = node.args |
|
if getattr(class_name_arg, 'id', None) != self.current_class_name: |
|
self.interesting_super_lines.append(node.lineno) |
|
|
|
for child_node in ast.walk(node): |
|
if child_node != node: |
|
self.generic_visit(child_node) |
|
|
|
return node |
|
|
|
|
|
|
|
for filename in map(str, files): |
|
|
|
with open(filename, 'r') as f: |
|
source = f.read() |
|
|
|
parsed = ast.parse(source, filename) |
|
|
|
node_visitor = SuperVisitor(filename) |
|
node_visitor.visit(parsed) |
|
if node_visitor.interesting_super_lines: |
|
print(filename, ":", node_visitor.interesting_super_lines) |