Andrew
Andrew

Reputation: 2157

How to get the first function call argument via AST?

I'm trying to get arguments from a function call. For example we have such function call sample:

self.assertEqual(dictlike.fromkeys('a'), {'a':None})

I use such code:

import ast


class CallVisitor(ast.NodeVisitor):
    def visit_Call(self, node):
        print('Node type: Call\nFields: ', node._fields)
        ast.NodeVisitor.generic_visit(self, node)

    def visit_Name(self, node):
        print('Node type: Name\nFields: ', node._fields)
        ast.NodeVisitor.generic_visit(self, node)

    def visit_Constant(self, node):
        print('Node type: Constant\nFields: ', node._fields)
        ast.NodeVisitor.generic_visit(self, node)

    def visit_keyword(self, node):
        print('Node type: keyword\nFields: ', node._fields)
        ast.NodeVisitor.generic_visit(self, node)

    def visit_FunctionDef(self,node):
        print('Node type: FunctionDef\nFields:', node.fields)
        ast.NodeVisitor.generic_visit(self, node)


if __name__ == '__main__':
    source = """self.assertEqual(dictlike.fromkeys('a'), {'a':None})"""

    root = ast.parse(source)
    for node in ast.walk(root):
        if isinstance(node, ast.Name) and isinstance(node.ctx, ast.Store):
            print(node.id)
        elif isinstance(node, ast.Attribute):
            print(node.attr)

and I receive such output:

assertEqual
fromkeys

I also tried to get it from the dump: print (ast.dump(node))

but I didn't manage to get certain field:

Module(body=[Expr(value=Call(func=Attribute(value=Name(id='self', ctx=Load()), attr='assertEqual', ctx=Load()), args=[Call(func=Attribute(value=Name(id='dictlike', ctx=Load()), attr='fromkeys', ctx=Load()), args=[Constant(value='a', kind=None)], keywords=[]), Dict(keys=[Constant(value='a', kind=None)], values=[Constant(value=None, kind=None)])], keywords=[]))], type_ignores=[])

for example I tried such way:

print(node.args[0])

finally I would like to receive:

dictlike.fromkeys('a')

maybe I did something wrong ?

Upvotes: 2

Views: 802

Answers (1)

Ajax1234
Ajax1234

Reputation: 71451

Assuming you are attempting to extract the parameters from assertion test cases in your source, you can use ast.walk:

import ast
source = """self.assertEqual(dictlike.fromkeys('a'), {'a':None})"""
r = [[*map(ast.unparse, i.args+i.keywords)] for i in ast.walk(ast.parse(source)) 
     if isinstance(i, ast.Call) and getattr(i.func, 'attr', '').startswith('assert')]

Output:

[["dictlike.fromkeys('a')", "{'a': None}"]]

Upvotes: 0

Related Questions