mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 18:07:37 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			69 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			69 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """
 | |
| Copy-parse of ast.dump, removing the `isinstance` checks. This is needed,
 | |
| because testing pegen requires generating a C extension module, which contains
 | |
| a copy of the symbols defined in Python-ast.c. Thus, the isinstance check would
 | |
| always fail. We rely on string comparison of the base classes instead.
 | |
| TODO: Remove the above-described hack.
 | |
| """
 | |
| 
 | |
| from typing import Any, Optional, Tuple
 | |
| 
 | |
| 
 | |
| def ast_dump(
 | |
|     node: Any,
 | |
|     annotate_fields: bool = True,
 | |
|     include_attributes: bool = False,
 | |
|     *,
 | |
|     indent: Optional[str] = None,
 | |
| ) -> str:
 | |
|     def _format(node: Any, level: int = 0) -> Tuple[str, bool]:
 | |
|         if indent is not None:
 | |
|             level += 1
 | |
|             prefix = "\n" + indent * level
 | |
|             sep = ",\n" + indent * level
 | |
|         else:
 | |
|             prefix = ""
 | |
|             sep = ", "
 | |
|         if any(cls.__name__ == "AST" for cls in node.__class__.__mro__):
 | |
|             cls = type(node)
 | |
|             args = []
 | |
|             allsimple = True
 | |
|             keywords = annotate_fields
 | |
|             for name in node._fields:
 | |
|                 try:
 | |
|                     value = getattr(node, name)
 | |
|                 except AttributeError:
 | |
|                     keywords = True
 | |
|                     continue
 | |
|                 if value is None and getattr(cls, name, ...) is None:
 | |
|                     keywords = True
 | |
|                     continue
 | |
|                 value, simple = _format(value, level)
 | |
|                 allsimple = allsimple and simple
 | |
|                 if keywords:
 | |
|                     args.append("%s=%s" % (name, value))
 | |
|                 else:
 | |
|                     args.append(value)
 | |
|             if include_attributes and node._attributes:
 | |
|                 for name in node._attributes:
 | |
|                     try:
 | |
|                         value = getattr(node, name)
 | |
|                     except AttributeError:
 | |
|                         continue
 | |
|                     if value is None and getattr(cls, name, ...) is None:
 | |
|                         continue
 | |
|                     value, simple = _format(value, level)
 | |
|                     allsimple = allsimple and simple
 | |
|                     args.append("%s=%s" % (name, value))
 | |
|             if allsimple and len(args) <= 3:
 | |
|                 return "%s(%s)" % (node.__class__.__name__, ", ".join(args)), not args
 | |
|             return "%s(%s%s)" % (node.__class__.__name__, prefix, sep.join(args)), False
 | |
|         elif isinstance(node, list):
 | |
|             if not node:
 | |
|                 return "[]", True
 | |
|             return "[%s%s]" % (prefix, sep.join(_format(x, level)[0] for x in node)), False
 | |
|         return repr(node), True
 | |
| 
 | |
|     if all(cls.__name__ != "AST" for cls in node.__class__.__mro__):
 | |
|         raise TypeError("expected AST, got %r" % node.__class__.__name__)
 | |
|     return _format(node)[0]
 | 
