blob: ea3c0b29d5d4ddd9daf27fdb37ec7bb6ee8033c4 [file] [log] [blame]
Georg Brandle5a32dc2007-12-21 08:16:54 +00001"""
2Define names for built-in types that aren't directly accessible as a builtin.
Guido van Rossume7b146f2000-02-04 15:28:42 +00003"""
Guido van Rossum85d89451994-06-23 11:53:27 +00004import sys
5
Tim Peters26991a72001-09-25 22:02:03 +00006# 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
Georg Brandla18af4e2007-04-21 15:47:16 +00009# "__iter__" and "__next__" attributes instead.
Tim Peters26991a72001-09-25 22:02:03 +000010
Guido van Rossumadc940e1994-09-29 10:04:43 +000011def _f(): pass
12FunctionType = type(_f)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000013LambdaType = type(lambda: None) # Same as FunctionType
Guido van Rossuma8add0e2007-05-14 22:03:55 +000014CodeType = type(_f.__code__)
Victor Stinner0db176f2012-04-16 00:16:30 +020015MappingProxyType = type(type.__dict__)
Barry Warsaw409da152012-06-03 16:18:47 -040016SimpleNamespace = type(sys.implementation)
Guido van Rossum85d89451994-06-23 11:53:27 +000017
Pierre Glaserdf8d2cd2019-02-07 20:36:48 +010018def _cell_factory():
19 a = 1
20 def f():
21 nonlocal a
22 return f.__closure__[0]
23CellType = type(_cell_factory())
24
Tim Peters264c6592004-07-18 00:08:11 +000025def _g():
Tim Peters3e7b1a02001-06-25 19:46:25 +000026 yield 1
Tim Peters264c6592004-07-18 00:08:11 +000027GeneratorType = type(_g())
Tim Peters3e7b1a02001-06-25 19:46:25 +000028
Yury Selivanov5376ba92015-06-22 12:19:30 -040029async def _c(): pass
30_c = _c()
31CoroutineType = type(_c)
32_c.close() # Prevent ResourceWarning
33
Yury Selivanoveb636452016-09-08 22:01:51 -070034async def _ag():
35 yield
36_ag = _ag()
37AsyncGeneratorType = type(_ag)
38
Guido van Rossumadc940e1994-09-29 10:04:43 +000039class _C:
Guido van Rossum898c9151997-09-04 22:12:34 +000040 def _m(self): pass
Guido van Rossum65810fe2006-05-26 19:12:38 +000041MethodType = type(_C()._m)
Guido van Rossum85d89451994-06-23 11:53:27 +000042
Guido van Rossumadc940e1994-09-29 10:04:43 +000043BuiltinFunctionType = type(len)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000044BuiltinMethodType = type([].append) # Same as BuiltinFunctionType
Guido van Rossum85d89451994-06-23 11:53:27 +000045
Jim Fasarakis-Hilliard08c16012017-04-25 21:26:36 +030046WrapperDescriptorType = type(object.__init__)
Guido van Rossum934aba62017-02-01 10:55:58 -080047MethodWrapperType = type(object().__str__)
48MethodDescriptorType = type(str.join)
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +020049ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
Guido van Rossum934aba62017-02-01 10:55:58 -080050
Guido van Rossum85d89451994-06-23 11:53:27 +000051ModuleType = type(sys)
Guido van Rossum85d89451994-06-23 11:53:27 +000052
53try:
Guido van Rossum898c9151997-09-04 22:12:34 +000054 raise TypeError
Guido van Rossum85d89451994-06-23 11:53:27 +000055except TypeError:
Guido van Rossuma8add0e2007-05-14 22:03:55 +000056 tb = sys.exc_info()[2]
57 TracebackType = type(tb)
58 FrameType = type(tb.tb_frame)
Guido van Rossumf15d1591997-09-29 23:22:12 +000059 tb = None; del tb
Guido van Rossum85d89451994-06-23 11:53:27 +000060
Christian Heimes5e696852008-04-09 08:37:03 +000061# For Jython, the following two types are identical
62GetSetDescriptorType = type(FunctionType.__code__)
63MemberDescriptorType = type(FunctionType.__globals__)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000064
Henry Chen0a6a4122019-03-03 06:35:24 -080065del sys, _f, _g, _C, _c, _ag # Not for export
Nick Coghlan7fc570a2012-05-20 02:34:13 +100066
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."""
Ivan Levkivskyi2b5fd1e2017-12-14 23:32:56 +010071 resolved_bases = resolve_bases(bases)
72 meta, ns, kwds = prepare_class(name, resolved_bases, kwds)
Nick Coghlan7fc570a2012-05-20 02:34:13 +100073 if exec_body is not None:
74 exec_body(ns)
Ivan Levkivskyi2b5fd1e2017-12-14 23:32:56 +010075 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)
Nick Coghlan7fc570a2012-05-20 02:34:13 +100099
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:
Eric Snow4f29e752016-09-08 15:11:11 -0700129 ns = {}
Nick Coghlan7fc570a2012-05-20 02:34:13 +1000130 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
Ethan Furmane03ea372013-09-25 07:14:41 -0700148
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
Ethan Furman63c141c2013-10-18 00:27:39 -0700166 self.__doc__ = doc or fget.__doc__
Ethan Furmane03ea372013-09-25 07:14:41 -0700167 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
Serhiy Storchaka7beb4f92015-03-04 09:43:27 +0200205
206
Yury Selivanov00e33722015-06-24 11:44:51 -0400207class _GeneratorWrapper:
208 # TODO: Implement this in C.
209 def __init__(self, gen):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400210 self.__wrapped = gen
211 self.__isgen = gen.__class__ is GeneratorType
Yury Selivanov00e33722015-06-24 11:44:51 -0400212 self.__name__ = getattr(gen, '__name__', None)
213 self.__qualname__ = getattr(gen, '__qualname__', None)
214 def send(self, val):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400215 return self.__wrapped.send(val)
Yury Selivanov00e33722015-06-24 11:44:51 -0400216 def throw(self, tp, *rest):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400217 return self.__wrapped.throw(tp, *rest)
Yury Selivanov00e33722015-06-24 11:44:51 -0400218 def close(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400219 return self.__wrapped.close()
Yury Selivanov00e33722015-06-24 11:44:51 -0400220 @property
221 def gi_code(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400222 return self.__wrapped.gi_code
Yury Selivanov00e33722015-06-24 11:44:51 -0400223 @property
224 def gi_frame(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400225 return self.__wrapped.gi_frame
Yury Selivanov00e33722015-06-24 11:44:51 -0400226 @property
227 def gi_running(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400228 return self.__wrapped.gi_running
Yury Selivanov53e62302015-07-03 00:35:02 -0400229 @property
230 def gi_yieldfrom(self):
231 return self.__wrapped.gi_yieldfrom
Yury Selivanov00e33722015-06-24 11:44:51 -0400232 cr_code = gi_code
233 cr_frame = gi_frame
234 cr_running = gi_running
Yury Selivanov53e62302015-07-03 00:35:02 -0400235 cr_await = gi_yieldfrom
Yury Selivanov00e33722015-06-24 11:44:51 -0400236 def __next__(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400237 return next(self.__wrapped)
Yury Selivanov00e33722015-06-24 11:44:51 -0400238 def __iter__(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400239 if self.__isgen:
240 return self.__wrapped
Yury Selivanov00e33722015-06-24 11:44:51 -0400241 return self
242 __await__ = __iter__
243
Yury Selivanovc565cd52015-05-29 09:06:05 -0400244def coroutine(func):
245 """Convert regular generator function to a coroutine."""
246
Yury Selivanovc565cd52015-05-29 09:06:05 -0400247 if not callable(func):
248 raise TypeError('types.coroutine() expects a callable')
249
Yury Selivanov5376ba92015-06-22 12:19:30 -0400250 if (func.__class__ is FunctionType and
251 getattr(func, '__code__', None).__class__ is CodeType):
Yury Selivanovc565cd52015-05-29 09:06:05 -0400252
Yury Selivanov5376ba92015-06-22 12:19:30 -0400253 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__
Victor Stinnera9f05d62019-05-24 23:57:23 +0200265 # 0x100 == CO_ITERABLE_COROUTINE
266 func.__code__ = co.replace(co_flags=co.co_flags | 0x100)
Yury Selivanov5376ba92015-06-22 12:19:30 -0400267 return func
Yury Selivanovc565cd52015-05-29 09:06:05 -0400268
Yury Selivanov13f77232015-05-29 16:19:18 -0400269 # The following code is primarily to support functions that
270 # return generator-like objects (for instance generators
271 # compiled with Cython).
272
Serhiy Storchaka81108372017-09-26 00:55:55 +0300273 # Delay functools and _collections_abc import for speeding up types import.
274 import functools
275 import _collections_abc
276 @functools.wraps(func)
Yury Selivanovc565cd52015-05-29 09:06:05 -0400277 def wrapped(*args, **kwargs):
278 coro = func(*args, **kwargs)
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400279 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
Yury Selivanov5376ba92015-06-22 12:19:30 -0400282 return coro
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400283 if (isinstance(coro, _collections_abc.Generator) and
284 not isinstance(coro, _collections_abc.Coroutine)):
Yury Selivanov5376ba92015-06-22 12:19:30 -0400285 # 'coro' is either a pure Python generator iterator, or it
286 # implements collections.abc.Generator (and does not implement
287 # collections.abc.Coroutine).
Yury Selivanov00e33722015-06-24 11:44:51 -0400288 return _GeneratorWrapper(coro)
Yury Selivanov5376ba92015-06-22 12:19:30 -0400289 # 'coro' is either an instance of collections.abc.Coroutine or
290 # some other object -- pass it through.
Yury Selivanovc565cd52015-05-29 09:06:05 -0400291 return coro
292
293 return wrapped
294
295
Serhiy Storchaka7beb4f92015-03-04 09:43:27 +0200296__all__ = [n for n in globals() if n[:1] != '_']