ast manipulation

T

Tsize

Hello,

I am hoping for a little help. I have been playing with the python
ast module and have run into
an issue that I need a little push on. I would like to be able to
change a specific element in a
specific node in an ast then compile the resulting ast. Consider the
simplified example below
with its output. In this example I would like a way to change a
specific addition operation. With the NodeTransformer I see how to
change every addition operator but not how to change a specific one.
I would like this to work on both the 2.6 and 3.1 branches. Ideally I
would like to read a file, count the instances of an operation of
interest and then use an index to make the
changes.

I am probably missing something simple but I am lost right now.

import ast

class SwitchMinusPlus(ast.NodeTransformer):

def visit_BinOp(self, node):
node = self.generic_visit(node)
if isinstance(node.op, ast.Add):
node.op = ast.Sub()
return node

myfile = open('trivial.py').read()
print myfile
tree = compile(myfile, '<string>', 'exec', ast.PyCF_ONLY_AST)
print ast.dump(tree, annotate_fields=False, include_attributes=False)
node = SwitchMinusPlus().visit(ast.parse(myfile))
print ast.dump(node, annotate_fields=False, include_attributes=False)

Which gives the following output: Note that this code changes the
addition operator to an
subtraction operator at the AST level for every instance.

a = 8
b = 6
c = b + a
d = c + a
Module([Assign([Name('a', Store())], Num(8)), Assign([Name('b', Store
())], Num(6)),
Assign([Name('c', Store())], BinOp(Name('b', Load()), Add(), Name('a',
Load()))),
Assign([Name('d', Store())], BinOp(Name('c', Load()), Add(), Name('a',
Load())))])

Module([Assign([Name('a', Store())], Num(8)), Assign([Name('b', Store
())], Num(6)),
Assign([Name('c', Store())], BinOp(Name('b', Load()), Sub(), Name('a',
Load()))),
Assign([Name('d', Store())], BinOp(Name('c', Load()), Sub(), Name('a',
Load())))])

Thanks in advance,
Thomas
 
T

Terry Reedy

Tsize said:
Hello,

I am hoping for a little help. I have been playing with the python
ast module and have run into
an issue that I need a little push on. I would like to be able to
change a specific element in a
specific node in an ast then compile the resulting ast.

If you can identify the specific nodes you want to change, no problem
Consider the simplified example below
with its output. In this example I would like a way to change a
specific addition operation. With the NodeTransformer I see how to
change every addition operator but not how to change a specific one.

Which specific one or one?
I would like this to work on both the 2.6 and 3.1 branches. Ideally I
would like to read a file, count the instances of an operation of
interest and then use an index to make the changes.

If 'specific one' means number i, great. In not, not.
I am probably missing something simple but I am lost right now.

You have not said what 'specific one' means.
Nor what your general goal is, why you want to change asts.
import ast

class SwitchMinusPlus(ast.NodeTransformer):

def visit_BinOp(self, node):
node = self.generic_visit(node)
if isinstance(node.op, ast.Add):

if isinstance(node.op, ast.Add) and isspecificnode(node):
node.op = ast.Sub()
return node

myfile = open('trivial.py').read()
print myfile
tree = compile(myfile, '<string>', 'exec', ast.PyCF_ONLY_AST)
print ast.dump(tree, annotate_fields=False, include_attributes=False)
node = SwitchMinusPlus().visit(ast.parse(myfile))
print ast.dump(node, annotate_fields=False, include_attributes=False)

Which gives the following output: Note that this code changes the
addition operator to an
subtraction operator at the AST level for every instance.

a = 8
b = 6
c = b + a
d = c + a
Module([Assign([Name('a', Store())], Num(8)), Assign([Name('b', Store
())], Num(6)),
Assign([Name('c', Store())], BinOp(Name('b', Load()), Add(), Name('a',
Load()))),
Assign([Name('d', Store())], BinOp(Name('c', Load()), Add(), Name('a',
Load())))])

Module([Assign([Name('a', Store())], Num(8)), Assign([Name('b', Store
())], Num(6)),
Assign([Name('c', Store())], BinOp(Name('b', Load()), Sub(), Name('a',
Load()))),
Assign([Name('d', Store())], BinOp(Name('c', Load()), Sub(), Name('a',
Load())))])
 
T

Tsize

Terry,

Thank you for responding. I actually figured out how to do this
shortly after posting the message. Sorry I wasn't quite clear enough
in my post, I will try to be a little more explict in the future.
Just to mention it I want to go to each node in the ast including
child nodes and change the values. I am making a limited mutation
analysis program. If it looks generally useful as I get further along
I will release the code. I did an early prototype that worked on the
text of the code itself but I thought that using the ast for this
would be better and maybe a little faster.

Regards,
Thomas
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,189
Members
46,734
Latest member
manin

Latest Threads

Top