https://github.com/python/cpython/commit/46a2c11eaa8cbef6f73dd7050029bd8ff13026fc
commit: 46a2c11eaa8cbef6f73dd7050029bd8ff13026fc
branch: main
author: sobolevn <[email protected]>
committer: sobolevn <[email protected]>
date: 2026-05-09T08:33:09Z
summary:

gh-149530: Remove `symtable.Class.get_methods` deprecated method (#149531)

files:
A Misc/NEWS.d/next/Library/2026-05-08-06-56-57.gh-issue-149530.cl2AJ8.rst
M Doc/deprecations/pending-removal-in-3.16.rst
M Doc/library/symtable.rst
M Doc/tools/removed-ids.txt
M Doc/whatsnew/3.14.rst
M Doc/whatsnew/3.16.rst
M Lib/symtable.py
M Lib/test/test_symtable.py
M Misc/NEWS.d/3.14.0a1.rst

diff --git a/Doc/deprecations/pending-removal-in-3.16.rst 
b/Doc/deprecations/pending-removal-in-3.16.rst
index b00c7002b03772..a64212e38e61cb 100644
--- a/Doc/deprecations/pending-removal-in-3.16.rst
+++ b/Doc/deprecations/pending-removal-in-3.16.rst
@@ -84,7 +84,7 @@ Pending removal in Python 3.16
 
 * :mod:`symtable`:
 
-  * The :meth:`Class.get_methods <symtable.Class.get_methods>` method
+  * The :meth:`!symtable.Class.get_methods` method
     has been deprecated since Python 3.14.
 
 * :mod:`sys`:
diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst
index 52a722608db431..95f20b06b5aa1e 100644
--- a/Doc/library/symtable.rst
+++ b/Doc/library/symtable.rst
@@ -187,57 +187,6 @@ Examining Symbol Tables
 
    A namespace of a class.  This class inherits from :class:`SymbolTable`.
 
-   .. method:: get_methods()
-
-      Return a tuple containing the names of method-like functions declared
-      in the class.
-
-      Here, the term 'method' designates *any* function defined in the class
-      body via :keyword:`def` or :keyword:`async def`.
-
-      Functions defined in a deeper scope (e.g., in an inner class) are not
-      picked up by :meth:`get_methods`.
-
-      For example:
-
-      .. testsetup:: symtable.Class.get_methods
-
-         import warnings
-         context = warnings.catch_warnings()
-         context.__enter__()
-         warnings.simplefilter("ignore", category=DeprecationWarning)
-
-      .. testcleanup:: symtable.Class.get_methods
-
-         context.__exit__()
-
-      .. doctest:: symtable.Class.get_methods
-
-         >>> import symtable
-         >>> st = symtable.symtable('''
-         ... def outer(): pass
-         ...
-         ... class A:
-         ...    def f():
-         ...        def w(): pass
-         ...
-         ...    def g(self): pass
-         ...
-         ...    @classmethod
-         ...    async def h(cls): pass
-         ...
-         ...    global outer
-         ...    def outer(self): pass
-         ... ''', 'test', 'exec')
-         >>> class_A = st.get_children()[2]
-         >>> class_A.get_methods()
-         ('f', 'g', 'h')
-
-      Although ``A().f()`` raises :exc:`TypeError` at runtime, ``A.f`` is still
-      considered as a method-like function.
-
-      .. deprecated-removed:: 3.14 3.16
-
 
 .. class:: Symbol
 
diff --git a/Doc/tools/removed-ids.txt b/Doc/tools/removed-ids.txt
index 5e3ef2efe271fd..adac1b993047bc 100644
--- a/Doc/tools/removed-ids.txt
+++ b/Doc/tools/removed-ids.txt
@@ -5,3 +5,6 @@ c-api/allocation.html: deprecated-aliases
 c-api/file.html: deprecated-api
 
 library/asyncio-task.html: terminating-a-task-group
+
+# Removed APIs
+library/symtable.html: symtable.Class.get_methods
\ No newline at end of file
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 0bb8858aea16fe..39d1d8da5367e5 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -2718,7 +2718,7 @@ New deprecations
   (Contributed by Tian Gao in :gh:`124369` and :gh:`125951`.)
 
 * :mod:`symtable`:
-  Deprecate :meth:`symtable.Class.get_methods` due to the lack of interest,
+  Deprecate :meth:`!symtable.Class.get_methods` due to the lack of interest,
   scheduled for removal in Python 3.16.
   (Contributed by Bénédikt Tran in :gh:`119698`.)
 
diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst
index 4ddc836d9b29e4..d9beda92aba6a3 100644
--- a/Doc/whatsnew/3.16.rst
+++ b/Doc/whatsnew/3.16.rst
@@ -120,6 +120,12 @@ functools
 * Calling the Python implementation of :func:`functools.reduce` with *function*
   or *sequence* as keyword arguments has been deprecated since Python 3.14.
 
+symtable
+--------
+
+* The :meth:`!symtable.Class.get_methods` method
+  which has been deprecated since Python 3.14.
+
 sysconfig
 ---------
 
diff --git a/Lib/symtable.py b/Lib/symtable.py
index c7152a70f5aa0b..9238437191c00f 100644
--- a/Lib/symtable.py
+++ b/Lib/symtable.py
@@ -240,41 +240,7 @@ def get_cells(self):
 
 
 class Class(SymbolTable):
-
-    __methods = None
-
-    def get_methods(self):
-        """Return a tuple of methods declared in the class.
-        """
-        import warnings
-        typename = f'{self.__class__.__module__}.{self.__class__.__name__}'
-        warnings.warn(f'{typename}.get_methods() is deprecated '
-                      f'and will be removed in Python 3.16.',
-                      DeprecationWarning, stacklevel=2)
-
-        if self.__methods is None:
-            d = {}
-
-            def is_local_symbol(ident):
-                flags = self._table.symbols.get(ident, 0)
-                return ((flags >> SCOPE_OFF) & SCOPE_MASK) == LOCAL
-
-            for st in self._table.children:
-                # pick the function-like symbols that are local identifiers
-                if is_local_symbol(st.name):
-                    match st.type:
-                        case _symtable.TYPE_FUNCTION:
-                            d[st.name] = 1
-                        case _symtable.TYPE_TYPE_PARAMETERS:
-                            # Get the function-def block in the annotation
-                            # scope 'st' with the same identifier, if any.
-                            scope_name = st.name
-                            for c in st.children:
-                                if c.name == scope_name and c.type == 
_symtable.TYPE_FUNCTION:
-                                    d[scope_name] = 1
-                                    break
-            self.__methods = tuple(d)
-        return self.__methods
+    pass
 
 
 class Symbol:
diff --git a/Lib/test/test_symtable.py b/Lib/test/test_symtable.py
index c748243110df9f..8c03420c4c5e4b 100644
--- a/Lib/test/test_symtable.py
+++ b/Lib/test/test_symtable.py
@@ -2,8 +2,6 @@
 Test the API of the symtable module.
 """
 
-import re
-import textwrap
 import symtable
 import warnings
 import unittest
@@ -364,87 +362,6 @@ def test_name(self):
         self.assertEqual(self.spam.lookup("x").get_name(), "x")
         self.assertEqual(self.Mine.get_name(), "Mine")
 
-    def test_class_get_methods(self):
-        deprecation_mess = (
-            re.escape('symtable.Class.get_methods() is deprecated '
-                      'and will be removed in Python 3.16.')
-        )
-
-        with self.assertWarnsRegex(DeprecationWarning, deprecation_mess):
-            self.assertEqual(self.Mine.get_methods(), ('a_method',))
-
-        top = symtable.symtable(TEST_COMPLEX_CLASS_CODE, "?", "exec")
-        this = find_block(top, "ComplexClass")
-
-        with self.assertWarnsRegex(DeprecationWarning, deprecation_mess):
-            self.assertEqual(this.get_methods(), (
-                'a_method', 'a_method_pep_695',
-                'an_async_method', 'an_async_method_pep_695',
-                'a_classmethod', 'a_classmethod_pep_695',
-                'an_async_classmethod', 'an_async_classmethod_pep_695',
-                'a_staticmethod', 'a_staticmethod_pep_695',
-                'an_async_staticmethod', 'an_async_staticmethod_pep_695',
-                'a_fakemethod', 'a_fakemethod_pep_695',
-                'an_async_fakemethod', 'an_async_fakemethod_pep_695',
-                'glob_unassigned_meth', 'glob_unassigned_meth_pep_695',
-                'glob_unassigned_async_meth', 
'glob_unassigned_async_meth_pep_695',
-                'glob_assigned_meth', 'glob_assigned_meth_pep_695',
-                'glob_assigned_async_meth', 'glob_assigned_async_meth_pep_695',
-            ))
-
-        # Test generator expressions that are of type TYPE_FUNCTION
-        # but will not be reported by get_methods() since they are
-        # not functions per se.
-        #
-        # Other kind of comprehensions such as list, set or dict
-        # expressions do not have the TYPE_FUNCTION type.
-
-        def check_body(body, expected_methods):
-            indented = textwrap.indent(body, ' ' * 4)
-            top = symtable.symtable(f"class A:\n{indented}", "?", "exec")
-            this = find_block(top, "A")
-            with self.assertWarnsRegex(DeprecationWarning, deprecation_mess):
-                self.assertEqual(this.get_methods(), expected_methods)
-
-        # statements with 'genexpr' inside it
-        GENEXPRS = (
-            'x = (x for x in [])',
-            'x = (x async for x in [])',
-            'type x[genexpr = (x for x in [])] = (x for x in [])',
-            'type x[genexpr = (x async for x in [])] = (x async for x in [])',
-            'genexpr = (x for x in [])',
-            'genexpr = (x async for x in [])',
-            'type genexpr[genexpr = (x for x in [])] = (x for x in [])',
-            'type genexpr[genexpr = (x async for x in [])] = (x async for x in 
[])',
-        )
-
-        for gen in GENEXPRS:
-            # test generator expression
-            with self.subTest(gen=gen):
-                check_body(gen, ())
-
-            # test generator expression + variable named 'genexpr'
-            with self.subTest(gen=gen, isvar=True):
-                check_body('\n'.join((gen, 'genexpr = 1')), ())
-                check_body('\n'.join(('genexpr = 1', gen)), ())
-
-        for paramlist in ('()', '(x)', '(x, y)', '(z: T)'):
-            for func in (
-                f'def genexpr{paramlist}:pass',
-                f'async def genexpr{paramlist}:pass',
-                f'def genexpr[T]{paramlist}:pass',
-                f'async def genexpr[T]{paramlist}:pass',
-            ):
-                with self.subTest(func=func):
-                    # test function named 'genexpr'
-                    check_body(func, ('genexpr',))
-
-                for gen in GENEXPRS:
-                    with self.subTest(gen=gen, func=func):
-                        # test generator expression + function named 'genexpr'
-                        check_body('\n'.join((gen, func)), ('genexpr',))
-                        check_body('\n'.join((func, gen)), ('genexpr',))
-
     def test_filename_correct(self):
         ### Bug tickler: SyntaxError file name correct whether error raised
         ### while parsing or building symbol table.
diff --git a/Misc/NEWS.d/3.14.0a1.rst b/Misc/NEWS.d/3.14.0a1.rst
index 5303bd89efff5b..79936955757280 100644
--- a/Misc/NEWS.d/3.14.0a1.rst
+++ b/Misc/NEWS.d/3.14.0a1.rst
@@ -2038,7 +2038,7 @@ Remove workarounds for non-IEEE 754 systems in 
:mod:`cmath`.
 .. nonce: WlygzR
 .. section: Library
 
-Due to the lack of interest for :meth:`symtable.Class.get_methods`, the
+Due to the lack of interest for :meth:`!symtable.Class.get_methods`, the
 method is marked as deprecated and will be removed in Python 3.16. Patch by
 Bénédikt Tran.
 
@@ -2746,7 +2746,7 @@ situations.
 .. nonce: rRrprk
 .. section: Library
 
-Fix :meth:`symtable.Class.get_methods` and document its behaviour. Patch by
+Fix :meth:`!symtable.Class.get_methods` and document its behaviour. Patch by
 Bénédikt Tran.
 
 ..
diff --git 
a/Misc/NEWS.d/next/Library/2026-05-08-06-56-57.gh-issue-149530.cl2AJ8.rst 
b/Misc/NEWS.d/next/Library/2026-05-08-06-56-57.gh-issue-149530.cl2AJ8.rst
new file mode 100644
index 00000000000000..2b74e8cdadd03c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-05-08-06-56-57.gh-issue-149530.cl2AJ8.rst
@@ -0,0 +1,2 @@
+Removed :meth:`!symtable.Class.get_methods` which has been deprecated since
+3.14.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to