From c09d4c4a26a39a3c1185bc3449d3e0886cb82784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 22 Jul 2024 16:04:17 +0200 Subject: [PATCH] gh-119698: deprecate ``symtable.Class.get_methods`` (#121902) --- Doc/library/symtable.rst | 16 ++++++++ Doc/whatsnew/3.14.rst | 3 ++ Lib/symtable.py | 6 +++ Lib/test/test_symtable.py | 41 +++++++++++-------- ...-07-17-09-44-35.gh-issue-119698.WlygzR.rst | 3 ++ 5 files changed, 53 insertions(+), 16 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-07-17-09-44-35.gh-issue-119698.WlygzR.rst diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index aa5f8d95925..8ebcb3bcf1b 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -191,6 +191,19 @@ Examining Symbol Tables 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 @@ -214,6 +227,9 @@ Examining Symbol Tables 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 An entry in a :class:`SymbolTable` corresponding to an identifier in the diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 6f577334705..8228ebabc91 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -183,6 +183,9 @@ Deprecated write new code. The :mod:`subprocess` module is recommended instead. (Contributed by Victor Stinner in :gh:`120743`.) +* Deprecate :meth:`symtable.Class.get_methods` due to the lack of interest. + (Contributed by Bénédikt Tran in :gh:`119698`.) + Removed ======= diff --git a/Lib/symtable.py b/Lib/symtable.py index 8c796b7cc7e..7a30e1ac4ca 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -237,6 +237,12 @@ class Class(SymbolTable): 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 = {} diff --git a/Lib/test/test_symtable.py b/Lib/test/test_symtable.py index 82f667d3687..bd367c1591c 100644 --- a/Lib/test/test_symtable.py +++ b/Lib/test/test_symtable.py @@ -2,6 +2,7 @@ Test the API of the symtable module. """ +import re import textwrap import symtable import unittest @@ -359,25 +360,32 @@ class SymtableTest(unittest.TestCase): self.assertEqual(self.Mine.get_name(), "Mine") def test_class_get_methods(self): - self.assertEqual(self.Mine.get_methods(), ('a_method',)) + 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") - 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', - )) + 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 @@ -390,7 +398,8 @@ class SymtableTest(unittest.TestCase): indented = textwrap.indent(body, ' ' * 4) top = symtable.symtable(f"class A:\n{indented}", "?", "exec") this = find_block(top, "A") - self.assertEqual(this.get_methods(), expected_methods) + with self.assertWarnsRegex(DeprecationWarning, deprecation_mess): + self.assertEqual(this.get_methods(), expected_methods) # statements with 'genexpr' inside it GENEXPRS = ( diff --git a/Misc/NEWS.d/next/Library/2024-07-17-09-44-35.gh-issue-119698.WlygzR.rst b/Misc/NEWS.d/next/Library/2024-07-17-09-44-35.gh-issue-119698.WlygzR.rst new file mode 100644 index 00000000000..5134e609e7f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-07-17-09-44-35.gh-issue-119698.WlygzR.rst @@ -0,0 +1,3 @@ +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.