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