]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-140344: ast: Add deprecation warnings (#140345)
authorJeff Epler <jepler@unpythonic.net>
Mon, 18 May 2026 18:20:49 +0000 (11:20 -0700)
committerGitHub <noreply@github.com>
Mon, 18 May 2026 18:20:49 +0000 (11:20 -0700)
These were all deprecated in 3.9 (bace59d8b8) but without
a runtime deprecation warning. Add it now, so that these
items can be removed in 3.21 per PEP 387.

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Doc/deprecations/index.rst
Doc/deprecations/pending-removal-in-3.21.rst [new file with mode: 0644]
Doc/whatsnew/3.16.rst
Lib/ast.py
Lib/test/test_ast/test_ast.py
Misc/NEWS.d/next/Library/2025-10-20-09-12-18.gh-issue-140344.WjbYg-.rst [new file with mode: 0644]

index eedcd2e9c9dd4239b2340941ffa37c906a8c3a71..50e1b126fd1346dbd2e76075557708b57d4ef4d4 100644 (file)
@@ -13,6 +13,8 @@ Deprecations
 
 .. include:: pending-removal-in-3.20.rst
 
+.. include:: pending-removal-in-3.21.rst
+
 .. include:: pending-removal-in-future.rst
 
 .. include:: soft-deprecations.rst
diff --git a/Doc/deprecations/pending-removal-in-3.21.rst b/Doc/deprecations/pending-removal-in-3.21.rst
new file mode 100644 (file)
index 0000000..5d0c566
--- /dev/null
@@ -0,0 +1,10 @@
+Pending removal in Python 3.21
+------------------------------
+
+* :mod:`ast`:
+
+  * Classes ``slice``, ``Index``, ``ExtSlice``, ``Suite``, ``Param``,
+    ``AugLoad`` and ``AugStore``, will be removed in Python 3.21. These types
+    are not generated by the parser or accepted by the code generator.
+  * The ``dims`` property of ``ast.Tuple`` will be removed in Python 3.21. Use
+    the ``ast.Tuple.elts`` property instead.
index 9383ce5665993e046531336be0d666729ccadd6f..2e5342e4f02053431c0744b6e040cb9d44d8e890 100644 (file)
@@ -184,9 +184,16 @@ tarfile
 Deprecated
 ==========
 
-* module_name:
-  TODO
-
+* :mod:`ast`:
+
+  * Classes ``slice``, ``Index``, ``ExtSlice``, ``Suite``, ``Param``,
+    ``AugLoad`` and ``AugStore``, deprecated since Python 3.9, are no longer
+    imported by ``from ast import *`` and issue a deprecation warning on
+    use. The classes are slated for removal in Python 3.21. These types are not
+    generated by the parser or accepted by the code generator.
+  * The ``dims`` property of ``ast.Tuple`` objects, deprecated since Python
+    3.9, now issues a deprecation warning on use. This property is slated for
+    removal in 3.21. Use ``ast.Tuple.elts`` instead.
 
 .. Add deprecations above alphabetically, not here at the end.
 
index 4f88a554344cc95b18e391c1a1287937d4c9a148..f445b32040e5fb2491b268bf5776e2889291f22e 100644 (file)
@@ -21,7 +21,7 @@ that work tightly with the python syntax (template engines for example).
 :license: Python License.
 """
 from _ast import *
-
+lazy import warnings
 
 def parse(source, filename='<unknown>', mode='exec', *,
           type_comments=False, feature_version=None, optimize=-1, module=None):
@@ -630,9 +630,11 @@ if not hasattr(Tuple, 'dims'):
 
     def _dims_getter(self):
         """Deprecated. Use elts instead."""
+        warnings._deprecated(f"ast.Tuple.dims", remove=(3, 21))
         return self.elts
 
     def _dims_setter(self, value):
+        warnings._deprecated(f"ast.Tuple.dims", remove=(3, 21))
         self.elts = value
 
     Tuple.dims = property(_dims_getter, _dims_setter)
@@ -714,5 +716,23 @@ def main(args=None):
                color=can_colorize(file=sys.stdout),
                indent=args.indent, show_empty=args.show_empty))
 
+_deprecated = {
+        'slice': globals().pop("slice"),
+        'Index': globals().pop("Index"),
+        'ExtSlice': globals().pop("ExtSlice"),
+        'Suite': globals().pop("Suite"),
+        'AugLoad': globals().pop("AugLoad"),
+        'AugStore': globals().pop("AugStore"),
+        'Param': globals().pop("Param")
+}
+
+def __getattr__(attr):
+    try:
+        val = _deprecated[attr]
+    except KeyError:
+        raise AttributeError(f"module 'ast' has no attribute {attr!r}") from None
+    warnings._deprecated(f"ast.{attr}", remove=(3, 21))
+    return val
+
 if __name__ == '__main__':
     main()
index af8b334da03e7028a584c080fca3f32aff50869e..0112c9163fd0cdb4ce7d9f8bad80694cb932b9c8 100644 (file)
@@ -523,6 +523,12 @@ class AST_Tests(unittest.TestCase):
         self.assertIs(ast.Constant(None).value, None)
         self.assertIs(ast.Constant(...).value, ...)
 
+        with self.assertWarns(DeprecationWarning):
+            ast.Tuple().dims
+
+        with self.assertWarns(DeprecationWarning):
+            ast.Tuple().dims = 3
+
     def test_constant_subclasses(self):
         class N(ast.Constant):
             def __init__(self, *args, **kwargs):
@@ -1100,6 +1106,38 @@ class AST_Tests(unittest.TestCase):
         self.assertIsInstance(tree.body[0].value.values[0], ast.Constant)
         self.assertIsInstance(tree.body[0].value.values[1], ast.Interpolation)
 
+    def test_deprecated(self):
+        with self.assertWarns(DeprecationWarning):
+            ast.slice
+
+        with self.assertWarns(DeprecationWarning):
+            ast.Index
+
+        with self.assertWarns(DeprecationWarning):
+            ast.ExtSlice
+
+        with self.assertWarns(DeprecationWarning):
+            ast.Suite
+
+        with self.assertWarns(DeprecationWarning):
+            ast.AugLoad
+
+        with self.assertWarns(DeprecationWarning):
+            ast.AugStore
+
+        with self.assertWarns(DeprecationWarning):
+            ast.Param
+
+        namespace = {}
+        exec("from ast import *", namespace)
+        self.assertNotIn("slice", namespace)
+        self.assertNotIn("Index", namespace)
+        self.assertNotIn("ExtSlice", namespace)
+        self.assertNotIn("Suite", namespace)
+        self.assertNotIn("AugLoad", namespace)
+        self.assertNotIn("AugStore", namespace)
+        self.assertNotIn("Param", namespace)
+
     def test_filter_syntax_warnings_by_module(self):
         filename = support.findfile('test_import/data/syntax_warnings.py')
         with open(filename, 'rb') as f:
@@ -1139,8 +1177,9 @@ class CopyTests(unittest.TestCase):
         def do(cls):
             if cls.__module__ != 'ast':
                 return
-            if cls is ast.Index:
-                return
+            with warnings.catch_warnings(action="ignore", category=DeprecationWarning):
+                if cls is ast.Index:
+                    return
             # Don't attempt to create instances of abstract AST nodes
             if _ast._is_abstract(cls):
                 return
diff --git a/Misc/NEWS.d/next/Library/2025-10-20-09-12-18.gh-issue-140344.WjbYg-.rst b/Misc/NEWS.d/next/Library/2025-10-20-09-12-18.gh-issue-140344.WjbYg-.rst
new file mode 100644 (file)
index 0000000..ca30469
--- /dev/null
@@ -0,0 +1,11 @@
+The classes ``ast.slice``, ``ast.ExtSlice``, ``ast.Index``, ``ast.Suite``, ``ast.AugLoad``,
+``ast.AugStore``, and ``ast.Param``, deprecated since Python 3.9, now issue
+deprecation warnings on use. They are now scheduled for removal in Python 3.21.
+
+The ``dims`` property of ``ast.Tuple`` objects, deprecated since Python 3.9,
+now issues a deprecation warning when accessed. The property is scheduled for
+removal in Python 3.21. Use the (non-deprecated) ``elts`` property of
+``ast.Tuple`` objects instead.
+
+The deprecated global names are also no longer imported by
+``from ast import *``.