(root)/
Python-3.12.0/
Tools/
peg_generator/
pegen/
ast_dump.py
       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]