mirror of
https://github.com/python/cpython.git
synced 2025-07-07 11:25:30 +00:00
GH-118761: Expose more core interpreter types in `_types
` (#132103)
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
This commit is contained in:
parent
92fb949eac
commit
1755157207
3 changed files with 130 additions and 65 deletions
|
@ -4,6 +4,8 @@ from test.support import (
|
|||
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 unittest.mock
|
|||
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')
|
||||
|
|
122
Lib/types.py
122
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
|
||||
|
||||
WrapperDescriptorType = type(object.__init__)
|
||||
MethodWrapperType = type(object().__str__)
|
||||
MethodDescriptorType = type(str.join)
|
||||
ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
|
||||
|
||||
ModuleType = type(_types)
|
||||
|
||||
try:
|
||||
raise TypeError
|
||||
except TypeError as exc:
|
||||
TracebackType = type(exc.__traceback__)
|
||||
FrameType = type(exc.__traceback__.tb_frame)
|
||||
from _types import *
|
||||
except ImportError:
|
||||
import sys
|
||||
|
||||
GetSetDescriptorType = type(FunctionType.__code__)
|
||||
MemberDescriptorType = type(FunctionType.__globals__)
|
||||
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)
|
||||
|
||||
CapsuleType = _types.CapsuleType
|
||||
def _cell_factory():
|
||||
a = 1
|
||||
def f():
|
||||
nonlocal a
|
||||
return f.__closure__[0]
|
||||
CellType = type(_cell_factory())
|
||||
|
||||
del _types, _f, _g, _C, _c, _ag, _cell_factory # Not for export
|
||||
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)
|
||||
|
||||
try:
|
||||
raise TypeError
|
||||
except TypeError as exc:
|
||||
TracebackType = type(exc.__traceback__)
|
||||
FrameType = type(exc.__traceback__.tb_frame)
|
||||
|
||||
GetSetDescriptorType = type(FunctionType.__code__)
|
||||
MemberDescriptorType = type(FunctionType.__globals__)
|
||||
|
||||
GenericAlias = type(list[int])
|
||||
UnionType = type(int | str)
|
||||
|
||||
EllipsisType = type(Ellipsis)
|
||||
NoneType = type(None)
|
||||
NotImplementedType = type(NotImplemented)
|
||||
|
||||
# CapsuleType cannot be accessed from pure Python,
|
||||
# so there is no fallback definition.
|
||||
|
||||
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 coroutine(func):
|
|||
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue