When I write scripts, I have a common library of personal functions that I use by lazily importing the whole thing. So I wanted to clean that up so instead of importing thousands of lines of code, I could have a script automatically select the functions I need for that particular script and copy them into a file for publication. I got that working using a combination of ast
and inspect
, but now I want to copy the exact line of code where global variables are defined inside of my module.
For example if I use the shortcut eprint
in the script it should scrape the line: eprint = Eprinter(verbose=1).eprint
which creates a shortcut to a class method.
I'm trying to adopt the code I found here: https://stackoverflow.com/a/13230346/11343425
class GetAssignments(ast.NodeVisitor):
def visit_Name(self, node):
if isinstance(node.ctx, ast.Store):
if node.id == 'eprint':
print(node.id, node.lineno)
return node.lineno
code = inspect.getsource(printing)
a = GetAssignments()
b = a.visit(ast.parse(code))
print('b =', b)
This will print the node.lineno just fine, but it returns None and I can't figure out why.
ast.NodeVisitor is meant to be subclassed which means visit_Name
can't return anything. However, a custom function can be an intermediary like so:
class GetAssignments(ast.NodeVisitor):
def visit_Name(self, node):
if isinstance(node.ctx, ast.Store):
if node.id == self.expr:
print("Found line number", node.lineno)
self.lineno = node.lineno
def search(self, node, expr):
self.expr = expr
self.visit(node)
return self.lineno
code = inspect.getsource(printing)
lineno = GetAssignments().search(ast.parse(code), 'eprint')
line = code.split('\n')[lineno-1]
print(lineno, line)