blob: ce4652f37189763dbce5b3946d53b45d4e076493 [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
Tim Peters264c6592004-07-18 00:08:11 +000018def _g():
Tim Peters3e7b1a02001-06-25 19:46:25 +000019 yield 1
Tim Peters264c6592004-07-18 00:08:11 +000020GeneratorType = type(_g())
Tim Peters3e7b1a02001-06-25 19:46:25 +000021
Yury Selivanov5376ba92015-06-22 12:19:30 -040022async def _c(): pass
23_c = _c()
24CoroutineType = type(_c)
25_c.close() # Prevent ResourceWarning
26
Yury Selivanoveb636452016-09-08 22:01:51 -070027async def _ag():
28 yield
29_ag = _ag()
30AsyncGeneratorType = type(_ag)
31
Guido van Rossumadc940e1994-09-29 10:04:43 +000032class _C:
Guido van Rossum898c9151997-09-04 22:12:34 +000033 def _m(self): pass
Guido van Rossum65810fe2006-05-26 19:12:38 +000034MethodType = type(_C()._m)
Guido van Rossum85d89451994-06-23 11:53:27 +000035
Guido van Rossumadc940e1994-09-29 10:04:43 +000036BuiltinFunctionType = type(len)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000037BuiltinMethodType = type([].append) # Same as BuiltinFunctionType
Guido van Rossum85d89451994-06-23 11:53:27 +000038
Jim Fasarakis-Hilliard08c16012017-04-25 21:26:36 +030039WrapperDescriptorType = type(object.__init__)
Guido van Rossum934aba62017-02-01 10:55:58 -080040MethodWrapperType = type(object().__str__)
41MethodDescriptorType = type(str.join)
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +020042ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
Guido van Rossum934aba62017-02-01 10:55:58 -080043
Guido van Rossum85d89451994-06-23 11:53:27 +000044ModuleType = type(sys)
Guido van Rossum85d89451994-06-23 11:53:27 +000045
46try:
Guido van Rossum898c9151997-09-04 22:12:34 +000047 raise TypeError
Guido van Rossum85d89451994-06-23 11:53:27 +000048except TypeError:
Guido van Rossuma8add0e2007-05-14 22:03:55 +000049 tb = sys.exc_info()[2]
50 TracebackType = type(tb)
51 FrameType = type(tb.tb_frame)
Guido van Rossumf15d1591997-09-29 23:22:12 +000052 tb = None; del tb
Guido van Rossum85d89451994-06-23 11:53:27 +000053
Christian Heimes5e696852008-04-09 08:37:03 +000054# For Jython, the following two types are identical
55GetSetDescriptorType = type(FunctionType.__code__)
56MemberDescriptorType = type(FunctionType.__globals__)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000057
Yury Selivanov5376ba92015-06-22 12:19:30 -040058del sys, _f, _g, _C, _c, # Not for export
Nick Coghlan7fc570a2012-05-20 02:34:13 +100059
60
61# Provide a PEP 3115 compliant mechanism for class creation
62def new_class(name, bases=(), kwds=None, exec_body=None):
63 """Create a class object dynamically using the appropriate metaclass."""
Ivan Levkivskyi2b5fd1e2017-12-14 23:32:56 +010064 resolved_bases = resolve_bases(bases)
65 meta, ns, kwds = prepare_class(name, resolved_bases, kwds)
Nick Coghlan7fc570a2012-05-20 02:34:13 +100066 if exec_body is not None:
67 exec_body(ns)
Ivan Levkivskyi2b5fd1e2017-12-14 23:32:56 +010068 if resolved_bases is not bases:
69 ns['__orig_bases__'] = bases
70 return meta(name, resolved_bases, ns, **kwds)
71
72def resolve_bases(bases):
73 """Resolve MRO entries dynamically as specified by PEP 560."""
74 new_bases = list(bases)
75 updated = False
76 shift = 0
77 for i, base in enumerate(bases):
78 if isinstance(base, type):
79 continue
80 if not hasattr(base, "__mro_entries__"):
81 continue
82 new_base = base.__mro_entries__(bases)
83 updated = True
84 if not isinstance(new_base, tuple):
85 raise TypeError("__mro_entries__ must return a tuple")
86 else:
87 new_bases[i+shift:i+shift+1] = new_base
88 shift += len(new_base) - 1
89 if not updated:
90 return bases
91 return tuple(new_bases)
Nick Coghlan7fc570a2012-05-20 02:34:13 +100092
93def prepare_class(name, bases=(), kwds=None):
94 """Call the __prepare__ method of the appropriate metaclass.
95
96 Returns (metaclass, namespace, kwds) as a 3-tuple
97
98 *metaclass* is the appropriate metaclass
99 *namespace* is the prepared class namespace
100 *kwds* is an updated copy of the passed in kwds argument with any
101 'metaclass' entry removed. If no kwds argument is passed in, this will
102 be an empty dict.
103 """
104 if kwds is None:
105 kwds = {}
106 else:
107 kwds = dict(kwds) # Don't alter the provided mapping
108 if 'metaclass' in kwds:
109 meta = kwds.pop('metaclass')
110 else:
111 if bases:
112 meta = type(bases[0])
113 else:
114 meta = type
115 if isinstance(meta, type):
116 # when meta is a type, we first determine the most-derived metaclass
117 # instead of invoking the initial candidate directly
118 meta = _calculate_meta(meta, bases)
119 if hasattr(meta, '__prepare__'):
120 ns = meta.__prepare__(name, bases, **kwds)
121 else:
Eric Snow4f29e752016-09-08 15:11:11 -0700122 ns = {}
Nick Coghlan7fc570a2012-05-20 02:34:13 +1000123 return meta, ns, kwds
124
125def _calculate_meta(meta, bases):
126 """Calculate the most derived metaclass."""
127 winner = meta
128 for base in bases:
129 base_meta = type(base)
130 if issubclass(winner, base_meta):
131 continue
132 if issubclass(base_meta, winner):
133 winner = base_meta
134 continue
135 # else:
136 raise TypeError("metaclass conflict: "
137 "the metaclass of a derived class "
138 "must be a (non-strict) subclass "
139 "of the metaclasses of all its bases")
140 return winner
Ethan Furmane03ea372013-09-25 07:14:41 -0700141
142class DynamicClassAttribute:
143 """Route attribute access on a class to __getattr__.
144
145 This is a descriptor, used to define attributes that act differently when
146 accessed through an instance and through a class. Instance access remains
147 normal, but access to an attribute through a class will be routed to the
148 class's __getattr__ method; this is done by raising AttributeError.
149
150 This allows one to have properties active on an instance, and have virtual
151 attributes on the class with the same name (see Enum for an example).
152
153 """
154 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
155 self.fget = fget
156 self.fset = fset
157 self.fdel = fdel
158 # next two lines make DynamicClassAttribute act the same as property
Ethan Furman63c141c2013-10-18 00:27:39 -0700159 self.__doc__ = doc or fget.__doc__
Ethan Furmane03ea372013-09-25 07:14:41 -0700160 self.overwrite_doc = doc is None
161 # support for abstract methods
162 self.__isabstractmethod__ = bool(getattr(fget, '__isabstractmethod__', False))
163
164 def __get__(self, instance, ownerclass=None):
165 if instance is None:
166 if self.__isabstractmethod__:
167 return self
168 raise AttributeError()
169 elif self.fget is None:
170 raise AttributeError("unreadable attribute")
171 return self.fget(instance)
172
173 def __set__(self, instance, value):
174 if self.fset is None:
175 raise AttributeError("can't set attribute")
176 self.fset(instance, value)
177
178 def __delete__(self, instance):
179 if self.fdel is None:
180 raise AttributeError("can't delete attribute")
181 self.fdel(instance)
182
183 def getter(self, fget):
184 fdoc = fget.__doc__ if self.overwrite_doc else None
185 result = type(self)(fget, self.fset, self.fdel, fdoc or self.__doc__)
186 result.overwrite_doc = self.overwrite_doc
187 return result
188
189 def setter(self, fset):
190 result = type(self)(self.fget, fset, self.fdel, self.__doc__)
191 result.overwrite_doc = self.overwrite_doc
192 return result
193
194 def deleter(self, fdel):
195 result = type(self)(self.fget, self.fset, fdel, self.__doc__)
196 result.overwrite_doc = self.overwrite_doc
197 return result
Serhiy Storchaka7beb4f92015-03-04 09:43:27 +0200198
199
Yury Selivanov00e33722015-06-24 11:44:51 -0400200class _GeneratorWrapper:
201 # TODO: Implement this in C.
202 def __init__(self, gen):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400203 self.__wrapped = gen
204 self.__isgen = gen.__class__ is GeneratorType
Yury Selivanov00e33722015-06-24 11:44:51 -0400205 self.__name__ = getattr(gen, '__name__', None)
206 self.__qualname__ = getattr(gen, '__qualname__', None)
207 def send(self, val):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400208 return self.__wrapped.send(val)
Yury Selivanov00e33722015-06-24 11:44:51 -0400209 def throw(self, tp, *rest):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400210 return self.__wrapped.throw(tp, *rest)
Yury Selivanov00e33722015-06-24 11:44:51 -0400211 def close(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400212 return self.__wrapped.close()
Yury Selivanov00e33722015-06-24 11:44:51 -0400213 @property
214 def gi_code(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400215 return self.__wrapped.gi_code
Yury Selivanov00e33722015-06-24 11:44:51 -0400216 @property
217 def gi_frame(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400218 return self.__wrapped.gi_frame
Yury Selivanov00e33722015-06-24 11:44:51 -0400219 @property
220 def gi_running(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400221 return self.__wrapped.gi_running
Yury Selivanov53e62302015-07-03 00:35:02 -0400222 @property
223 def gi_yieldfrom(self):
224 return self.__wrapped.gi_yieldfrom
Yury Selivanov00e33722015-06-24 11:44:51 -0400225 cr_code = gi_code
226 cr_frame = gi_frame
227 cr_running = gi_running
Yury Selivanov53e62302015-07-03 00:35:02 -0400228 cr_await = gi_yieldfrom
Yury Selivanov00e33722015-06-24 11:44:51 -0400229 def __next__(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400230 return next(self.__wrapped)
Yury Selivanov00e33722015-06-24 11:44:51 -0400231 def __iter__(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400232 if self.__isgen:
233 return self.__wrapped
Yury Selivanov00e33722015-06-24 11:44:51 -0400234 return self
235 __await__ = __iter__
236
Yury Selivanovc565cd52015-05-29 09:06:05 -0400237def coroutine(func):
238 """Convert regular generator function to a coroutine."""
239
Yury Selivanovc565cd52015-05-29 09:06:05 -0400240 if not callable(func):
241 raise TypeError('types.coroutine() expects a callable')
242
Yury Selivanov5376ba92015-06-22 12:19:30 -0400243 if (func.__class__ is FunctionType and
244 getattr(func, '__code__', None).__class__ is CodeType):
Yury Selivanovc565cd52015-05-29 09:06:05 -0400245
Yury Selivanov5376ba92015-06-22 12:19:30 -0400246 co_flags = func.__code__.co_flags
247
248 # Check if 'func' is a coroutine function.
249 # (0x180 == CO_COROUTINE | CO_ITERABLE_COROUTINE)
250 if co_flags & 0x180:
251 return func
252
253 # Check if 'func' is a generator function.
254 # (0x20 == CO_GENERATOR)
255 if co_flags & 0x20:
256 # TODO: Implement this in C.
257 co = func.__code__
258 func.__code__ = CodeType(
259 co.co_argcount, co.co_kwonlyargcount, co.co_nlocals,
260 co.co_stacksize,
261 co.co_flags | 0x100, # 0x100 == CO_ITERABLE_COROUTINE
262 co.co_code,
263 co.co_consts, co.co_names, co.co_varnames, co.co_filename,
264 co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars,
265 co.co_cellvars)
266 return func
Yury Selivanovc565cd52015-05-29 09:06:05 -0400267
Yury Selivanov13f77232015-05-29 16:19:18 -0400268 # The following code is primarily to support functions that
269 # return generator-like objects (for instance generators
270 # compiled with Cython).
271
Serhiy Storchaka81108372017-09-26 00:55:55 +0300272 # Delay functools and _collections_abc import for speeding up types import.
273 import functools
274 import _collections_abc
275 @functools.wraps(func)
Yury Selivanovc565cd52015-05-29 09:06:05 -0400276 def wrapped(*args, **kwargs):
277 coro = func(*args, **kwargs)
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400278 if (coro.__class__ is CoroutineType or
279 coro.__class__ is GeneratorType and coro.gi_code.co_flags & 0x100):
280 # 'coro' is a native coroutine object or an iterable coroutine
Yury Selivanov5376ba92015-06-22 12:19:30 -0400281 return coro
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400282 if (isinstance(coro, _collections_abc.Generator) and
283 not isinstance(coro, _collections_abc.Coroutine)):
Yury Selivanov5376ba92015-06-22 12:19:30 -0400284 # 'coro' is either a pure Python generator iterator, or it
285 # implements collections.abc.Generator (and does not implement
286 # collections.abc.Coroutine).
Yury Selivanov00e33722015-06-24 11:44:51 -0400287 return _GeneratorWrapper(coro)
Yury Selivanov5376ba92015-06-22 12:19:30 -0400288 # 'coro' is either an instance of collections.abc.Coroutine or
289 # some other object -- pass it through.
Yury Selivanovc565cd52015-05-29 09:06:05 -0400290 return coro
291
292 return wrapped
293
294
Serhiy Storchaka7beb4f92015-03-04 09:43:27 +0200295__all__ = [n for n in globals() if n[:1] != '_']