PageRenderTime 55ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/Lib/types.py

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