https://github.com/python/cpython/commit/1755157207cf46eeb5037ddb80576c5840372c21
commit: 1755157207cf46eeb5037ddb80576c5840372c21
branch: main
author: Adam Turner <9087854+aa-tur...@users.noreply.github.com>
committer: AA-Turner <9087854+aa-tur...@users.noreply.github.com>
date: 2025-04-05T18:11:07Z
summary:

GH-118761: Expose more core interpreter types in ``_types`` (#132103)

Co-authored-by: Bénédikt Tran <10796600+picn...@users.noreply.github.com>
Co-authored-by: Peter Bierma <zintensity...@gmail.com>

files:
M Lib/test/test_types.py
M Lib/types.py
M Modules/_typesmodule.c

diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py
index 350567ec7e990d..f9e12931a63e4f 100644
--- a/Lib/test/test_types.py
+++ b/Lib/test/test_types.py
@@ -4,6 +4,8 @@
     run_with_locale, cpython_only, no_rerun,
     MISSING_C_DOCSTRINGS, EqualToForwardRef,
 )
+from test.support.import_helper import import_fresh_module
+
 import collections.abc
 from collections import namedtuple, UserDict
 import copy
@@ -19,6 +21,8 @@
 import weakref
 import typing
 
+c_types = import_fresh_module('types', fresh=['_types'])
+py_types = import_fresh_module('types', blocked=['_types'])
 
 T = typing.TypeVar("T")
 
@@ -34,6 +38,28 @@ def clear_typing_caches():
 
 class TypesTests(unittest.TestCase):
 
+    def test_names(self):
+        c_only_names = {'CapsuleType'}
+        ignored = {'new_class', 'resolve_bases', 'prepare_class',
+                   'get_original_bases', 'DynamicClassAttribute', 'coroutine'}
+
+        for name in c_types.__all__:
+            if name not in c_only_names | ignored:
+                self.assertIs(getattr(c_types, name), getattr(py_types, name))
+
+        all_names = ignored | {
+            'AsyncGeneratorType', 'BuiltinFunctionType', 'BuiltinMethodType',
+            'CapsuleType', 'CellType', 'ClassMethodDescriptorType', 'CodeType',
+            'CoroutineType', 'EllipsisType', 'FrameType', 'FunctionType',
+            'GeneratorType', 'GenericAlias', 'GetSetDescriptorType',
+            'LambdaType', 'MappingProxyType', 'MemberDescriptorType',
+            'MethodDescriptorType', 'MethodType', 'MethodWrapperType',
+            'ModuleType', 'NoneType', 'NotImplementedType', 'SimpleNamespace',
+            'TracebackType', 'UnionType', 'WrapperDescriptorType',
+        }
+        self.assertEqual(all_names, set(c_types.__all__))
+        self.assertEqual(all_names - c_only_names, set(py_types.__all__))
+
     def test_truth_values(self):
         if None: self.fail('None is true instead of false')
         if 0: self.fail('0 is true instead of false')
diff --git a/Lib/types.py b/Lib/types.py
index 9aa0a3b087c1c7..6efac3394345a5 100644
--- a/Lib/types.py
+++ b/Lib/types.py
@@ -2,67 +2,78 @@
 Define names for built-in types that aren't directly accessible as a builtin.
 """
 
-import _types
-
 # Iterators in Python aren't a matter of type but of protocol.  A large
 # and changing number of builtin types implement *some* flavor of
 # iterator.  Don't check the type!  Use hasattr to check for both
 # "__iter__" and "__next__" attributes instead.
 
-def _f(): pass
-FunctionType = type(_f)
-LambdaType = type(lambda: None)         # Same as FunctionType
-CodeType = type(_f.__code__)
-MappingProxyType = type(type.__dict__)
-SimpleNamespace = _types.SimpleNamespace
-
-def _cell_factory():
-    a = 1
-    def f():
-        nonlocal a
-    return f.__closure__[0]
-CellType = type(_cell_factory())
-
-def _g():
-    yield 1
-GeneratorType = type(_g())
-
-async def _c(): pass
-_c = _c()
-CoroutineType = type(_c)
-_c.close()  # Prevent ResourceWarning
-
-async def _ag():
-    yield
-_ag = _ag()
-AsyncGeneratorType = type(_ag)
-
-class _C:
-    def _m(self): pass
-MethodType = type(_C()._m)
-
-BuiltinFunctionType = type(len)
-BuiltinMethodType = type([].append)     # Same as BuiltinFunctionType
+try:
+    from _types import *
+except ImportError:
+    import sys
+
+    def _f(): pass
+    FunctionType = type(_f)
+    LambdaType = type(lambda: None)  # Same as FunctionType
+    CodeType = type(_f.__code__)
+    MappingProxyType = type(type.__dict__)
+    SimpleNamespace = type(sys.implementation)
+
+    def _cell_factory():
+        a = 1
+        def f():
+            nonlocal a
+        return f.__closure__[0]
+    CellType = type(_cell_factory())
+
+    def _g():
+        yield 1
+    GeneratorType = type(_g())
+
+    async def _c(): pass
+    _c = _c()
+    CoroutineType = type(_c)
+    _c.close()  # Prevent ResourceWarning
+
+    async def _ag():
+        yield
+    _ag = _ag()
+    AsyncGeneratorType = type(_ag)
+
+    class _C:
+        def _m(self): pass
+    MethodType = type(_C()._m)
+
+    BuiltinFunctionType = type(len)
+    BuiltinMethodType = type([].append)  # Same as BuiltinFunctionType
+
+    WrapperDescriptorType = type(object.__init__)
+    MethodWrapperType = type(object().__str__)
+    MethodDescriptorType = type(str.join)
+    ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
+
+    ModuleType = type(sys)
 
-WrapperDescriptorType = type(object.__init__)
-MethodWrapperType = type(object().__str__)
-MethodDescriptorType = type(str.join)
-ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
+    try:
+        raise TypeError
+    except TypeError as exc:
+        TracebackType = type(exc.__traceback__)
+        FrameType = type(exc.__traceback__.tb_frame)
 
-ModuleType = type(_types)
+    GetSetDescriptorType = type(FunctionType.__code__)
+    MemberDescriptorType = type(FunctionType.__globals__)
 
-try:
-    raise TypeError
-except TypeError as exc:
-    TracebackType = type(exc.__traceback__)
-    FrameType = type(exc.__traceback__.tb_frame)
+    GenericAlias = type(list[int])
+    UnionType = type(int | str)
 
-GetSetDescriptorType = type(FunctionType.__code__)
-MemberDescriptorType = type(FunctionType.__globals__)
+    EllipsisType = type(Ellipsis)
+    NoneType = type(None)
+    NotImplementedType = type(NotImplemented)
 
-CapsuleType = _types.CapsuleType
+    # CapsuleType cannot be accessed from pure Python,
+    # so there is no fallback definition.
 
-del _types, _f, _g, _C, _c, _ag, _cell_factory  # Not for export
+    del sys, _f, _g, _C, _c, _ag, _cell_factory  # Not for export
 
 
 # Provide a PEP 3115 compliant mechanism for class creation
@@ -326,11 +337,4 @@ def wrapped(*args, **kwargs):
 
     return wrapped
 
-GenericAlias = type(list[int])
-UnionType = type(int | str)
-
-EllipsisType = type(Ellipsis)
-NoneType = type(None)
-NotImplementedType = type(NotImplemented)
-
 __all__ = [n for n in globals() if not n.startswith('_')]  # for pydoc
diff --git a/Modules/_typesmodule.c b/Modules/_typesmodule.c
index aabb35f47eefc3..a30a88196e7192 100644
--- a/Modules/_typesmodule.c
+++ b/Modules/_typesmodule.c
@@ -1,17 +1,52 @@
 /* _types module */
 
 #include "Python.h"
+#include "pycore_descrobject.h"   // _PyMethodWrapper_Type
 #include "pycore_namespace.h"     // _PyNamespace_Type
+#include "pycore_object.h"        // _PyNone_Type, _PyNotImplemented_Type
+#include "pycore_unionobject.h"   // _PyUnion_Type
 
 static int
 _types_exec(PyObject *m)
 {
-    if (PyModule_AddObjectRef(m, "CapsuleType", (PyObject *)&PyCapsule_Type) < 
0) {
-        return -1;
-    }
-    if (PyModule_AddObjectRef(m, "SimpleNamespace", (PyObject 
*)&_PyNamespace_Type) < 0) {
-        return -1;
-    }
+#define EXPORT_STATIC_TYPE(NAME, TYPE)                                   \
+    do {                                                                 \
+        assert(PyUnstable_IsImmortal((PyObject *)&(TYPE)));              \
+        if (PyModule_AddObjectRef(m, (NAME), (PyObject *)&(TYPE)) < 0) { \
+            return -1;                                                   \
+        }                                                                \
+    } while (0)
+
+    EXPORT_STATIC_TYPE("AsyncGeneratorType", PyAsyncGen_Type);
+    EXPORT_STATIC_TYPE("BuiltinFunctionType", PyCFunction_Type);
+    // BuiltinMethodType is the same as BuiltinFunctionType
+    EXPORT_STATIC_TYPE("BuiltinMethodType", PyCFunction_Type);
+    EXPORT_STATIC_TYPE("CapsuleType", PyCapsule_Type);
+    EXPORT_STATIC_TYPE("CellType", PyCell_Type);
+    EXPORT_STATIC_TYPE("ClassMethodDescriptorType", PyClassMethodDescr_Type);
+    EXPORT_STATIC_TYPE("CodeType", PyCode_Type);
+    EXPORT_STATIC_TYPE("CoroutineType", PyCoro_Type);
+    EXPORT_STATIC_TYPE("EllipsisType", PyEllipsis_Type);
+    EXPORT_STATIC_TYPE("FrameType", PyFrame_Type);
+    EXPORT_STATIC_TYPE("FunctionType", PyFunction_Type);
+    EXPORT_STATIC_TYPE("GeneratorType", PyGen_Type);
+    EXPORT_STATIC_TYPE("GenericAlias", Py_GenericAliasType);
+    EXPORT_STATIC_TYPE("GetSetDescriptorType", PyGetSetDescr_Type);
+    // LambdaType is the same as FunctionType
+    EXPORT_STATIC_TYPE("LambdaType", PyFunction_Type);
+    EXPORT_STATIC_TYPE("MappingProxyType", PyDictProxy_Type);
+    EXPORT_STATIC_TYPE("MemberDescriptorType", PyMemberDescr_Type);
+    EXPORT_STATIC_TYPE("MethodDescriptorType", PyMethodDescr_Type);
+    EXPORT_STATIC_TYPE("MethodType", PyMethod_Type);
+    EXPORT_STATIC_TYPE("MethodWrapperType", _PyMethodWrapper_Type);
+    EXPORT_STATIC_TYPE("ModuleType", PyModule_Type);
+    EXPORT_STATIC_TYPE("NoneType", _PyNone_Type);
+    EXPORT_STATIC_TYPE("NotImplementedType", _PyNotImplemented_Type);
+    EXPORT_STATIC_TYPE("SimpleNamespace", _PyNamespace_Type);
+    EXPORT_STATIC_TYPE("TracebackType", PyTraceBack_Type);
+    EXPORT_STATIC_TYPE("UnionType", _PyUnion_Type);
+    EXPORT_STATIC_TYPE("WrapperDescriptorType", PyWrapperDescr_Type);
+#undef EXPORT_STATIC_TYPE
     return 0;
 }
 

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to