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