From 1f962564f955eb86aa5de9cd874acfaf2a1ed3ce Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Wed, 2 Apr 2025 10:40:10 -0700 Subject: [PATCH 1/2] gh-118761: Fix star-import of ast (alternative) --- Lib/_ast_unparse.py | 10 +--------- Lib/ast.py | 21 +++++++++------------ 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/Lib/_ast_unparse.py b/Lib/_ast_unparse.py index c03f9bd4c1d40b..56d9e935dd9d87 100644 --- a/Lib/_ast_unparse.py +++ b/Lib/_ast_unparse.py @@ -6,8 +6,6 @@ from contextlib import contextmanager, nullcontext from enum import IntEnum, auto, _simple_enum -__all__ = ('unparse',) - # Large float and imaginary literals get turned into infinities in the AST. # We unparse those infinities to INFSTR. _INFSTR = "1e" + repr(sys.float_info.max_10_exp + 1) @@ -48,7 +46,7 @@ def next(self): _MULTI_QUOTES = ('"""', "'''") _ALL_QUOTES = (*_SINGLE_QUOTES, *_MULTI_QUOTES) -class _Unparser(NodeVisitor): +class Unparser(NodeVisitor): """Methods in this class recursively traverse an AST and output source code for the abstract syntax; original formatting is disregarded.""" @@ -1142,9 +1140,3 @@ def visit_MatchOr(self, node): with self.require_parens(_Precedence.BOR, node): self.set_precedence(_Precedence.BOR.next(), *node.patterns) self.interleave(lambda: self.write(" | "), self.traverse, node.patterns) - - -def unparse(ast_obj): - unparser = _Unparser() - return unparser.visit(ast_obj) -unparse.__module__ = 'ast' # backwards compatibility diff --git a/Lib/ast.py b/Lib/ast.py index 8be4f68455150a..976a2725e9c751 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -620,6 +620,15 @@ class AugStore(expr_context): class Param(expr_context): """Deprecated AST node class. Unused in Python 3.""" +_Unparser = None + +def unparse(ast_obj): + global _Unparser + if _Unparser is None: + from _ast_unparse import Unparser as _Unparser + unparser = _Unparser() + return unparser.visit(ast_obj) + def main(): import argparse @@ -651,15 +660,3 @@ def main(): if __name__ == '__main__': main() - -def __dir__(): - dir_ = {n for n in globals() if not n.startswith('_') and n != 'sys'} - return sorted(dir_ | {'unparse'}) - -def __getattr__(name): - if name == 'unparse': - global unparse - from _ast_unparse import unparse - return unparse - - raise AttributeError(f'module {__name__!r} has no attribute {name!r}') From 8166a7798ae0f7665eef466a2d11d6355435d345 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Wed, 2 Apr 2025 10:50:27 -0700 Subject: [PATCH 2/2] Suggestion from Adam --- Lib/ast.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Lib/ast.py b/Lib/ast.py index 976a2725e9c751..507fec5f2d3890 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -24,7 +24,6 @@ :copyright: Copyright 2008 by Armin Ronacher. :license: Python License. """ -import sys from _ast import * @@ -620,18 +619,20 @@ class AugStore(expr_context): class Param(expr_context): """Deprecated AST node class. Unused in Python 3.""" -_Unparser = None def unparse(ast_obj): global _Unparser - if _Unparser is None: + try: + unparser = _Unparser() + except NameError: from _ast_unparse import Unparser as _Unparser - unparser = _Unparser() + unparser = _Unparser() return unparser.visit(ast_obj) def main(): import argparse + import sys parser = argparse.ArgumentParser() parser.add_argument('infile', nargs='?', default='-',