'How to find ast nodes and its sub nodes in Python
I am trying to traverse through ast nodes in Python to fetch value node's Name ids for all Assign Nodes. Ast.walk() method gives me nodes randomly.
Assumption : Only for Assign nodes
for node in ast.walk(tree):
if isinstance(node,(ast.Assign)):
if isinstance(node.value,(ast.Name)):
print('Assign Value:-','lineno: ',node.value.lineno,' id :',node.value.id)
if isinstance(node.value,(ast.Tuple)):
for i in range(len(node.value.elts)):
if isinstance(node.value.elts[i],(ast.Name)):
print('Assign Value:-','lineno: ',node.value.elts[i].lineno,' id :',node.value.elts[i].id)
Here, sometimes ast gives BinOps, Call etc inside value node. I have to get Name.id inside value node.
Ex: a,b = (c+d), e --> Expected Values should be c,d,e..but I get only e . Also, how to tag (c,d) to target 'a' .
Target can be fetched from Assign Node .
Solution 1:[1]
You can walk
the original ast
, and for every ast.Assign
, recursively extract target names and associated value id
s:
import ast
def names(a):
return [i.id for i in ast.walk(a) if isinstance(i, ast.Name)]
def bindings(target, value):
if isinstance(target, ast.Name):
yield [target.id, names(value)]
elif isinstance(target, (ast.List, ast.Tuple)):
if not isinstance(value, (ast.List, ast.Tuple)):
yield [tuple(names(target)), names(value)]
else:
for a, b in zip(target.elts, value.elts):
yield from bindings(a, b)
def assign_bindings(s):
return [dict(bindings(i.targets[0], i.value)) for i in ast.walk(ast.parse(s))
if isinstance(i, ast.Assign)]
The code above allows you to pass assign_bindings
a source string that has assignment statements with unpacking, single name bindings, tuples, expressions, etc:
print(assign_bindings('a, b = (c+d), e'))
print(assign_bindings('a, [b, c, [d, [e]]] = [n1, [n2, n3, [n4, [n5]]]]'))
print(assign_bindings('vals = func(a + b)'))
Output:
[{'a': ['c', 'd'], 'b': ['e']}]
[{'a': ['n1'], 'b': ['n2'], 'c': ['n3'], 'd': ['n4'], 'e': ['n5']}]
[{'vals': ['func', 'a', 'b']}]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Ajax1234 |