abstract syntax tree - Python NodeTransformer: how to remove nodes? -
i'm playing around ast manipulations. i'm trying remove nodes input ast. nodetransformer class appropriate tool purpose, think. sadly, doesn't behave expected.
the documetation says:
"the nodetransformer walk ast , use return value of visitor methods replace or remove old node. if return value of visitor method none, node removed location, otherwise replaced return value."
now @ program:
import _ast import ast import sys #ast transformer class mytransformer(ast.nodetransformer): def iterate_children(self, node): """ helper """ children = ast.iter_child_nodes(node) c in children: self.visit(c) def generic_visit(self, node): """ default behaviour """ print("visiting: "+node.__class__.__name__) self.iterate_children(node) return node def visit_for(self, node): """ nodes: replace nothing """ print("removing node") return none #read source program filename = sys.argv[1] open (filename, "r") myfile: source = str(myfile.read()) #compile source ast m = compile(source, "<string>", "exec", _ast.pycf_only_ast) #do ast manipulation t = mytransformer() t.visit(m) # fix locations m = ast.fix_missing_locations(m) #visualize resulting ast #p = astprinter() #p.fromast(m) #execute transformed program print("computing...") codeobj = compile(m, '<string>', 'exec') exec(codeobj) here input file:
l = [0, 1, 2, 3] total = 0 in l: total += print(total) and outcome:
visiting: module visiting: assign visiting: name visiting: store visiting: list visiting: num visiting: num visiting: num visiting: num visiting: load visiting: assign visiting: name visiting: store visiting: num removing node visiting: expr visiting: call visiting: name visiting: load visiting: name visiting: load computing... 6 i expected '0', because loop has been removed. there '6' (=0+1+2+3).
does know why?
python version: 3.2.3
the numbers in ( ) indicate line number in input program. code image drawing not provided here; please ignore "root" node. can see, loop still there.
thanks reading!
update 21.8.:
i posted link question on python mailinglist (python-list@python.org). seems did overwriting. without children visitor, works expected.
entire source code of mytransformer:
class mytransformer(ast.nodetransformer): def visit_for(self, node): """ nodes: replace nothing """ print("removing node") return none
no, works correctly because removed self-written generic_visit(). can see in source code of ast.py, nodetransformer child of nodevisitor, has own generic_visit() method. method performs updating of ast nodes , if override method, should know doing for. overriding change logic of nodetransformer.
if still need override generic_visit() (for example print messages visiting: <ast object> when visit node), you have call parent method in generic_visit(). so, method next:
def generic_visit(self, node): """ printing visit messages """ super().generic_visit(node) print("visiting: "+node.__class__.__name__) self.iterate_children(node) return node the iterate_children() doesn't affect result in case, must removed. forces visitor run over children of each node. generic_visit() runs on nodes. so, iterate_children() visit nodes more once. wastes computing time , may give errors in more complex cases.
Comments
Post a Comment