blob: 336918fea09d4a1babfbcaecfcda65fc9a6d00fa [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)
42
Guido van Rossum85d89451994-06-23 11:53:27 +000043ModuleType = type(sys)
Guido van Rossum85d89451994-06-23 11:53:27 +000044
45try:
Guido van Rossum898c9151997-09-04 22:12:34 +000046 raise TypeError
Guido van Rossum85d89451994-06-23 11:53:27 +000047except TypeError:
Guido van Rossuma8add0e2007-05-14 22:03:55 +000048 tb = sys.exc_info()[2]
49 TracebackType = type(tb)
50 FrameType = type(tb.tb_frame)
Guido van Rossumf15d1591997-09-29 23:22:12 +000051 tb = None; del tb
Guido van Rossum85d89451994-06-23 11:53:27 +000052
Christian Heimes5e696852008-04-09 08:37:03 +000053# For Jython, the following two types are identical
54GetSetDescriptorType = type(FunctionType.__code__)
55MemberDescriptorType = type(FunctionType.__globals__)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000056
Yury Selivanov5376ba92015-06-22 12:19:30 -040057del sys, _f, _g, _C, _c, # Not for export
Nick Coghlan7fc570a2012-05-20 02:34:13 +100058
59
60# Provide a PEP 3115 compliant mechanism for class creation
61def new_class(name, bases=(), kwds=None, exec_body=None):
62 """Create a class object dynamically using the appropriate metaclass."""
63 meta, ns, kwds = prepare_class(name, bases, kwds)
64 if exec_body is not None:
65 exec_body(ns)
66 return meta(name, bases, ns, **kwds)
67
68def prepare_class(name, bases=(), kwds=None):
69 """Call the __prepare__ method of the appropriate metaclass.
70
71 Returns (metaclass, namespace, kwds) as a 3-tuple
72
73 *metaclass* is the appropriate metaclass
74 *namespace* is the prepared class namespace
75 *kwds* is an updated copy of the passed in kwds argument with any
76 'metaclass' entry removed. If no kwds argument is passed in, this will
77 be an empty dict.
78 """
79 if kwds is None:
80 kwds = {}
81 else:
82 kwds = dict(kwds) # Don't alter the provided mapping
83 if 'metaclass' in kwds:
84 meta = kwds.pop('metaclass')
85 else:
86 if bases:
87 meta = type(bases[0])
88 else:
89 meta = type
90 if isinstance(meta, type):
91 # when meta is a type, we first determine the most-derived metaclass
92 # instead of invoking the initial candidate directly
93 meta = _calculate_meta(meta, bases)
94 if hasattr(meta, '__prepare__'):
95 ns = meta.__prepare__(name, bases, **kwds)
96 else:
Eric Snow4f29e752016-09-08 15:11:11 -070097 ns = {}
Nick Coghlan7fc570a2012-05-20 02:34:13 +100098 return meta, ns, kwds
99
100def _calculate_meta(meta, bases):
101 """Calculate the most derived metaclass."""
102 winner = meta
103 for base in bases:
104 base_meta = type(base)
105 if issubclass(winner, base_meta):
106 continue
107 if issubclass(base_meta, winner):
108 winner = base_meta
109 continue
110 # else:
111 raise TypeError("metaclass conflict: "
112 "the metaclass of a derived class "
113 "must be a (non-strict) subclass "
114 "of the metaclasses of all its bases")
115 return winner
Ethan Furmane03ea372013-09-25 07:14:41 -0700116
117class DynamicClassAttribute:
118 """Route attribute access on a class to __getattr__.
119
120 This is a descriptor, used to define attributes that act differently when
121 accessed through an instance and through a class. Instance access remains
122 normal, but access to an attribute through a class will be routed to the
123 class's __getattr__ method; this is done by raising AttributeError.
124
125 This allows one to have properties active on an instance, and have virtual
126 attributes on the class with the same name (see Enum for an example).
127
128 """
129 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
130 self.fget = fget
131 self.fset = fset
132 self.fdel = fdel
133 # next two lines make DynamicClassAttribute act the same as property
Ethan Furman63c141c2013-10-18 00:27:39 -0700134 self.__doc__ = doc or fget.__doc__
Ethan Furmane03ea372013-09-25 07:14:41 -0700135 self.overwrite_doc = doc is None
136 # support for abstract methods
137 self.__isabstractmethod__ = bool(getattr(fget, '__isabstractmethod__', False))
138
139 def __get__(self, instance, ownerclass=None):
140 if instance is None:
141 if self.__isabstractmethod__:
142 return self
143 raise AttributeError()
144 elif self.fget is None:
145 raise AttributeError("unreadable attribute")
146 return self.fget(instance)
147
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
153 def __delete__(self, instance):
154 if self.fdel is None:
155 raise AttributeError("can't delete attribute")
156 self.fdel(instance)
157
158 def getter(self, fget):
159 fdoc = fget.__doc__ if self.overwrite_doc else None
160 result = type(self)(fget, self.fset, self.fdel, fdoc or self.__doc__)
161 result.overwrite_doc = self.overwrite_doc
162 return result
163
164 def setter(self, fset):
165 result = type(self)(self.fget, fset, self.fdel, self.__doc__)
166 result.overwrite_doc = self.overwrite_doc
167 return result
168
169 def deleter(self, fdel):
170 result = type(self)(self.fget, self.fset, fdel, self.__doc__)
171 result.overwrite_doc = self.overwrite_doc
172 return result
Serhiy Storchaka7beb4f92015-03-04 09:43:27 +0200173
174
Yury Selivanov00e33722015-06-24 11:44:51 -0400175class _GeneratorWrapper:
176 # TODO: Implement this in C.
177 def __init__(self, gen):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400178 self.__wrapped = gen
179 self.__isgen = gen.__class__ is GeneratorType
Yury Selivanov00e33722015-06-24 11:44:51 -0400180 self.__name__ = getattr(gen, '__name__', None)
181 self.__qualname__ = getattr(gen, '__qualname__', None)
182 def send(self, val):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400183 return self.__wrapped.send(val)
Yury Selivanov00e33722015-06-24 11:44:51 -0400184 def throw(self, tp, *rest):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400185 return self.__wrapped.throw(tp, *rest)
Yury Selivanov00e33722015-06-24 11:44:51 -0400186 def close(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400187 return self.__wrapped.close()
Yury Selivanov00e33722015-06-24 11:44:51 -0400188 @property
189 def gi_code(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400190 return self.__wrapped.gi_code
Yury Selivanov00e33722015-06-24 11:44:51 -0400191 @property
192 def gi_frame(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400193 return self.__wrapped.gi_frame
Yury Selivanov00e33722015-06-24 11:44:51 -0400194 @property
195 def gi_running(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400196 return self.__wrapped.gi_running
Yury Selivanov53e62302015-07-03 00:35:02 -0400197 @property
198 def gi_yieldfrom(self):
199 return self.__wrapped.gi_yieldfrom
Yury Selivanov00e33722015-06-24 11:44:51 -0400200 cr_code = gi_code
201 cr_frame = gi_frame
202 cr_running = gi_running
Yury Selivanov53e62302015-07-03 00:35:02 -0400203 cr_await = gi_yieldfrom
Yury Selivanov00e33722015-06-24 11:44:51 -0400204 def __next__(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400205 return next(self.__wrapped)
Yury Selivanov00e33722015-06-24 11:44:51 -0400206 def __iter__(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400207 if self.__isgen:
208 return self.__wrapped
Yury Selivanov00e33722015-06-24 11:44:51 -0400209 return self
210 __await__ = __iter__
211
Yury Selivanovc565cd52015-05-29 09:06:05 -0400212def coroutine(func):
213 """Convert regular generator function to a coroutine."""
214
Yury Selivanovc565cd52015-05-29 09:06:05 -0400215 if not callable(func):
216 raise TypeError('types.coroutine() expects a callable')
217
Yury Selivanov5376ba92015-06-22 12:19:30 -0400218 if (func.__class__ is FunctionType and
219 getattr(func, '__code__', None).__class__ is CodeType):
Yury Selivanovc565cd52015-05-29 09:06:05 -0400220
Yury Selivanov5376ba92015-06-22 12:19:30 -0400221 co_flags = func.__code__.co_flags
222
223 # Check if 'func' is a coroutine function.
224 # (0x180 == CO_COROUTINE | CO_ITERABLE_COROUTINE)
225 if co_flags & 0x180:
226 return func
227
228 # Check if 'func' is a generator function.
229 # (0x20 == CO_GENERATOR)
230 if co_flags & 0x20:
231 # TODO: Implement this in C.
232 co = func.__code__
233 func.__code__ = CodeType(
234 co.co_argcount, co.co_kwonlyargcount, co.co_nlocals,
235 co.co_stacksize,
236 co.co_flags | 0x100, # 0x100 == CO_ITERABLE_COROUTINE
237 co.co_code,
238 co.co_consts, co.co_names, co.co_varnames, co.co_filename,
239 co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars,
240 co.co_cellvars)
241 return func
Yury Selivanovc565cd52015-05-29 09:06:05 -0400242
Yury Selivanov13f77232015-05-29 16:19:18 -0400243 # The following code is primarily to support functions that
244 # return generator-like objects (for instance generators
245 # compiled with Cython).
246
Serhiy Storchaka81108372017-09-26 00:55:55 +0300247 # Delay functools and _collections_abc import for speeding up types import.
248 import functools
249 import _collections_abc
250 @functools.wraps(func)
Yury Selivanovc565cd52015-05-29 09:06:05 -0400251 def wrapped(*args, **kwargs):
252 coro = func(*args, **kwargs)
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400253 if (coro.__class__ is CoroutineType or
254 coro.__class__ is GeneratorType and coro.gi_code.co_flags & 0x100):
255 # 'coro' is a native coroutine object or an iterable coroutine
Yury Selivanov5376ba92015-06-22 12:19:30 -0400256 return coro
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400257 if (isinstance(coro, _collections_abc.Generator) and
258 not isinstance(coro, _collections_abc.Coroutine)):
Yury Selivanov5376ba92015-06-22 12:19:30 -0400259 # 'coro' is either a pure Python generator iterator, or it
260 # implements collections.abc.Generator (and does not implement
261 # collections.abc.Coroutine).
Yury Selivanov00e33722015-06-24 11:44:51 -0400262 return _GeneratorWrapper(coro)
Yury Selivanov5376ba92015-06-22 12:19:30 -0400263 # 'coro' is either an instance of collections.abc.Coroutine or
264 # some other object -- pass it through.
Yury Selivanovc565cd52015-05-29 09:06:05 -0400265 return coro
266
267 return wrapped
268
269
Serhiy Storchaka7beb4f92015-03-04 09:43:27 +0200270__all__ = [n for n in globals() if n[:1] != '_']