]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-110045: Update symtable module for PEP 695 (#110066)
authorJelle Zijlstra <jelle.zijlstra@gmail.com>
Fri, 29 Sep 2023 02:08:04 +0000 (19:08 -0700)
committerGitHub <noreply@github.com>
Fri, 29 Sep 2023 02:08:04 +0000 (02:08 +0000)
Doc/library/symtable.rst
Lib/symtable.py
Lib/test/test_symtable.py
Misc/NEWS.d/next/Library/2023-09-28-18-08-02.gh-issue-110045.0YIGKv.rst [new file with mode: 0644]
Modules/symtablemodule.c

index 65ff5bfe7abd61867e699e764fefc620cfbaa985..85eae5f38225758cca0c4862f21073a6d79b0b50 100644 (file)
@@ -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 <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()
 
index 5dd71ffc6b4f195eb938549f6debc21c3f047d57..4b0bc6f497a5535d5944b6d9fd0b027161ac1f9d 100644 (file)
@@ -62,8 +62,8 @@ class SymbolTable:
     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"
@@ -71,8 +71,15 @@ class SymbolTable:
             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.
index 36cb7b3f242e4cc659cb4e476baffbe2fe2c04a2..82c1d7c856a1e599c46fec9fcffc4d0db3a5c959 100644 (file)
@@ -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 @@ class SymtableTest(unittest.TestCase):
         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 @@ class SymtableTest(unittest.TestCase):
         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 (file)
index 0000000..44a6df1
--- /dev/null
@@ -0,0 +1,2 @@
+Update the :mod:`symtable` module to support the new scopes introduced by
+:pep:`695`.
index dba80034d310af3b7772cb5d47832b76b5303d24..ddc9ac3324356dc37b0a3f714cea159ba8cff327 100644 (file)
@@ -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;