Skip to content

gh-90953: Emit deprecation warnings for deprecated ast features #31432

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
68 changes: 60 additions & 8 deletions Lib/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,7 @@ def get_docstring(node, clean=True):
if not(node.body and isinstance(node.body[0], Expr)):
return None
node = node.body[0].value
if isinstance(node, Str):
text = node.s
elif isinstance(node, Constant) and isinstance(node.value, str):
if isinstance(node, Constant) and isinstance(node.value, str):
text = node.value
else:
return None
Expand Down Expand Up @@ -504,15 +502,34 @@ def generic_visit(self, node):
# The following code is for backward compatibility.
# It will be removed in future.

def _getter(self):
def _n_getter(self):
"""Deprecated. Use value instead."""
import warnings
warnings.warn("Attribute n is deprecated; use value instead",
DeprecationWarning, stacklevel=2)
return self.value

def _setter(self, value):
def _n_setter(self, value):
import warnings
warnings.warn("Attribute n is deprecated; use value instead",
DeprecationWarning, stacklevel=2)
self.value = value

Constant.n = property(_getter, _setter)
Constant.s = property(_getter, _setter)
def _s_getter(self):
"""Deprecated. Use value instead."""
import warnings
warnings.warn("Attribute s is deprecated; use value instead",
DeprecationWarning, stacklevel=2)
return self.value

def _s_setter(self, value):
import warnings
warnings.warn("Attribute s is deprecated; use value instead",
DeprecationWarning, stacklevel=2)
self.value = value

Constant.n = property(_n_getter, _n_setter)
Constant.s = property(_s_getter, _s_setter)

class _ABC(type):

Expand Down Expand Up @@ -543,6 +560,9 @@ def _new(cls, *args, **kwargs):
if pos < len(args):
raise TypeError(f"{cls.__name__} got multiple values for argument {key!r}")
if cls in _const_types:
import warnings
warnings.warn(f"ast.{cls.__qualname__} is deprecated; use ast.Constant instead",
DeprecationWarning, stacklevel=2)
return Constant(*args, **kwargs)
return Constant.__new__(cls, *args, **kwargs)

Expand All @@ -565,10 +585,15 @@ class Ellipsis(Constant, metaclass=_ABC):
_fields = ()

def __new__(cls, *args, **kwargs):
if cls is Ellipsis:
if cls is _ast_Ellipsis:
import warnings
warnings.warn("ast.Ellipsis is deprecated; use ast.Constant instead",
DeprecationWarning, stacklevel=2)
return Constant(..., *args, **kwargs)
return Constant.__new__(cls, *args, **kwargs)

_ast_Ellipsis = Ellipsis

_const_types = {
Num: (int, float, complex),
Str: (str,),
Expand Down Expand Up @@ -602,6 +627,9 @@ def __new__(cls, value, **kwargs):
class ExtSlice(slice):
"""Deprecated AST node class. Use ast.Tuple instead."""
def __new__(cls, dims=(), **kwargs):
import warnings
warnings.warn("ast.ExtSlice is deprecated; use ast.Tuple instead",
DeprecationWarning, stacklevel=2)
return Tuple(list(dims), Load(), **kwargs)

# If the ast module is loaded more than once, only add deprecated methods once
Expand All @@ -611,9 +639,14 @@ def __new__(cls, dims=(), **kwargs):

def _dims_getter(self):
"""Deprecated. Use elts instead."""
import warnings
warnings.warn("Attribute dims is deprecated; use elts instead",
DeprecationWarning, stacklevel=2)
return self.elts

def _dims_setter(self, value):
warnings.warn("Attribute dims is deprecated, use elts instead",
DeprecationWarning, stacklevel=2)
self.elts = value

Tuple.dims = property(_dims_getter, _dims_setter)
Expand Down Expand Up @@ -1699,6 +1732,25 @@ def unparse(ast_obj):
return unparser.visit(ast_obj)


_deprecated_globals = {
name: (globals().pop(name), '; use ast.Constant instead')
for name in ('Num', 'Str', 'Bytes', 'NameConstant', 'Ellipsis')
}
_deprecated_globals['slice'] = globals().pop('slice'), ''
_deprecated_globals['Index'] = globals().pop('Index'), ''
_deprecated_globals['ExtSlice'] = globals().pop('ExtSlice'), '; use ast.Tuple instead'

def __getattr__(name):
if name in _deprecated_globals:
value, details = _deprecated_globals[name]
globals()[name] = value
import warnings
warnings.warn(f"ast.{name} is deprecated{details}",
DeprecationWarning, stacklevel=2)
return value
raise AttributeError(f"module 'ast' has no attribute '{name}'")


def main():
import argparse

Expand Down
Loading