Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I would like to format the following ast parse:
>>> import ast
>>> print(ast.dump(ast.parse('-a+b')))
Module(body=[Expr(value=BinOp(left=UnaryOp(op=USub(), operand=Name(id='a', ctx=Load())), op=Add(), right=Name(id='b', ctx=Load())))])
It seems like the indent
option was introduced in python3.9, but I don't see an option to 'pretty-print' before then. What options are there to print a nicely-formatting output for an the syntax tree?
If you need to pretty-print the AST in an earlier python version and are happy with the indent function in Python3.9 why not just take the dump
function from 3.9 and implement it in your project? The source code is here: https://github.com/python/cpython/blob/e56d54e447694c6ced2093d2273c3e3d60b36b6f/Lib/ast.py#L111-L175
And it doesn't look very complicated and doesn't seem to use any features specific to 3.9.
I had one use case in which I couldn't upgrade to Python 3.9 (where indent argument was added), yet I needed a way to prettify the result of ast.dump
.
I wrote the following method that can take an unformatted ast.dump
output and print that in a way that is easier on the eyes.
def prettify(ast_tree_str, indent=4):
ret = []
stack = []
in_string = False
curr_indent = 0
for i in range(len(ast_tree_str)):
char = ast_tree_str[i]
if in_string and char != '\'' and char != '"':
ret.append(char)
elif char == '(' or char == '[':
ret.append(char)
if i < len(ast_tree_str) - 1:
next_char = ast_tree_str[i+1]
if next_char == ')' or next_char == ']':
curr_indent += indent
stack.append(char)
continue
print(''.join(ret))
ret.clear()
curr_indent += indent
ret.append(' ' * curr_indent)
stack.append(char)
elif char == ',':
ret.append(char)
print(''.join(ret))
ret.clear()
ret.append(' ' * curr_indent)
elif char == ')' or char == ']':
ret.append(char)
curr_indent -= indent
stack.pop()
elif char == '\'' or char == '"':
if (len(ret) > 0 and ret[-1] == '\\') or (in_string and stack[-1] != char):
ret.append(char)
continue
if len(stack) > 0 and stack[-1] == char:
ret.append(char)
in_string = False
stack.pop()
continue
in_string = True
ret.append(char)
stack.append(char)
elif char == ' ':
else:
ret.append(char)
print(''.join(ret))
Usage:
if __name__ == '__main__':
content = """
@testdecorator
def my_method(a, b):
def ola():
print("Hello")
ola()
return (a + b) * 5 + "dasdas,da'sda\\'asdas\\'\\'"
ast_tree = ast.parse(source=content)
prettify(ast.dump(ast_tree))
PS.: It's not 100% equivalent to what one could get out of the Python 3.9 ast.dump(...., indent=n)
but it should be enough for now. Feel free to improve it
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.