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