From 5360cf93fec65ff5ce526a948bdcae74485779d0 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Thu, 28 Sep 2023 18:06:53 -0700 Subject: [PATCH 1/4] gh-110045: Update symtable module for PEP 695 --- Lib/symtable.py | 11 +++++-- Lib/test/test_symtable.py | 31 +++++++++++++++++++ ...-09-28-18-08-02.gh-issue-110045.0YIGKv.rst | 2 ++ Modules/symtablemodule.c | 8 +++++ 4 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-09-28-18-08-02.gh-issue-110045.0YIGKv.rst diff --git a/Lib/symtable.py b/Lib/symtable.py index 5dd71ffc6b4f19..22a9df953fdd27 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -71,8 +71,15 @@ def get_type(self): return "function" if self._table.type == _symtable.TYPE_CLASS: return "class" - assert self._table.type in (1, 2, 3), \ - "unexpected type: {0}".format(self._table.type) + if self._table.type == _symtable.TYPE_ANNOTATION: + return "annotation" + if self._table.type == _symtable.TYPE_TYPE_VAR_BOUND: + return "TypeVar bound" + if self._table.type == _symtable.TYPE_TYPE_ALIAS: + return "type alias" + if self._table.type == _symtable.TYPE_TYPE_PARAM: + return "type parameter" + assert False, f"unexpected type: {self._table.type}" def get_id(self): """Return an identifier for the table. diff --git a/Lib/test/test_symtable.py b/Lib/test/test_symtable.py index 36cb7b3f242e4c..82c1d7c856a1e5 100644 --- a/Lib/test/test_symtable.py +++ b/Lib/test/test_symtable.py @@ -40,6 +40,15 @@ def foo(): def namespace_test(): pass def namespace_test(): pass + +type Alias = int +type GenericAlias[T] = list[T] + +def generic_spam[T](a): + pass + +class GenericMine[T: int]: + pass """ @@ -59,6 +68,14 @@ class SymtableTest(unittest.TestCase): internal = find_block(spam, "internal") other_internal = find_block(spam, "other_internal") foo = find_block(top, "foo") + Alias = find_block(top, "Alias") + GenericAlias = find_block(top, "GenericAlias") + GenericAlias_inner = find_block(GenericAlias, "GenericAlias") + generic_spam = find_block(top, "generic_spam") + generic_spam_inner = find_block(generic_spam, "generic_spam") + GenericMine = find_block(top, "GenericMine") + GenericMine_inner = find_block(GenericMine, "GenericMine") + T = find_block(GenericMine, "T") def test_type(self): self.assertEqual(self.top.get_type(), "module") @@ -66,6 +83,15 @@ def test_type(self): self.assertEqual(self.a_method.get_type(), "function") self.assertEqual(self.spam.get_type(), "function") self.assertEqual(self.internal.get_type(), "function") + self.assertEqual(self.foo.get_type(), "function") + self.assertEqual(self.Alias.get_type(), "type alias") + self.assertEqual(self.GenericAlias.get_type(), "type parameter") + self.assertEqual(self.GenericAlias_inner.get_type(), "type alias") + self.assertEqual(self.generic_spam.get_type(), "type parameter") + self.assertEqual(self.generic_spam_inner.get_type(), "function") + self.assertEqual(self.GenericMine.get_type(), "type parameter") + self.assertEqual(self.GenericMine_inner.get_type(), "class") + self.assertEqual(self.T.get_type(), "TypeVar bound") def test_id(self): self.assertGreater(self.top.get_id(), 0) @@ -73,6 +99,11 @@ def test_id(self): self.assertGreater(self.a_method.get_id(), 0) self.assertGreater(self.spam.get_id(), 0) self.assertGreater(self.internal.get_id(), 0) + self.assertGreater(self.foo.get_id(), 0) + self.assertGreater(self.Alias.get_id(), 0) + self.assertGreater(self.GenericAlias.get_id(), 0) + self.assertGreater(self.generic_spam.get_id(), 0) + self.assertGreater(self.GenericMine.get_id(), 0) def test_optimized(self): self.assertFalse(self.top.is_optimized()) diff --git a/Misc/NEWS.d/next/Library/2023-09-28-18-08-02.gh-issue-110045.0YIGKv.rst b/Misc/NEWS.d/next/Library/2023-09-28-18-08-02.gh-issue-110045.0YIGKv.rst new file mode 100644 index 00000000000000..44a6df1083762f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-09-28-18-08-02.gh-issue-110045.0YIGKv.rst @@ -0,0 +1,2 @@ +Update the :mod:`symtable` module to support the new scopes introduced by +:pep:`695`. diff --git a/Modules/symtablemodule.c b/Modules/symtablemodule.c index dba80034d310af..ddc9ac3324356d 100644 --- a/Modules/symtablemodule.c +++ b/Modules/symtablemodule.c @@ -86,6 +86,14 @@ symtable_init_constants(PyObject *m) if (PyModule_AddIntConstant(m, "TYPE_CLASS", ClassBlock) < 0) return -1; if (PyModule_AddIntConstant(m, "TYPE_MODULE", ModuleBlock) < 0) return -1; + if (PyModule_AddIntConstant(m, "TYPE_ANNOTATION", AnnotationBlock) < 0) + return -1; + if (PyModule_AddIntConstant(m, "TYPE_TYPE_VAR_BOUND", TypeVarBoundBlock) < 0) + return -1; + if (PyModule_AddIntConstant(m, "TYPE_TYPE_ALIAS", TypeAliasBlock) < 0) + return -1; + if (PyModule_AddIntConstant(m, "TYPE_TYPE_PARAM", TypeParamBlock) < 0) + return -1; if (PyModule_AddIntMacro(m, LOCAL) < 0) return -1; if (PyModule_AddIntMacro(m, GLOBAL_EXPLICIT) < 0) return -1; From 614958291421844f0c257acdaf53dcf6c5a838d1 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Thu, 28 Sep 2023 18:18:41 -0700 Subject: [PATCH 2/4] Update docstring --- Lib/symtable.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/symtable.py b/Lib/symtable.py index 22a9df953fdd27..4b0bc6f497a553 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -62,8 +62,8 @@ def __repr__(self): def get_type(self): """Return the type of the symbol table. - The values returned are 'class', 'module' and - 'function'. + The values returned are 'class', 'module', 'function', + 'annotation', 'TypeVar bound', 'type alias', and 'type parameter'. """ if self._table.type == _symtable.TYPE_MODULE: return "module" From 4d9c89324142e0e9126425e99280344abdb694ce Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Thu, 28 Sep 2023 18:31:14 -0700 Subject: [PATCH 3/4] docs --- Doc/library/symtable.rst | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index 65ff5bfe7abd61..85ff911baf126c 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -38,7 +38,13 @@ Examining Symbol Tables .. method:: get_type() Return the type of the symbol table. Possible values are ``'class'``, - ``'module'``, and ``'function'``. + ``'module'``, ``'function'``, ``'annotation'``, ``'TypeVar bound'``, + ``'type alias'``, and ``'type parameter'``. The latter four refer to + different flavors of :ref:`annotation scopes `. + + .. versionchanged:: 3.12:: + Added ``'annotation'``, ``'TypeVar bound'``, ``'type alias'``, + and ``'type parameter'`` as possible return values. .. method:: get_id() @@ -49,6 +55,10 @@ Examining Symbol Tables Return the table's name. This is the name of the class if the table is for a class, the name of the function if the table is for a function, or ``'top'`` if the table is global (:meth:`get_type` returns ``'module'``). + For type parameter scopes (which are used for generic classes, functions, + and type aliases), it is the name of the underlying class, function, or + type alias. For type alias scopes, it is the name of the type alias. + For :class:`~typing.TypeVar` bound scopes, it is the name of the ``TypeVar``. .. method:: get_lineno() From b19a8fcf6f9227d3aa7efa961772b83716d77ea4 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Thu, 28 Sep 2023 18:43:03 -0700 Subject: [PATCH 4/4] fix doc syntax --- Doc/library/symtable.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index 85ff911baf126c..85eae5f3822575 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -42,7 +42,7 @@ Examining Symbol Tables ``'type alias'``, and ``'type parameter'``. The latter four refer to different flavors of :ref:`annotation scopes `. - .. versionchanged:: 3.12:: + .. versionchanged:: 3.12 Added ``'annotation'``, ``'TypeVar bound'``, ``'type alias'``, and ``'type parameter'`` as possible return values.