Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python AST processing

I have a Python AST [as returned by ast.parse()].

I know this is an AST of a class method.

How do I find all calls to other methods of the same class?

Basically, I want to collect something like:

['foo', 'bar']

for a code snippet like:

def baz(self): # this is a class method
    '''baz docstring'''
    self.foo() + self.bar()

I need a function that will accept an AST and will return the list of other methods [method names as strings] of the class that are being invoked inside a method of the same class.

like image 967
Alex_coder Avatar asked Mar 04 '10 12:03

Alex_coder


People also ask

How does Python AST work?

The ast module helps Python applications to process trees of the Python abstract syntax grammar. The abstract syntax itself might change with each Python release; this module helps to find out programmatically what the current grammar looks like. An abstract syntax tree can be generated by passing ast.

What is AST process?

In computer science, an abstract syntax tree (AST), or just syntax tree, is a tree representation of the abstract syntactic structure of text (often source code) written in a formal language. Each node of the tree denotes a construct occurring in the text.

Is AST built into Python?

ast is a module in the python standard library. Python codes need to be converted to an Abstract Syntax Tree (AST) before becoming “byte code”(. pyc files).

What is AST call Python?

Call(func, args, keywords, starargs, kwargs) is a class in Python defined in the ast module that is used to express a function call in the form of an Abstract Syntax Tree.


1 Answers

The general approach is to subclass ast.NodeVisitor:

>>> class VisitCalls(ast.NodeVisitor):
...   def visit_Call(self, what):
...     if what.func.value.id == 'self':
...       print what.func.attr
... 
>>> f='''def x(self):
...   return self.bar() + self.baz()
... '''
>>> xx = ast.parse(f)
>>> VisitCalls().visit(xx)
bar
baz

However, this will only catch "immediate" calls to self.something. In the general case you could have e.g. somelist.append(self.blah) and then much later in the code somelist[i + j](): the problem of determining whether the latter is a call to self.blah or to some other callable that has nothing to do with methods of the current instance is Turing-complete (CS jargon for "completely insoluble in the general case", much like a mathematician might say "NP-hard";-).

But if all you need is to solve the simple "immediate call" case, you're good to go;-).

like image 75
Alex Martelli Avatar answered Sep 29 '22 12:09

Alex Martelli