types

Define names for built-in types that aren't directly accessible as a builtin.

  1"""
  2Define names for built-in types that aren't directly accessible as a builtin.
  3"""
  4
  5# Iterators in Python aren't a matter of type but of protocol.  A large
  6# and changing number of builtin types implement *some* flavor of
  7# iterator.  Don't check the type!  Use hasattr to check for both
  8# "__iter__" and "__next__" attributes instead.
  9
 10try:
 11    from _types import *
 12except ImportError:
 13    import sys
 14
 15    def _f(): pass
 16    FunctionType = type(_f)
 17    LambdaType = type(lambda: None)  # Same as FunctionType
 18    CodeType = type(_f.__code__)
 19    MappingProxyType = type(type.__dict__)
 20    SimpleNamespace = type(sys.implementation)
 21
 22    def _cell_factory():
 23        a = 1
 24        def f():
 25            nonlocal a
 26        return f.__closure__[0]
 27    CellType = type(_cell_factory())
 28
 29    def _g():
 30        yield 1
 31    GeneratorType = type(_g())
 32
 33    async def _c(): pass
 34    _c = _c()
 35    CoroutineType = type(_c)
 36    _c.close()  # Prevent ResourceWarning
 37
 38    async def _ag():
 39        yield
 40    _ag = _ag()
 41    AsyncGeneratorType = type(_ag)
 42
 43    class _C:
 44        def _m(self): pass
 45    MethodType = type(_C()._m)
 46
 47    BuiltinFunctionType = type(len)
 48    BuiltinMethodType = type([].append)  # Same as BuiltinFunctionType
 49
 50    WrapperDescriptorType = type(object.__init__)
 51    MethodWrapperType = type(object().__str__)
 52    MethodDescriptorType = type(str.join)
 53    ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
 54
 55    ModuleType = type(sys)
 56
 57    try:
 58        raise TypeError
 59    except TypeError as exc:
 60        TracebackType = type(exc.__traceback__)
 61        FrameType = type(exc.__traceback__.tb_frame)
 62
 63    GetSetDescriptorType = type(FunctionType.__code__)
 64    MemberDescriptorType = type(FunctionType.__globals__)
 65
 66    GenericAlias = type(list[int])
 67    UnionType = type(int | str)
 68
 69    EllipsisType = type(Ellipsis)
 70    NoneType = type(None)
 71    NotImplementedType = type(NotImplemented)
 72
 73    # CapsuleType cannot be accessed from pure Python,
 74    # so there is no fallback definition.
 75
 76    del sys, _f, _g, _C, _c, _ag, _cell_factory  # Not for export
 77
 78
 79# Provide a PEP 3115 compliant mechanism for class creation
 80def new_class(name, bases=(), kwds=None, exec_body=None):
 81    """Create a class object dynamically using the appropriate metaclass."""
 82    resolved_bases = resolve_bases(bases)
 83    meta, ns, kwds = prepare_class(name, resolved_bases, kwds)
 84    if exec_body is not None:
 85        exec_body(ns)
 86    if resolved_bases is not bases:
 87        ns['__orig_bases__'] = bases
 88    return meta(name, resolved_bases, ns, **kwds)
 89
 90def resolve_bases(bases):
 91    """Resolve MRO entries dynamically as specified by PEP 560."""
 92    new_bases = list(bases)
 93    updated = False
 94    shift = 0
 95    for i, base in enumerate(bases):
 96        if isinstance(base, type):
 97            continue
 98        if not hasattr(base, "__mro_entries__"):
 99            continue
100        new_base = base.__mro_entries__(bases)
101        updated = True
102        if not isinstance(new_base, tuple):
103            raise TypeError("__mro_entries__ must return a tuple")
104        else:
105            new_bases[i+shift:i+shift+1] = new_base
106            shift += len(new_base) - 1
107    if not updated:
108        return bases
109    return tuple(new_bases)
110
111def prepare_class(name, bases=(), kwds=None):
112    """Call the __prepare__ method of the appropriate metaclass.
113
114    Returns (metaclass, namespace, kwds) as a 3-tuple
115
116    *metaclass* is the appropriate metaclass
117    *namespace* is the prepared class namespace
118    *kwds* is an updated copy of the passed in kwds argument with any
119    'metaclass' entry removed. If no kwds argument is passed in, this will
120    be an empty dict.
121    """
122    if kwds is None:
123        kwds = {}
124    else:
125        kwds = dict(kwds) # Don't alter the provided mapping
126    if 'metaclass' in kwds:
127        meta = kwds.pop('metaclass')
128    else:
129        if bases:
130            meta = type(bases[0])
131        else:
132            meta = type
133    if isinstance(meta, type):
134        # when meta is a type, we first determine the most-derived metaclass
135        # instead of invoking the initial candidate directly
136        meta = _calculate_meta(meta, bases)
137    if hasattr(meta, '__prepare__'):
138        ns = meta.__prepare__(name, bases, **kwds)
139    else:
140        ns = {}
141    return meta, ns, kwds
142
143def _calculate_meta(meta, bases):
144    """Calculate the most derived metaclass."""
145    winner = meta
146    for base in bases:
147        base_meta = type(base)
148        if issubclass(winner, base_meta):
149            continue
150        if issubclass(base_meta, winner):
151            winner = base_meta
152            continue
153        # else:
154        raise TypeError("metaclass conflict: "
155                        "the metaclass of a derived class "
156                        "must be a (non-strict) subclass "
157                        "of the metaclasses of all its bases")
158    return winner
159
160
161def get_original_bases(cls, /):
162    """Return the class's "original" bases prior to modification by `__mro_entries__`.
163
164    Examples::
165
166        from typing import TypeVar, Generic, NamedTuple, TypedDict
167
168        T = TypeVar("T")
169        class Foo(Generic[T]): ...
170        class Bar(Foo[int], float): ...
171        class Baz(list[str]): ...
172        Eggs = NamedTuple("Eggs", [("a", int), ("b", str)])
173        Spam = TypedDict("Spam", {"a": int, "b": str})
174
175        assert get_original_bases(Bar) == (Foo[int], float)
176        assert get_original_bases(Baz) == (list[str],)
177        assert get_original_bases(Eggs) == (NamedTuple,)
178        assert get_original_bases(Spam) == (TypedDict,)
179        assert get_original_bases(int) == (object,)
180    """
181    try:
182        return cls.__dict__.get("__orig_bases__", cls.__bases__)
183    except AttributeError:
184        raise TypeError(
185            f"Expected an instance of type, not {type(cls).__name__!r}"
186        ) from None
187
188
189class DynamicClassAttribute:
190    """Route attribute access on a class to __getattr__.
191
192    This is a descriptor, used to define attributes that act differently when
193    accessed through an instance and through a class.  Instance access remains
194    normal, but access to an attribute through a class will be routed to the
195    class's __getattr__ method; this is done by raising AttributeError.
196
197    This allows one to have properties active on an instance, and have virtual
198    attributes on the class with the same name.  (Enum used this between Python
199    versions 3.4 - 3.9 .)
200
201    Subclass from this to use a different method of accessing virtual attributes
202    and still be treated properly by the inspect module. (Enum uses this since
203    Python 3.10 .)
204
205    """
206    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
207        self.fget = fget
208        self.fset = fset
209        self.fdel = fdel
210        # next two lines make DynamicClassAttribute act the same as property
211        self.__doc__ = doc or fget.__doc__
212        self.overwrite_doc = doc is None
213        # support for abstract methods
214        self.__isabstractmethod__ = bool(getattr(fget, '__isabstractmethod__', False))
215
216    def __get__(self, instance, ownerclass=None):
217        if instance is None:
218            if self.__isabstractmethod__:
219                return self
220            raise AttributeError()
221        elif self.fget is None:
222            raise AttributeError("unreadable attribute")
223        return self.fget(instance)
224
225    def __set__(self, instance, value):
226        if self.fset is None:
227            raise AttributeError("can't set attribute")
228        self.fset(instance, value)
229
230    def __delete__(self, instance):
231        if self.fdel is None:
232            raise AttributeError("can't delete attribute")
233        self.fdel(instance)
234
235    def getter(self, fget):
236        fdoc = fget.__doc__ if self.overwrite_doc else None
237        result = type(self)(fget, self.fset, self.fdel, fdoc or self.__doc__)
238        result.overwrite_doc = self.overwrite_doc
239        return result
240
241    def setter(self, fset):
242        result = type(self)(self.fget, fset, self.fdel, self.__doc__)
243        result.overwrite_doc = self.overwrite_doc
244        return result
245
246    def deleter(self, fdel):
247        result = type(self)(self.fget, self.fset, fdel, self.__doc__)
248        result.overwrite_doc = self.overwrite_doc
249        return result
250
251
252class _GeneratorWrapper:
253    # TODO: Implement this in C.
254    def __init__(self, gen):
255        self.__wrapped = gen
256        self.__isgen = gen.__class__ is GeneratorType
257        self.__name__ = getattr(gen, '__name__', None)
258        self.__qualname__ = getattr(gen, '__qualname__', None)
259    def send(self, val):
260        return self.__wrapped.send(val)
261    def throw(self, tp, *rest):
262        return self.__wrapped.throw(tp, *rest)
263    def close(self):
264        return self.__wrapped.close()
265    @property
266    def gi_code(self):
267        return self.__wrapped.gi_code
268    @property
269    def gi_frame(self):
270        return self.__wrapped.gi_frame
271    @property
272    def gi_running(self):
273        return self.__wrapped.gi_running
274    @property
275    def gi_yieldfrom(self):
276        return self.__wrapped.gi_yieldfrom
277    @property
278    def gi_suspended(self):
279        return self.__wrapped.gi_suspended
280    cr_code = gi_code
281    cr_frame = gi_frame
282    cr_running = gi_running
283    cr_await = gi_yieldfrom
284    cr_suspended = gi_suspended
285    def __next__(self):
286        return next(self.__wrapped)
287    def __iter__(self):
288        if self.__isgen:
289            return self.__wrapped
290        return self
291    __await__ = __iter__
292
293def coroutine(func):
294    """Convert regular generator function to a coroutine."""
295
296    if not callable(func):
297        raise TypeError('types.coroutine() expects a callable')
298
299    if (func.__class__ is FunctionType and
300        getattr(func, '__code__', None).__class__ is CodeType):
301
302        co_flags = func.__code__.co_flags
303
304        # Check if 'func' is a coroutine function.
305        # (0x180 == CO_COROUTINE | CO_ITERABLE_COROUTINE)
306        if co_flags & 0x180:
307            return func
308
309        # Check if 'func' is a generator function.
310        # (0x20 == CO_GENERATOR)
311        if co_flags & 0x20:
312            # TODO: Implement this in C.
313            co = func.__code__
314            # 0x100 == CO_ITERABLE_COROUTINE
315            func.__code__ = co.replace(co_flags=co.co_flags | 0x100)
316            return func
317
318    # The following code is primarily to support functions that
319    # return generator-like objects (for instance generators
320    # compiled with Cython).
321
322    # Delay functools and _collections_abc import for speeding up types import.
323    import functools
324    import _collections_abc
325    @functools.wraps(func)
326    def wrapped(*args, **kwargs):
327        coro = func(*args, **kwargs)
328        if (coro.__class__ is CoroutineType or
329            coro.__class__ is GeneratorType and coro.gi_code.co_flags & 0x100):
330            # 'coro' is a native coroutine object or an iterable coroutine
331            return coro
332        if (isinstance(coro, _collections_abc.Generator) and
333            not isinstance(coro, _collections_abc.Coroutine)):
334            # 'coro' is either a pure Python generator iterator, or it
335            # implements collections.abc.Generator (and does not implement
336            # collections.abc.Coroutine).
337            return _GeneratorWrapper(coro)
338        # 'coro' is either an instance of collections.abc.Coroutine or
339        # some other object -- pass it through.
340        return coro
341
342    return wrapped
343
344__all__ = [n for n in globals() if not n.startswith('_')]  # for pydoc
AsyncGeneratorType = <class 'async_generator'>
BuiltinFunctionType = <class 'builtin_function_or_method'>
BuiltinMethodType = <class 'builtin_function_or_method'>
CapsuleType = <class 'PyCapsule'>
CellType = <class 'cell'>
ClassMethodDescriptorType = <class 'classmethod_descriptor'>
CodeType = <class 'code'>
CoroutineType = <class 'coroutine'>
EllipsisType = <class 'ellipsis'>
FrameType = <class 'frame'>
FunctionType = <class 'function'>
GeneratorType = <class 'generator'>
class GenericAlias:

Represent a PEP 585 generic type

E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

GetSetDescriptorType = <class 'getset_descriptor'>
LambdaType = <class 'function'>
MappingProxyType = <class 'mappingproxy'>
MemberDescriptorType = <class 'member_descriptor'>
MethodDescriptorType = <class 'method_descriptor'>
MethodType = <class 'method'>
MethodWrapperType = <class 'method-wrapper'>
ModuleType = <class 'module'>
class NoneType:

The type of the None singleton.

class NotImplementedType:

The type of the NotImplemented singleton.

class SimpleNamespace:

A simple attribute-based namespace.

SimpleNamespace(*args, **kwargs)
TracebackType = <class 'traceback'>
UnionType = <class 'typing.Union'>
WrapperDescriptorType = <class 'wrapper_descriptor'>
def new_class(name, bases=(), kwds=None, exec_body=None):
81def new_class(name, bases=(), kwds=None, exec_body=None):
82    """Create a class object dynamically using the appropriate metaclass."""
83    resolved_bases = resolve_bases(bases)
84    meta, ns, kwds = prepare_class(name, resolved_bases, kwds)
85    if exec_body is not None:
86        exec_body(ns)
87    if resolved_bases is not bases:
88        ns['__orig_bases__'] = bases
89    return meta(name, resolved_bases, ns, **kwds)

Create a class object dynamically using the appropriate metaclass.

def resolve_bases(bases):
 91def resolve_bases(bases):
 92    """Resolve MRO entries dynamically as specified by PEP 560."""
 93    new_bases = list(bases)
 94    updated = False
 95    shift = 0
 96    for i, base in enumerate(bases):
 97        if isinstance(base, type):
 98            continue
 99        if not hasattr(base, "__mro_entries__"):
100            continue
101        new_base = base.__mro_entries__(bases)
102        updated = True
103        if not isinstance(new_base, tuple):
104            raise TypeError("__mro_entries__ must return a tuple")
105        else:
106            new_bases[i+shift:i+shift+1] = new_base
107            shift += len(new_base) - 1
108    if not updated:
109        return bases
110    return tuple(new_bases)

Resolve MRO entries dynamically as specified by PEP 560.

def prepare_class(name, bases=(), kwds=None):
112def prepare_class(name, bases=(), kwds=None):
113    """Call the __prepare__ method of the appropriate metaclass.
114
115    Returns (metaclass, namespace, kwds) as a 3-tuple
116
117    *metaclass* is the appropriate metaclass
118    *namespace* is the prepared class namespace
119    *kwds* is an updated copy of the passed in kwds argument with any
120    'metaclass' entry removed. If no kwds argument is passed in, this will
121    be an empty dict.
122    """
123    if kwds is None:
124        kwds = {}
125    else:
126        kwds = dict(kwds) # Don't alter the provided mapping
127    if 'metaclass' in kwds:
128        meta = kwds.pop('metaclass')
129    else:
130        if bases:
131            meta = type(bases[0])
132        else:
133            meta = type
134    if isinstance(meta, type):
135        # when meta is a type, we first determine the most-derived metaclass
136        # instead of invoking the initial candidate directly
137        meta = _calculate_meta(meta, bases)
138    if hasattr(meta, '__prepare__'):
139        ns = meta.__prepare__(name, bases, **kwds)
140    else:
141        ns = {}
142    return meta, ns, kwds

Call the __prepare__ method of the appropriate metaclass.

Returns (metaclass, namespace, kwds) as a 3-tuple

metaclass is the appropriate metaclass namespace is the prepared class namespace kwds is an updated copy of the passed in kwds argument with any 'metaclass' entry removed. If no kwds argument is passed in, this will be an empty dict.

def get_original_bases(cls, /):
162def get_original_bases(cls, /):
163    """Return the class's "original" bases prior to modification by `__mro_entries__`.
164
165    Examples::
166
167        from typing import TypeVar, Generic, NamedTuple, TypedDict
168
169        T = TypeVar("T")
170        class Foo(Generic[T]): ...
171        class Bar(Foo[int], float): ...
172        class Baz(list[str]): ...
173        Eggs = NamedTuple("Eggs", [("a", int), ("b", str)])
174        Spam = TypedDict("Spam", {"a": int, "b": str})
175
176        assert get_original_bases(Bar) == (Foo[int], float)
177        assert get_original_bases(Baz) == (list[str],)
178        assert get_original_bases(Eggs) == (NamedTuple,)
179        assert get_original_bases(Spam) == (TypedDict,)
180        assert get_original_bases(int) == (object,)
181    """
182    try:
183        return cls.__dict__.get("__orig_bases__", cls.__bases__)
184    except AttributeError:
185        raise TypeError(
186            f"Expected an instance of type, not {type(cls).__name__!r}"
187        ) from None

Return the class's "original" bases prior to modification by __mro_entries__.

Examples::

from typing import TypeVar, Generic, NamedTuple, TypedDict

T = TypeVar("T")
class Foo(Generic[T]): ...
class Bar(Foo[int], float): ...
class Baz(list[str]): ...
Eggs = NamedTuple("Eggs", [("a", int), ("b", str)])
Spam = TypedDict("Spam", {"a": int, "b": str})

assert get_original_bases(Bar) == (Foo[int], float)
assert get_original_bases(Baz) == (list[str],)
assert get_original_bases(Eggs) == (NamedTuple,)
assert get_original_bases(Spam) == (TypedDict,)
assert get_original_bases(int) == (object,)
class DynamicClassAttribute:
190class DynamicClassAttribute:
191    """Route attribute access on a class to __getattr__.
192
193    This is a descriptor, used to define attributes that act differently when
194    accessed through an instance and through a class.  Instance access remains
195    normal, but access to an attribute through a class will be routed to the
196    class's __getattr__ method; this is done by raising AttributeError.
197
198    This allows one to have properties active on an instance, and have virtual
199    attributes on the class with the same name.  (Enum used this between Python
200    versions 3.4 - 3.9 .)
201
202    Subclass from this to use a different method of accessing virtual attributes
203    and still be treated properly by the inspect module. (Enum uses this since
204    Python 3.10 .)
205
206    """
207    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
208        self.fget = fget
209        self.fset = fset
210        self.fdel = fdel
211        # next two lines make DynamicClassAttribute act the same as property
212        self.__doc__ = doc or fget.__doc__
213        self.overwrite_doc = doc is None
214        # support for abstract methods
215        self.__isabstractmethod__ = bool(getattr(fget, '__isabstractmethod__', False))
216
217    def __get__(self, instance, ownerclass=None):
218        if instance is None:
219            if self.__isabstractmethod__:
220                return self
221            raise AttributeError()
222        elif self.fget is None:
223            raise AttributeError("unreadable attribute")
224        return self.fget(instance)
225
226    def __set__(self, instance, value):
227        if self.fset is None:
228            raise AttributeError("can't set attribute")
229        self.fset(instance, value)
230
231    def __delete__(self, instance):
232        if self.fdel is None:
233            raise AttributeError("can't delete attribute")
234        self.fdel(instance)
235
236    def getter(self, fget):
237        fdoc = fget.__doc__ if self.overwrite_doc else None
238        result = type(self)(fget, self.fset, self.fdel, fdoc or self.__doc__)
239        result.overwrite_doc = self.overwrite_doc
240        return result
241
242    def setter(self, fset):
243        result = type(self)(self.fget, fset, self.fdel, self.__doc__)
244        result.overwrite_doc = self.overwrite_doc
245        return result
246
247    def deleter(self, fdel):
248        result = type(self)(self.fget, self.fset, fdel, self.__doc__)
249        result.overwrite_doc = self.overwrite_doc
250        return result

Route attribute access on a class to __getattr__.

This is a descriptor, used to define attributes that act differently when accessed through an instance and through a class. Instance access remains normal, but access to an attribute through a class will be routed to the class's __getattr__ method; this is done by raising AttributeError.

This allows one to have properties active on an instance, and have virtual attributes on the class with the same name. (Enum used this between Python versions 3.4 - 3.9 .)

Subclass from this to use a different method of accessing virtual attributes and still be treated properly by the inspect module. (Enum uses this since Python 3.10 .)

DynamicClassAttribute(fget=None, fset=None, fdel=None, doc=None)
207    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
208        self.fget = fget
209        self.fset = fset
210        self.fdel = fdel
211        # next two lines make DynamicClassAttribute act the same as property
212        self.__doc__ = doc or fget.__doc__
213        self.overwrite_doc = doc is None
214        # support for abstract methods
215        self.__isabstractmethod__ = bool(getattr(fget, '__isabstractmethod__', False))
fget
fset
fdel
overwrite_doc
def getter(self, fget):
236    def getter(self, fget):
237        fdoc = fget.__doc__ if self.overwrite_doc else None
238        result = type(self)(fget, self.fset, self.fdel, fdoc or self.__doc__)
239        result.overwrite_doc = self.overwrite_doc
240        return result
def setter(self, fset):
242    def setter(self, fset):
243        result = type(self)(self.fget, fset, self.fdel, self.__doc__)
244        result.overwrite_doc = self.overwrite_doc
245        return result
def deleter(self, fdel):
247    def deleter(self, fdel):
248        result = type(self)(self.fget, self.fset, fdel, self.__doc__)
249        result.overwrite_doc = self.overwrite_doc
250        return result
def coroutine(func):
294def coroutine(func):
295    """Convert regular generator function to a coroutine."""
296
297    if not callable(func):
298        raise TypeError('types.coroutine() expects a callable')
299
300    if (func.__class__ is FunctionType and
301        getattr(func, '__code__', None).__class__ is CodeType):
302
303        co_flags = func.__code__.co_flags
304
305        # Check if 'func' is a coroutine function.
306        # (0x180 == CO_COROUTINE | CO_ITERABLE_COROUTINE)
307        if co_flags & 0x180:
308            return func
309
310        # Check if 'func' is a generator function.
311        # (0x20 == CO_GENERATOR)
312        if co_flags & 0x20:
313            # TODO: Implement this in C.
314            co = func.__code__
315            # 0x100 == CO_ITERABLE_COROUTINE
316            func.__code__ = co.replace(co_flags=co.co_flags | 0x100)
317            return func
318
319    # The following code is primarily to support functions that
320    # return generator-like objects (for instance generators
321    # compiled with Cython).
322
323    # Delay functools and _collections_abc import for speeding up types import.
324    import functools
325    import _collections_abc
326    @functools.wraps(func)
327    def wrapped(*args, **kwargs):
328        coro = func(*args, **kwargs)
329        if (coro.__class__ is CoroutineType or
330            coro.__class__ is GeneratorType and coro.gi_code.co_flags & 0x100):
331            # 'coro' is a native coroutine object or an iterable coroutine
332            return coro
333        if (isinstance(coro, _collections_abc.Generator) and
334            not isinstance(coro, _collections_abc.Coroutine)):
335            # 'coro' is either a pure Python generator iterator, or it
336            # implements collections.abc.Generator (and does not implement
337            # collections.abc.Coroutine).
338            return _GeneratorWrapper(coro)
339        # 'coro' is either an instance of collections.abc.Coroutine or
340        # some other object -- pass it through.
341        return coro
342
343    return wrapped

Convert regular generator function to a coroutine.