Skip to content

Commit 46a2c11

Browse files
authored
gh-149530: Remove symtable.Class.get_methods deprecated method (#149531)
1 parent bc8cf07 commit 46a2c11

9 files changed

Lines changed: 16 additions & 173 deletions

File tree

Doc/deprecations/pending-removal-in-3.16.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ Pending removal in Python 3.16
8484

8585
* :mod:`symtable`:
8686

87-
* The :meth:`Class.get_methods <symtable.Class.get_methods>` method
87+
* The :meth:`!symtable.Class.get_methods` method
8888
has been deprecated since Python 3.14.
8989

9090
* :mod:`sys`:

Doc/library/symtable.rst

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -187,57 +187,6 @@ Examining Symbol Tables
187187

188188
A namespace of a class. This class inherits from :class:`SymbolTable`.
189189

190-
.. method:: get_methods()
191-
192-
Return a tuple containing the names of method-like functions declared
193-
in the class.
194-
195-
Here, the term 'method' designates *any* function defined in the class
196-
body via :keyword:`def` or :keyword:`async def`.
197-
198-
Functions defined in a deeper scope (e.g., in an inner class) are not
199-
picked up by :meth:`get_methods`.
200-
201-
For example:
202-
203-
.. testsetup:: symtable.Class.get_methods
204-
205-
import warnings
206-
context = warnings.catch_warnings()
207-
context.__enter__()
208-
warnings.simplefilter("ignore", category=DeprecationWarning)
209-
210-
.. testcleanup:: symtable.Class.get_methods
211-
212-
context.__exit__()
213-
214-
.. doctest:: symtable.Class.get_methods
215-
216-
>>> import symtable
217-
>>> st = symtable.symtable('''
218-
... def outer(): pass
219-
...
220-
... class A:
221-
... def f():
222-
... def w(): pass
223-
...
224-
... def g(self): pass
225-
...
226-
... @classmethod
227-
... async def h(cls): pass
228-
...
229-
... global outer
230-
... def outer(self): pass
231-
... ''', 'test', 'exec')
232-
>>> class_A = st.get_children()[2]
233-
>>> class_A.get_methods()
234-
('f', 'g', 'h')
235-
236-
Although ``A().f()`` raises :exc:`TypeError` at runtime, ``A.f`` is still
237-
considered as a method-like function.
238-
239-
.. deprecated-removed:: 3.14 3.16
240-
241190

242191
.. class:: Symbol
243192

Doc/tools/removed-ids.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ c-api/allocation.html: deprecated-aliases
55
c-api/file.html: deprecated-api
66

77
library/asyncio-task.html: terminating-a-task-group
8+
9+
# Removed APIs
10+
library/symtable.html: symtable.Class.get_methods

Doc/whatsnew/3.14.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2718,7 +2718,7 @@ New deprecations
27182718
(Contributed by Tian Gao in :gh:`124369` and :gh:`125951`.)
27192719

27202720
* :mod:`symtable`:
2721-
Deprecate :meth:`symtable.Class.get_methods` due to the lack of interest,
2721+
Deprecate :meth:`!symtable.Class.get_methods` due to the lack of interest,
27222722
scheduled for removal in Python 3.16.
27232723
(Contributed by Bénédikt Tran in :gh:`119698`.)
27242724

Doc/whatsnew/3.16.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ functools
120120
* Calling the Python implementation of :func:`functools.reduce` with *function*
121121
or *sequence* as keyword arguments has been deprecated since Python 3.14.
122122

123+
symtable
124+
--------
125+
126+
* The :meth:`!symtable.Class.get_methods` method
127+
which has been deprecated since Python 3.14.
128+
123129
sysconfig
124130
---------
125131

Lib/symtable.py

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -240,41 +240,7 @@ def get_cells(self):
240240

241241

242242
class Class(SymbolTable):
243-
244-
__methods = None
245-
246-
def get_methods(self):
247-
"""Return a tuple of methods declared in the class.
248-
"""
249-
import warnings
250-
typename = f'{self.__class__.__module__}.{self.__class__.__name__}'
251-
warnings.warn(f'{typename}.get_methods() is deprecated '
252-
f'and will be removed in Python 3.16.',
253-
DeprecationWarning, stacklevel=2)
254-
255-
if self.__methods is None:
256-
d = {}
257-
258-
def is_local_symbol(ident):
259-
flags = self._table.symbols.get(ident, 0)
260-
return ((flags >> SCOPE_OFF) & SCOPE_MASK) == LOCAL
261-
262-
for st in self._table.children:
263-
# pick the function-like symbols that are local identifiers
264-
if is_local_symbol(st.name):
265-
match st.type:
266-
case _symtable.TYPE_FUNCTION:
267-
d[st.name] = 1
268-
case _symtable.TYPE_TYPE_PARAMETERS:
269-
# Get the function-def block in the annotation
270-
# scope 'st' with the same identifier, if any.
271-
scope_name = st.name
272-
for c in st.children:
273-
if c.name == scope_name and c.type == _symtable.TYPE_FUNCTION:
274-
d[scope_name] = 1
275-
break
276-
self.__methods = tuple(d)
277-
return self.__methods
243+
pass
278244

279245

280246
class Symbol:

Lib/test/test_symtable.py

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
Test the API of the symtable module.
33
"""
44

5-
import re
6-
import textwrap
75
import symtable
86
import warnings
97
import unittest
@@ -364,87 +362,6 @@ def test_name(self):
364362
self.assertEqual(self.spam.lookup("x").get_name(), "x")
365363
self.assertEqual(self.Mine.get_name(), "Mine")
366364

367-
def test_class_get_methods(self):
368-
deprecation_mess = (
369-
re.escape('symtable.Class.get_methods() is deprecated '
370-
'and will be removed in Python 3.16.')
371-
)
372-
373-
with self.assertWarnsRegex(DeprecationWarning, deprecation_mess):
374-
self.assertEqual(self.Mine.get_methods(), ('a_method',))
375-
376-
top = symtable.symtable(TEST_COMPLEX_CLASS_CODE, "?", "exec")
377-
this = find_block(top, "ComplexClass")
378-
379-
with self.assertWarnsRegex(DeprecationWarning, deprecation_mess):
380-
self.assertEqual(this.get_methods(), (
381-
'a_method', 'a_method_pep_695',
382-
'an_async_method', 'an_async_method_pep_695',
383-
'a_classmethod', 'a_classmethod_pep_695',
384-
'an_async_classmethod', 'an_async_classmethod_pep_695',
385-
'a_staticmethod', 'a_staticmethod_pep_695',
386-
'an_async_staticmethod', 'an_async_staticmethod_pep_695',
387-
'a_fakemethod', 'a_fakemethod_pep_695',
388-
'an_async_fakemethod', 'an_async_fakemethod_pep_695',
389-
'glob_unassigned_meth', 'glob_unassigned_meth_pep_695',
390-
'glob_unassigned_async_meth', 'glob_unassigned_async_meth_pep_695',
391-
'glob_assigned_meth', 'glob_assigned_meth_pep_695',
392-
'glob_assigned_async_meth', 'glob_assigned_async_meth_pep_695',
393-
))
394-
395-
# Test generator expressions that are of type TYPE_FUNCTION
396-
# but will not be reported by get_methods() since they are
397-
# not functions per se.
398-
#
399-
# Other kind of comprehensions such as list, set or dict
400-
# expressions do not have the TYPE_FUNCTION type.
401-
402-
def check_body(body, expected_methods):
403-
indented = textwrap.indent(body, ' ' * 4)
404-
top = symtable.symtable(f"class A:\n{indented}", "?", "exec")
405-
this = find_block(top, "A")
406-
with self.assertWarnsRegex(DeprecationWarning, deprecation_mess):
407-
self.assertEqual(this.get_methods(), expected_methods)
408-
409-
# statements with 'genexpr' inside it
410-
GENEXPRS = (
411-
'x = (x for x in [])',
412-
'x = (x async for x in [])',
413-
'type x[genexpr = (x for x in [])] = (x for x in [])',
414-
'type x[genexpr = (x async for x in [])] = (x async for x in [])',
415-
'genexpr = (x for x in [])',
416-
'genexpr = (x async for x in [])',
417-
'type genexpr[genexpr = (x for x in [])] = (x for x in [])',
418-
'type genexpr[genexpr = (x async for x in [])] = (x async for x in [])',
419-
)
420-
421-
for gen in GENEXPRS:
422-
# test generator expression
423-
with self.subTest(gen=gen):
424-
check_body(gen, ())
425-
426-
# test generator expression + variable named 'genexpr'
427-
with self.subTest(gen=gen, isvar=True):
428-
check_body('\n'.join((gen, 'genexpr = 1')), ())
429-
check_body('\n'.join(('genexpr = 1', gen)), ())
430-
431-
for paramlist in ('()', '(x)', '(x, y)', '(z: T)'):
432-
for func in (
433-
f'def genexpr{paramlist}:pass',
434-
f'async def genexpr{paramlist}:pass',
435-
f'def genexpr[T]{paramlist}:pass',
436-
f'async def genexpr[T]{paramlist}:pass',
437-
):
438-
with self.subTest(func=func):
439-
# test function named 'genexpr'
440-
check_body(func, ('genexpr',))
441-
442-
for gen in GENEXPRS:
443-
with self.subTest(gen=gen, func=func):
444-
# test generator expression + function named 'genexpr'
445-
check_body('\n'.join((gen, func)), ('genexpr',))
446-
check_body('\n'.join((func, gen)), ('genexpr',))
447-
448365
def test_filename_correct(self):
449366
### Bug tickler: SyntaxError file name correct whether error raised
450367
### while parsing or building symbol table.

Misc/NEWS.d/3.14.0a1.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2038,7 +2038,7 @@ Remove workarounds for non-IEEE 754 systems in :mod:`cmath`.
20382038
.. nonce: WlygzR
20392039
.. section: Library
20402040
2041-
Due to the lack of interest for :meth:`symtable.Class.get_methods`, the
2041+
Due to the lack of interest for :meth:`!symtable.Class.get_methods`, the
20422042
method is marked as deprecated and will be removed in Python 3.16. Patch by
20432043
Bénédikt Tran.
20442044

@@ -2746,7 +2746,7 @@ situations.
27462746
.. nonce: rRrprk
27472747
.. section: Library
27482748
2749-
Fix :meth:`symtable.Class.get_methods` and document its behaviour. Patch by
2749+
Fix :meth:`!symtable.Class.get_methods` and document its behaviour. Patch by
27502750
Bénédikt Tran.
27512751

27522752
..
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Removed :meth:`!symtable.Class.get_methods` which has been deprecated since
2+
3.14.

0 commit comments

Comments
 (0)