Skip to content

Instantly share code, notes, and snippets.

@tirkarthi
Last active August 31, 2019 12:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tirkarthi/94f5dcd90757bee982980afe94cec82e to your computer and use it in GitHub Desktop.
Save tirkarthi/94f5dcd90757bee982980afe94cec82e to your computer and use it in GitHub Desktop.
ast.dump implementation using list of generated strings
import ast
from _ast import *
def dump(node, annotate_fields=True, include_attributes=False, indent=None):
def _format(node, level=0):
if indent is not None:
level += 1
prefix = '\n' + indent * level
sep = ',\n' + indent * level
else:
prefix = ''
sep = ', '
if isinstance(node, AST):
args = []
keywords = annotate_fields
for field in node._fields:
try:
value = getattr(node, field)
except AttributeError:
keywords = True
else:
if keywords:
args.append('%s=%s' % (field, _format(value, level)))
else:
args.append(_format(value, level))
if include_attributes and node._attributes:
for a in node._attributes:
try:
args.append('%s=%s' % (a, _format(getattr(node, a), level)))
except AttributeError:
pass
if not args:
return '%s()' % (node.__class__.__name__,)
return '%s(%s%s)' % (node.__class__.__name__, prefix, sep.join(args))
elif isinstance(node, list):
if not node:
return '[]'
return '[%s%s]' % (prefix, sep.join(_format(x, level) for x in node))
return repr(node)
if not isinstance(node, AST):
raise TypeError('expected AST, got %r' % node.__class__.__name__)
if indent is not None and not isinstance(indent, str):
indent = ' ' * indent
return _format(node)
def dump_cached(node, annotate_fields=True, include_attributes=False, indent=None):
def _format(node, level=0):
if indent is not None:
level += 1
try:
prefix = indentations[level]
except IndexError:
child_indentation = indentations[level - 1] + indent
prefix = '\n' + indent * level
indentations.append(prefix)
sep = ',\n' + indent * level
else:
prefix = ''
sep = ', '
if isinstance(node, AST):
args = []
keywords = annotate_fields
for field in node._fields:
try:
value = getattr(node, field)
except AttributeError:
keywords = True
else:
if keywords:
args.append('%s=%s' % (field, _format(value, level)))
else:
args.append(_format(value, level))
if include_attributes and node._attributes:
for a in node._attributes:
try:
args.append('%s=%s' % (a, _format(getattr(node, a), level)))
except AttributeError:
pass
if not args:
return '%s()' % (node.__class__.__name__,)
return '%s(%s%s)' % (node.__class__.__name__, prefix, sep.join(args))
elif isinstance(node, list):
if not node:
return '[]'
return '[%s%s]' % (prefix, sep.join(_format(x, level) for x in node))
return repr(node)
if not isinstance(node, AST):
raise TypeError('expected AST, got %r' % node.__class__.__name__)
if indent is not None:
if not isinstance(indent, str):
indent = ' ' * indent
indentations = ["\n" + indent]
return _format(node)
obj = ast.parse("1 + 1 == 2" * 100)
assert dump(obj) == dump_cached(obj)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment