1""" 2Copy-parse of ast.dump, removing the `isinstance` checks. This is needed, 3because testing pegen requires generating a C extension module, which contains 4a copy of the symbols defined in Python-ast.c. Thus, the isinstance check would 5always fail. We rely on string comparison of the base classes instead. 6TODO: Remove the above-described hack. 7""" 8 9 10def ast_dump(node, annotate_fields=True, include_attributes=False, *, indent=None): 11 def _format(node, level=0): 12 if indent is not None: 13 level += 1 14 prefix = "\n" + indent * level 15 sep = ",\n" + indent * level 16 else: 17 prefix = "" 18 sep = ", " 19 if any(cls.__name__ == "AST" for cls in node.__class__.__mro__): 20 cls = type(node) 21 args = [] 22 allsimple = True 23 keywords = annotate_fields 24 for name in node._fields: 25 try: 26 value = getattr(node, name) 27 except AttributeError: 28 keywords = True 29 continue 30 if value is None and getattr(cls, name, ...) is None: 31 keywords = True 32 continue 33 value, simple = _format(value, level) 34 allsimple = allsimple and simple 35 if keywords: 36 args.append("%s=%s" % (name, value)) 37 else: 38 args.append(value) 39 if include_attributes and node._attributes: 40 for name in node._attributes: 41 try: 42 value = getattr(node, name) 43 except AttributeError: 44 continue 45 if value is None and getattr(cls, name, ...) is None: 46 continue 47 value, simple = _format(value, level) 48 allsimple = allsimple and simple 49 args.append("%s=%s" % (name, value)) 50 if allsimple and len(args) <= 3: 51 return "%s(%s)" % (node.__class__.__name__, ", ".join(args)), not args 52 return "%s(%s%s)" % (node.__class__.__name__, prefix, sep.join(args)), False 53 elif isinstance(node, list): 54 if not node: 55 return "[]", True 56 return "[%s%s]" % (prefix, sep.join(_format(x, level)[0] for x in node)), False 57 return repr(node), True 58 59 if all(cls.__name__ != "AST" for cls in node.__class__.__mro__): 60 raise TypeError("expected AST, got %r" % node.__class__.__name__) 61 if indent is not None and not isinstance(indent, str): 62 indent = " " * indent 63 return _format(node)[0] 64