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