types.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. """
  2. Define names for built-in types that aren't directly accessible as a builtin.
  3. """
  4. import sys
  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. def _f(): pass
  10. FunctionType = type(_f)
  11. LambdaType = type(lambda: None) # Same as FunctionType
  12. CodeType = type(_f.__code__)
  13. MappingProxyType = type(type.__dict__)
  14. SimpleNamespace = type(sys.implementation)
  15. def _cell_factory():
  16. a = 1
  17. def f():
  18. nonlocal a
  19. return f.__closure__[0]
  20. CellType = type(_cell_factory())
  21. def _g():
  22. yield 1
  23. GeneratorType = type(_g())
  24. async def _c(): pass
  25. _c = _c()
  26. CoroutineType = type(_c)
  27. _c.close() # Prevent ResourceWarning
  28. async def _ag():
  29. yield
  30. _ag = _ag()
  31. AsyncGeneratorType = type(_ag)
  32. class _C:
  33. def _m(self): pass
  34. MethodType = type(_C()._m)
  35. BuiltinFunctionType = type(len)
  36. BuiltinMethodType = type([].append) # Same as BuiltinFunctionType
  37. WrapperDescriptorType = type(object.__init__)
  38. MethodWrapperType = type(object().__str__)
  39. MethodDescriptorType = type(str.join)
  40. ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
  41. ModuleType = type(sys)
  42. try:
  43. raise TypeError
  44. except TypeError:
  45. tb = sys.exc_info()[2]
  46. TracebackType = type(tb)
  47. FrameType = type(tb.tb_frame)
  48. tb = None; del tb
  49. # For Jython, the following two types are identical
  50. GetSetDescriptorType = type(FunctionType.__code__)
  51. MemberDescriptorType = type(FunctionType.__globals__)
  52. del sys, _f, _g, _C, _c, _ag # Not for export
  53. # Provide a PEP 3115 compliant mechanism for class creation
  54. def new_class(name, bases=(), kwds=None, exec_body=None):
  55. """Create a class object dynamically using the appropriate metaclass."""
  56. resolved_bases = resolve_bases(bases)
  57. meta, ns, kwds = prepare_class(name, resolved_bases, kwds)
  58. if exec_body is not None:
  59. exec_body(ns)
  60. if resolved_bases is not bases:
  61. ns['__orig_bases__'] = bases
  62. return meta(name, resolved_bases, ns, **kwds)
  63. def resolve_bases(bases):
  64. """Resolve MRO entries dynamically as specified by PEP 560."""
  65. new_bases = list(bases)
  66. updated = False
  67. shift = 0
  68. for i, base in enumerate(bases):
  69. if isinstance(base, type):
  70. continue
  71. if not hasattr(base, "__mro_entries__"):
  72. continue
  73. new_base = base.__mro_entries__(bases)
  74. updated = True
  75. if not isinstance(new_base, tuple):
  76. raise TypeError("__mro_entries__ must return a tuple")
  77. else:
  78. new_bases[i+shift:i+shift+1] = new_base
  79. shift += len(new_base) - 1
  80. if not updated:
  81. return bases
  82. return tuple(new_bases)
  83. def prepare_class(name, bases=(), kwds=None):
  84. """Call the __prepare__ method of the appropriate metaclass.
  85. Returns (metaclass, namespace, kwds) as a 3-tuple
  86. *metaclass* is the appropriate metaclass
  87. *namespace* is the prepared class namespace
  88. *kwds* is an updated copy of the passed in kwds argument with any
  89. 'metaclass' entry removed. If no kwds argument is passed in, this will
  90. be an empty dict.
  91. """
  92. if kwds is None:
  93. kwds = {}
  94. else:
  95. kwds = dict(kwds) # Don't alter the provided mapping
  96. if 'metaclass' in kwds:
  97. meta = kwds.pop('metaclass')
  98. else:
  99. if bases:
  100. meta = type(bases[0])
  101. else:
  102. meta = type
  103. if isinstance(meta, type):
  104. # when meta is a type, we first determine the most-derived metaclass
  105. # instead of invoking the initial candidate directly
  106. meta = _calculate_meta(meta, bases)
  107. if hasattr(meta, '__prepare__'):
  108. ns = meta.__prepare__(name, bases, **kwds)
  109. else:
  110. ns = {}
  111. return meta, ns, kwds
  112. def _calculate_meta(meta, bases):
  113. """Calculate the most derived metaclass."""
  114. winner = meta
  115. for base in bases:
  116. base_meta = type(base)
  117. if issubclass(winner, base_meta):
  118. continue
  119. if issubclass(base_meta, winner):
  120. winner = base_meta
  121. continue
  122. # else:
  123. raise TypeError("metaclass conflict: "
  124. "the metaclass of a derived class "
  125. "must be a (non-strict) subclass "
  126. "of the metaclasses of all its bases")
  127. return winner
  128. class DynamicClassAttribute:
  129. """Route attribute access on a class to __getattr__.
  130. This is a descriptor, used to define attributes that act differently when
  131. accessed through an instance and through a class. Instance access remains
  132. normal, but access to an attribute through a class will be routed to the
  133. class's __getattr__ method; this is done by raising AttributeError.
  134. This allows one to have properties active on an instance, and have virtual
  135. attributes on the class with the same name (see Enum for an example).
  136. """
  137. def __init__(self, fget=None, fset=None, fdel=None, doc=None):
  138. self.fget = fget
  139. self.fset = fset
  140. self.fdel = fdel
  141. # next two lines make DynamicClassAttribute act the same as property
  142. self.__doc__ = doc or fget.__doc__
  143. self.overwrite_doc = doc is None
  144. # support for abstract methods
  145. self.__isabstractmethod__ = bool(getattr(fget, '__isabstractmethod__', False))
  146. def __get__(self, instance, ownerclass=None):
  147. if instance is None:
  148. if self.__isabstractmethod__:
  149. return self
  150. raise AttributeError()
  151. elif self.fget is None:
  152. raise AttributeError("unreadable attribute")
  153. return self.fget(instance)
  154. def __set__(self, instance, value):
  155. if self.fset is None:
  156. raise AttributeError("can't set attribute")
  157. self.fset(instance, value)
  158. def __delete__(self, instance):
  159. if self.fdel is None:
  160. raise AttributeError("can't delete attribute")
  161. self.fdel(instance)
  162. def getter(self, fget):
  163. fdoc = fget.__doc__ if self.overwrite_doc else None
  164. result = type(self)(fget, self.fset, self.fdel, fdoc or self.__doc__)
  165. result.overwrite_doc = self.overwrite_doc
  166. return result
  167. def setter(self, fset):
  168. result = type(self)(self.fget, fset, self.fdel, self.__doc__)
  169. result.overwrite_doc = self.overwrite_doc
  170. return result
  171. def deleter(self, fdel):
  172. result = type(self)(self.fget, self.fset, fdel, self.__doc__)
  173. result.overwrite_doc = self.overwrite_doc
  174. return result
  175. class _GeneratorWrapper:
  176. # TODO: Implement this in C.
  177. def __init__(self, gen):
  178. self.__wrapped = gen
  179. self.__isgen = gen.__class__ is GeneratorType
  180. self.__name__ = getattr(gen, '__name__', None)
  181. self.__qualname__ = getattr(gen, '__qualname__', None)
  182. def send(self, val):
  183. return self.__wrapped.send(val)
  184. def throw(self, tp, *rest):
  185. return self.__wrapped.throw(tp, *rest)
  186. def close(self):
  187. return self.__wrapped.close()
  188. @property
  189. def gi_code(self):
  190. return self.__wrapped.gi_code
  191. @property
  192. def gi_frame(self):
  193. return self.__wrapped.gi_frame
  194. @property
  195. def gi_running(self):
  196. return self.__wrapped.gi_running
  197. @property
  198. def gi_yieldfrom(self):
  199. return self.__wrapped.gi_yieldfrom
  200. cr_code = gi_code
  201. cr_frame = gi_frame
  202. cr_running = gi_running
  203. cr_await = gi_yieldfrom
  204. def __next__(self):
  205. return next(self.__wrapped)
  206. def __iter__(self):
  207. if self.__isgen:
  208. return self.__wrapped
  209. return self
  210. __await__ = __iter__
  211. def coroutine(func):
  212. """Convert regular generator function to a coroutine."""
  213. if not callable(func):
  214. raise TypeError('types.coroutine() expects a callable')
  215. if (func.__class__ is FunctionType and
  216. getattr(func, '__code__', None).__class__ is CodeType):
  217. co_flags = func.__code__.co_flags
  218. # Check if 'func' is a coroutine function.
  219. # (0x180 == CO_COROUTINE | CO_ITERABLE_COROUTINE)
  220. if co_flags & 0x180:
  221. return func
  222. # Check if 'func' is a generator function.
  223. # (0x20 == CO_GENERATOR)
  224. if co_flags & 0x20:
  225. # TODO: Implement this in C.
  226. co = func.__code__
  227. # 0x100 == CO_ITERABLE_COROUTINE
  228. func.__code__ = co.replace(co_flags=co.co_flags | 0x100)
  229. return func
  230. # The following code is primarily to support functions that
  231. # return generator-like objects (for instance generators
  232. # compiled with Cython).
  233. # Delay functools and _collections_abc import for speeding up types import.
  234. import functools
  235. import _collections_abc
  236. @functools.wraps(func)
  237. def wrapped(*args, **kwargs):
  238. coro = func(*args, **kwargs)
  239. if (coro.__class__ is CoroutineType or
  240. coro.__class__ is GeneratorType and coro.gi_code.co_flags & 0x100):
  241. # 'coro' is a native coroutine object or an iterable coroutine
  242. return coro
  243. if (isinstance(coro, _collections_abc.Generator) and
  244. not isinstance(coro, _collections_abc.Coroutine)):
  245. # 'coro' is either a pure Python generator iterator, or it
  246. # implements collections.abc.Generator (and does not implement
  247. # collections.abc.Coroutine).
  248. return _GeneratorWrapper(coro)
  249. # 'coro' is either an instance of collections.abc.Coroutine or
  250. # some other object -- pass it through.
  251. return coro
  252. return wrapped
  253. __all__ = [n for n in globals() if n[:1] != '_']