17db96d56Sopenharmony_ci"""
27db96d56Sopenharmony_ciCopy-parse of ast.dump, removing the `isinstance` checks. This is needed,
37db96d56Sopenharmony_cibecause testing pegen requires generating a C extension module, which contains
47db96d56Sopenharmony_cia copy of the symbols defined in Python-ast.c. Thus, the isinstance check would
57db96d56Sopenharmony_cialways fail. We rely on string comparison of the base classes instead.
67db96d56Sopenharmony_ciTODO: Remove the above-described hack.
77db96d56Sopenharmony_ci"""
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_cifrom typing import Any, Optional, Tuple
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_ci
127db96d56Sopenharmony_cidef ast_dump(
137db96d56Sopenharmony_ci    node: Any,
147db96d56Sopenharmony_ci    annotate_fields: bool = True,
157db96d56Sopenharmony_ci    include_attributes: bool = False,
167db96d56Sopenharmony_ci    *,
177db96d56Sopenharmony_ci    indent: Optional[str] = None,
187db96d56Sopenharmony_ci) -> str:
197db96d56Sopenharmony_ci    def _format(node: Any, level: int = 0) -> Tuple[str, bool]:
207db96d56Sopenharmony_ci        if indent is not None:
217db96d56Sopenharmony_ci            level += 1
227db96d56Sopenharmony_ci            prefix = "\n" + indent * level
237db96d56Sopenharmony_ci            sep = ",\n" + indent * level
247db96d56Sopenharmony_ci        else:
257db96d56Sopenharmony_ci            prefix = ""
267db96d56Sopenharmony_ci            sep = ", "
277db96d56Sopenharmony_ci        if any(cls.__name__ == "AST" for cls in node.__class__.__mro__):
287db96d56Sopenharmony_ci            cls = type(node)
297db96d56Sopenharmony_ci            args = []
307db96d56Sopenharmony_ci            allsimple = True
317db96d56Sopenharmony_ci            keywords = annotate_fields
327db96d56Sopenharmony_ci            for name in node._fields:
337db96d56Sopenharmony_ci                try:
347db96d56Sopenharmony_ci                    value = getattr(node, name)
357db96d56Sopenharmony_ci                except AttributeError:
367db96d56Sopenharmony_ci                    keywords = True
377db96d56Sopenharmony_ci                    continue
387db96d56Sopenharmony_ci                if value is None and getattr(cls, name, ...) is None:
397db96d56Sopenharmony_ci                    keywords = True
407db96d56Sopenharmony_ci                    continue
417db96d56Sopenharmony_ci                value, simple = _format(value, level)
427db96d56Sopenharmony_ci                allsimple = allsimple and simple
437db96d56Sopenharmony_ci                if keywords:
447db96d56Sopenharmony_ci                    args.append("%s=%s" % (name, value))
457db96d56Sopenharmony_ci                else:
467db96d56Sopenharmony_ci                    args.append(value)
477db96d56Sopenharmony_ci            if include_attributes and node._attributes:
487db96d56Sopenharmony_ci                for name in node._attributes:
497db96d56Sopenharmony_ci                    try:
507db96d56Sopenharmony_ci                        value = getattr(node, name)
517db96d56Sopenharmony_ci                    except AttributeError:
527db96d56Sopenharmony_ci                        continue
537db96d56Sopenharmony_ci                    if value is None and getattr(cls, name, ...) is None:
547db96d56Sopenharmony_ci                        continue
557db96d56Sopenharmony_ci                    value, simple = _format(value, level)
567db96d56Sopenharmony_ci                    allsimple = allsimple and simple
577db96d56Sopenharmony_ci                    args.append("%s=%s" % (name, value))
587db96d56Sopenharmony_ci            if allsimple and len(args) <= 3:
597db96d56Sopenharmony_ci                return "%s(%s)" % (node.__class__.__name__, ", ".join(args)), not args
607db96d56Sopenharmony_ci            return "%s(%s%s)" % (node.__class__.__name__, prefix, sep.join(args)), False
617db96d56Sopenharmony_ci        elif isinstance(node, list):
627db96d56Sopenharmony_ci            if not node:
637db96d56Sopenharmony_ci                return "[]", True
647db96d56Sopenharmony_ci            return "[%s%s]" % (prefix, sep.join(_format(x, level)[0] for x in node)), False
657db96d56Sopenharmony_ci        return repr(node), True
667db96d56Sopenharmony_ci
677db96d56Sopenharmony_ci    if all(cls.__name__ != "AST" for cls in node.__class__.__mro__):
687db96d56Sopenharmony_ci        raise TypeError("expected AST, got %r" % node.__class__.__name__)
697db96d56Sopenharmony_ci    if indent is not None and not isinstance(indent, str):
707db96d56Sopenharmony_ci        indent = " " * indent
717db96d56Sopenharmony_ci    return _format(node)[0]
72