Skip to content
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

gh-119698: deprecate symtable.Class.get_methods #121902

Merged
merged 11 commits into from
Jul 22, 2024
16 changes: 16 additions & 0 deletions Doc/library/symtable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
3 changes: 3 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,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
=======
Expand Down
6 changes: 6 additions & 0 deletions Lib/symtable.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,12 @@ class Class(SymbolTable):
def get_methods(self):
"""Return a tuple of methods declared in the class.
"""
import warnings
picnixz marked this conversation as resolved.
Show resolved Hide resolved
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 = {}

Expand Down
41 changes: 25 additions & 16 deletions Lib/test/test_symtable.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Test the API of the symtable module.
"""

import re
import textwrap
import symtable
import unittest
Expand Down Expand Up @@ -359,25 +360,32 @@ def test_name(self):
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
Expand All @@ -390,7 +398,8 @@ 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")
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 = (
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Loading