Skip to content

Commit 7dc2c50

Browse files
gh-110045: Update symtable module for PEP 695 (#110066)
1 parent 2e37a38 commit 7dc2c50

File tree

5 files changed

+63
-5
lines changed

5 files changed

+63
-5
lines changed

Doc/library/symtable.rst

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@ Examining Symbol Tables
3838
.. method:: get_type()
3939

4040
Return the type of the symbol table. Possible values are ``'class'``,
41-
``'module'``, and ``'function'``.
41+
``'module'``, ``'function'``, ``'annotation'``, ``'TypeVar bound'``,
42+
``'type alias'``, and ``'type parameter'``. The latter four refer to
43+
different flavors of :ref:`annotation scopes <annotation-scopes>`.
44+
45+
.. versionchanged:: 3.12
46+
Added ``'annotation'``, ``'TypeVar bound'``, ``'type alias'``,
47+
and ``'type parameter'`` as possible return values.
4248

4349
.. method:: get_id()
4450

@@ -49,6 +55,10 @@ Examining Symbol Tables
4955
Return the table's name. This is the name of the class if the table is
5056
for a class, the name of the function if the table is for a function, or
5157
``'top'`` if the table is global (:meth:`get_type` returns ``'module'``).
58+
For type parameter scopes (which are used for generic classes, functions,
59+
and type aliases), it is the name of the underlying class, function, or
60+
type alias. For type alias scopes, it is the name of the type alias.
61+
For :class:`~typing.TypeVar` bound scopes, it is the name of the ``TypeVar``.
5262

5363
.. method:: get_lineno()
5464

Lib/symtable.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,24 @@ def __repr__(self):
6262
def get_type(self):
6363
"""Return the type of the symbol table.
6464
65-
The values returned are 'class', 'module' and
66-
'function'.
65+
The values returned are 'class', 'module', 'function',
66+
'annotation', 'TypeVar bound', 'type alias', and 'type parameter'.
6767
"""
6868
if self._table.type == _symtable.TYPE_MODULE:
6969
return "module"
7070
if self._table.type == _symtable.TYPE_FUNCTION:
7171
return "function"
7272
if self._table.type == _symtable.TYPE_CLASS:
7373
return "class"
74-
assert self._table.type in (1, 2, 3), \
75-
"unexpected type: {0}".format(self._table.type)
74+
if self._table.type == _symtable.TYPE_ANNOTATION:
75+
return "annotation"
76+
if self._table.type == _symtable.TYPE_TYPE_VAR_BOUND:
77+
return "TypeVar bound"
78+
if self._table.type == _symtable.TYPE_TYPE_ALIAS:
79+
return "type alias"
80+
if self._table.type == _symtable.TYPE_TYPE_PARAM:
81+
return "type parameter"
82+
assert False, f"unexpected type: {self._table.type}"
7683

7784
def get_id(self):
7885
"""Return an identifier for the table.

Lib/test/test_symtable.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ def foo():
4040
4141
def namespace_test(): pass
4242
def namespace_test(): pass
43+
44+
type Alias = int
45+
type GenericAlias[T] = list[T]
46+
47+
def generic_spam[T](a):
48+
pass
49+
50+
class GenericMine[T: int]:
51+
pass
4352
"""
4453

4554

@@ -59,20 +68,42 @@ class SymtableTest(unittest.TestCase):
5968
internal = find_block(spam, "internal")
6069
other_internal = find_block(spam, "other_internal")
6170
foo = find_block(top, "foo")
71+
Alias = find_block(top, "Alias")
72+
GenericAlias = find_block(top, "GenericAlias")
73+
GenericAlias_inner = find_block(GenericAlias, "GenericAlias")
74+
generic_spam = find_block(top, "generic_spam")
75+
generic_spam_inner = find_block(generic_spam, "generic_spam")
76+
GenericMine = find_block(top, "GenericMine")
77+
GenericMine_inner = find_block(GenericMine, "GenericMine")
78+
T = find_block(GenericMine, "T")
6279

6380
def test_type(self):
6481
self.assertEqual(self.top.get_type(), "module")
6582
self.assertEqual(self.Mine.get_type(), "class")
6683
self.assertEqual(self.a_method.get_type(), "function")
6784
self.assertEqual(self.spam.get_type(), "function")
6885
self.assertEqual(self.internal.get_type(), "function")
86+
self.assertEqual(self.foo.get_type(), "function")
87+
self.assertEqual(self.Alias.get_type(), "type alias")
88+
self.assertEqual(self.GenericAlias.get_type(), "type parameter")
89+
self.assertEqual(self.GenericAlias_inner.get_type(), "type alias")
90+
self.assertEqual(self.generic_spam.get_type(), "type parameter")
91+
self.assertEqual(self.generic_spam_inner.get_type(), "function")
92+
self.assertEqual(self.GenericMine.get_type(), "type parameter")
93+
self.assertEqual(self.GenericMine_inner.get_type(), "class")
94+
self.assertEqual(self.T.get_type(), "TypeVar bound")
6995

7096
def test_id(self):
7197
self.assertGreater(self.top.get_id(), 0)
7298
self.assertGreater(self.Mine.get_id(), 0)
7399
self.assertGreater(self.a_method.get_id(), 0)
74100
self.assertGreater(self.spam.get_id(), 0)
75101
self.assertGreater(self.internal.get_id(), 0)
102+
self.assertGreater(self.foo.get_id(), 0)
103+
self.assertGreater(self.Alias.get_id(), 0)
104+
self.assertGreater(self.GenericAlias.get_id(), 0)
105+
self.assertGreater(self.generic_spam.get_id(), 0)
106+
self.assertGreater(self.GenericMine.get_id(), 0)
76107

77108
def test_optimized(self):
78109
self.assertFalse(self.top.is_optimized())
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Update the :mod:`symtable` module to support the new scopes introduced by
2+
:pep:`695`.

Modules/symtablemodule.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ symtable_init_constants(PyObject *m)
8686
if (PyModule_AddIntConstant(m, "TYPE_CLASS", ClassBlock) < 0) return -1;
8787
if (PyModule_AddIntConstant(m, "TYPE_MODULE", ModuleBlock) < 0)
8888
return -1;
89+
if (PyModule_AddIntConstant(m, "TYPE_ANNOTATION", AnnotationBlock) < 0)
90+
return -1;
91+
if (PyModule_AddIntConstant(m, "TYPE_TYPE_VAR_BOUND", TypeVarBoundBlock) < 0)
92+
return -1;
93+
if (PyModule_AddIntConstant(m, "TYPE_TYPE_ALIAS", TypeAliasBlock) < 0)
94+
return -1;
95+
if (PyModule_AddIntConstant(m, "TYPE_TYPE_PARAM", TypeParamBlock) < 0)
96+
return -1;
8997

9098
if (PyModule_AddIntMacro(m, LOCAL) < 0) return -1;
9199
if (PyModule_AddIntMacro(m, GLOBAL_EXPLICIT) < 0) return -1;

0 commit comments

Comments
 (0)