google / pasta

Library to refactor python code through AST manipulation.
Apache License 2.0
341 stars 40 forks source link

Bad indentation when rewriting funcion body (new bug) #76

Closed cript0nauta closed 5 years ago

cript0nauta commented 5 years ago

Hi! I found an issue similar to #62. When certain conditions are met and I rewrite the body of a function, it won't be properly indented, therefore it will produce incorrect or syntactically invalid code.

I found the bug while rewriting some parts of this HostImporter class. I shrinked the code to find the minimum code required to trigger the bug and ended up with this:

import ast
import pasta

source_code = '''
class K(object):
    def f1():
        if True:
            yield host_ip
            pass

    def f2():
        pass
'''

class SampleTransformer(ast.NodeTransformer):
    def visit_FunctionDef(self, node):
        node.body = [ast.copy_location(ast.Pass(), node.body[0])]
        return node

tree = pasta.parse(source_code)
SampleTransformer().visit(tree)

print pasta.dump(tree)

The expected output of running this script should be

class K(object):
    def f1():
        pass
    def f2():
        pass

But the output is this instead:

class K(object):
    def f1():
        pass
def f2():
        pass

This code is incorrect, but not yet syntactically invalid. If you add a third f3() method to the K class, then the output will be:

class K(object):
    def f1():
        pass
def f2():
        pass
    def f3():
        pass

This will raise a SyntaxError when executed.

soupytwist commented 5 years ago

Thanks for reporting and including a simple case to reproduce it. I will revisit this soon when I get the chance!

soupytwist commented 5 years ago

Python continues to surprise me... no clue why ast.Yield is an expression and not a statement, but it seems it is. Thanks for uncovering this bug, and its interesting side effect.

cript0nauta commented 5 years ago

It works now, thanks!