@@ -294,9 +294,7 @@ def get_docstring(node, clean=True):
294294 if not (node .body and isinstance (node .body [0 ], Expr )):
295295 return None
296296 node = node .body [0 ].value
297- if isinstance (node , Str ):
298- text = node .s
299- elif isinstance (node , Constant ) and isinstance (node .value , str ):
297+ if isinstance (node , Constant ) and isinstance (node .value , str ):
300298 text = node .value
301299 else :
302300 return None
@@ -499,27 +497,66 @@ def generic_visit(self, node):
499497 return node
500498
501499
500+ _DEPRECATED_VALUE_ALIAS_MESSAGE = (
501+ "{name} is deprecated and will be removed in Python {remove}; use value instead"
502+ )
503+ _DEPRECATED_CLASS_MESSAGE = (
504+ "{name} is deprecated and will be removed in Python {remove}; "
505+ "use ast.Constant instead"
506+ )
507+
508+
502509# If the ast module is loaded more than once, only add deprecated methods once
503510if not hasattr (Constant , 'n' ):
504511 # The following code is for backward compatibility.
505512 # It will be removed in future.
506513
507- def _getter (self ):
514+ def _n_getter (self ):
515+ """Deprecated. Use value instead."""
516+ import warnings
517+ warnings ._deprecated (
518+ "Attribute n" , message = _DEPRECATED_VALUE_ALIAS_MESSAGE , remove = (3 , 14 )
519+ )
520+ return self .value
521+
522+ def _n_setter (self , value ):
523+ import warnings
524+ warnings ._deprecated (
525+ "Attribute n" , message = _DEPRECATED_VALUE_ALIAS_MESSAGE , remove = (3 , 14 )
526+ )
527+ self .value = value
528+
529+ def _s_getter (self ):
508530 """Deprecated. Use value instead."""
531+ import warnings
532+ warnings ._deprecated (
533+ "Attribute s" , message = _DEPRECATED_VALUE_ALIAS_MESSAGE , remove = (3 , 14 )
534+ )
509535 return self .value
510536
511- def _setter (self , value ):
537+ def _s_setter (self , value ):
538+ import warnings
539+ warnings ._deprecated (
540+ "Attribute s" , message = _DEPRECATED_VALUE_ALIAS_MESSAGE , remove = (3 , 14 )
541+ )
512542 self .value = value
513543
514- Constant .n = property (_getter , _setter )
515- Constant .s = property (_getter , _setter )
544+ Constant .n = property (_n_getter , _n_setter )
545+ Constant .s = property (_s_getter , _s_setter )
516546
517547class _ABC (type ):
518548
519549 def __init__ (cls , * args ):
520550 cls .__doc__ = """Deprecated AST node class. Use ast.Constant instead"""
521551
522552 def __instancecheck__ (cls , inst ):
553+ if cls in _const_types :
554+ import warnings
555+ warnings ._deprecated (
556+ f"ast.{ cls .__qualname__ } " ,
557+ message = _DEPRECATED_CLASS_MESSAGE ,
558+ remove = (3 , 14 )
559+ )
523560 if not isinstance (inst , Constant ):
524561 return False
525562 if cls in _const_types :
@@ -543,6 +580,10 @@ def _new(cls, *args, **kwargs):
543580 if pos < len (args ):
544581 raise TypeError (f"{ cls .__name__ } got multiple values for argument { key !r} " )
545582 if cls in _const_types :
583+ import warnings
584+ warnings ._deprecated (
585+ f"ast.{ cls .__qualname__ } " , message = _DEPRECATED_CLASS_MESSAGE , remove = (3 , 14 )
586+ )
546587 return Constant (* args , ** kwargs )
547588 return Constant .__new__ (cls , * args , ** kwargs )
548589
@@ -565,10 +606,19 @@ class Ellipsis(Constant, metaclass=_ABC):
565606 _fields = ()
566607
567608 def __new__ (cls , * args , ** kwargs ):
568- if cls is Ellipsis :
609+ if cls is _ast_Ellipsis :
610+ import warnings
611+ warnings ._deprecated (
612+ "ast.Ellipsis" , message = _DEPRECATED_CLASS_MESSAGE , remove = (3 , 14 )
613+ )
569614 return Constant (..., * args , ** kwargs )
570615 return Constant .__new__ (cls , * args , ** kwargs )
571616
617+ # Keep another reference to Ellipsis in the global namespace
618+ # so it can be referenced in Ellipsis.__new__
619+ # (The original "Ellipsis" name is removed from the global namespace later on)
620+ _ast_Ellipsis = Ellipsis
621+
572622_const_types = {
573623 Num : (int , float , complex ),
574624 Str : (str ,),
@@ -1699,6 +1749,22 @@ def unparse(ast_obj):
16991749 return unparser .visit (ast_obj )
17001750
17011751
1752+ _deprecated_globals = {
1753+ name : globals ().pop (name )
1754+ for name in ('Num' , 'Str' , 'Bytes' , 'NameConstant' , 'Ellipsis' )
1755+ }
1756+
1757+ def __getattr__ (name ):
1758+ if name in _deprecated_globals :
1759+ globals ()[name ] = value = _deprecated_globals [name ]
1760+ import warnings
1761+ warnings ._deprecated (
1762+ f"ast.{ name } " , message = _DEPRECATED_CLASS_MESSAGE , remove = (3 , 14 )
1763+ )
1764+ return value
1765+ raise AttributeError (f"module 'ast' has no attribute '{ name } '" )
1766+
1767+
17021768def main ():
17031769 import argparse
17041770
0 commit comments