blob: dc1b040f89e48774e2833cfae95e21a05951d35d [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
Guido van Rossumadc940e1994-09-29 10:04:43 +000027class _C:
Guido van Rossum898c9151997-09-04 22:12:34 +000028 def _m(self): pass
Guido van Rossum65810fe2006-05-26 19:12:38 +000029MethodType = type(_C()._m)
Guido van Rossum85d89451994-06-23 11:53:27 +000030
Guido van Rossumadc940e1994-09-29 10:04:43 +000031BuiltinFunctionType = type(len)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000032BuiltinMethodType = type([].append) # Same as BuiltinFunctionType
Guido van Rossum85d89451994-06-23 11:53:27 +000033
34ModuleType = type(sys)
Guido van Rossum85d89451994-06-23 11:53:27 +000035
36try:
Guido van Rossum898c9151997-09-04 22:12:34 +000037 raise TypeError
Guido van Rossum85d89451994-06-23 11:53:27 +000038except TypeError:
Guido van Rossuma8add0e2007-05-14 22:03:55 +000039 tb = sys.exc_info()[2]
40 TracebackType = type(tb)
41 FrameType = type(tb.tb_frame)
Guido van Rossumf15d1591997-09-29 23:22:12 +000042 tb = None; del tb
Guido van Rossum85d89451994-06-23 11:53:27 +000043
Christian Heimes5e696852008-04-09 08:37:03 +000044# For Jython, the following two types are identical
45GetSetDescriptorType = type(FunctionType.__code__)
46MemberDescriptorType = type(FunctionType.__globals__)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000047
Yury Selivanov5376ba92015-06-22 12:19:30 -040048del sys, _f, _g, _C, _c, # Not for export
Nick Coghlan7fc570a2012-05-20 02:34:13 +100049
50
51# Provide a PEP 3115 compliant mechanism for class creation
52def new_class(name, bases=(), kwds=None, exec_body=None):
53 """Create a class object dynamically using the appropriate metaclass."""
54 meta, ns, kwds = prepare_class(name, bases, kwds)
55 if exec_body is not None:
56 exec_body(ns)
57 return meta(name, bases, ns, **kwds)
58
59def prepare_class(name, bases=(), kwds=None):
60 """Call the __prepare__ method of the appropriate metaclass.
61
62 Returns (metaclass, namespace, kwds) as a 3-tuple
63
64 *metaclass* is the appropriate metaclass
65 *namespace* is the prepared class namespace
66 *kwds* is an updated copy of the passed in kwds argument with any
67 'metaclass' entry removed. If no kwds argument is passed in, this will
68 be an empty dict.
69 """
70 if kwds is None:
71 kwds = {}
72 else:
73 kwds = dict(kwds) # Don't alter the provided mapping
74 if 'metaclass' in kwds:
75 meta = kwds.pop('metaclass')
76 else:
77 if bases:
78 meta = type(bases[0])
79 else:
80 meta = type
81 if isinstance(meta, type):
82 # when meta is a type, we first determine the most-derived metaclass
83 # instead of invoking the initial candidate directly
84 meta = _calculate_meta(meta, bases)
85 if hasattr(meta, '__prepare__'):
86 ns = meta.__prepare__(name, bases, **kwds)
87 else:
88 ns = {}
89 return meta, ns, kwds
90
91def _calculate_meta(meta, bases):
92 """Calculate the most derived metaclass."""
93 winner = meta
94 for base in bases:
95 base_meta = type(base)
96 if issubclass(winner, base_meta):
97 continue
98 if issubclass(base_meta, winner):
99 winner = base_meta
100 continue
101 # else:
102 raise TypeError("metaclass conflict: "
103 "the metaclass of a derived class "
104 "must be a (non-strict) subclass "
105 "of the metaclasses of all its bases")
106 return winner
Ethan Furmane03ea372013-09-25 07:14:41 -0700107
108class DynamicClassAttribute:
109 """Route attribute access on a class to __getattr__.
110
111 This is a descriptor, used to define attributes that act differently when
112 accessed through an instance and through a class. Instance access remains
113 normal, but access to an attribute through a class will be routed to the
114 class's __getattr__ method; this is done by raising AttributeError.
115
116 This allows one to have properties active on an instance, and have virtual
117 attributes on the class with the same name (see Enum for an example).
118
119 """
120 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
121 self.fget = fget
122 self.fset = fset
123 self.fdel = fdel
124 # next two lines make DynamicClassAttribute act the same as property
Ethan Furman63c141c2013-10-18 00:27:39 -0700125 self.__doc__ = doc or fget.__doc__
Ethan Furmane03ea372013-09-25 07:14:41 -0700126 self.overwrite_doc = doc is None
127 # support for abstract methods
128 self.__isabstractmethod__ = bool(getattr(fget, '__isabstractmethod__', False))
129
130 def __get__(self, instance, ownerclass=None):
131 if instance is None:
132 if self.__isabstractmethod__:
133 return self
134 raise AttributeError()
135 elif self.fget is None:
136 raise AttributeError("unreadable attribute")
137 return self.fget(instance)
138
139 def __set__(self, instance, value):
140 if self.fset is None:
141 raise AttributeError("can't set attribute")
142 self.fset(instance, value)
143
144 def __delete__(self, instance):
145 if self.fdel is None:
146 raise AttributeError("can't delete attribute")
147 self.fdel(instance)
148
149 def getter(self, fget):
150 fdoc = fget.__doc__ if self.overwrite_doc else None
151 result = type(self)(fget, self.fset, self.fdel, fdoc or self.__doc__)
152 result.overwrite_doc = self.overwrite_doc
153 return result
154
155 def setter(self, fset):
156 result = type(self)(self.fget, fset, self.fdel, self.__doc__)
157 result.overwrite_doc = self.overwrite_doc
158 return result
159
160 def deleter(self, fdel):
161 result = type(self)(self.fget, self.fset, fdel, self.__doc__)
162 result.overwrite_doc = self.overwrite_doc
163 return result
Serhiy Storchaka7beb4f92015-03-04 09:43:27 +0200164
165
Yury Selivanovc565cd52015-05-29 09:06:05 -0400166import functools as _functools
167import collections.abc as _collections_abc
168
169def coroutine(func):
170 """Convert regular generator function to a coroutine."""
171
Yury Selivanovc565cd52015-05-29 09:06:05 -0400172 if not callable(func):
173 raise TypeError('types.coroutine() expects a callable')
174
Yury Selivanov5376ba92015-06-22 12:19:30 -0400175 if (func.__class__ is FunctionType and
176 getattr(func, '__code__', None).__class__ is CodeType):
Yury Selivanovc565cd52015-05-29 09:06:05 -0400177
Yury Selivanov5376ba92015-06-22 12:19:30 -0400178 co_flags = func.__code__.co_flags
179
180 # Check if 'func' is a coroutine function.
181 # (0x180 == CO_COROUTINE | CO_ITERABLE_COROUTINE)
182 if co_flags & 0x180:
183 return func
184
185 # Check if 'func' is a generator function.
186 # (0x20 == CO_GENERATOR)
187 if co_flags & 0x20:
188 # TODO: Implement this in C.
189 co = func.__code__
190 func.__code__ = CodeType(
191 co.co_argcount, co.co_kwonlyargcount, co.co_nlocals,
192 co.co_stacksize,
193 co.co_flags | 0x100, # 0x100 == CO_ITERABLE_COROUTINE
194 co.co_code,
195 co.co_consts, co.co_names, co.co_varnames, co.co_filename,
196 co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars,
197 co.co_cellvars)
198 return func
Yury Selivanovc565cd52015-05-29 09:06:05 -0400199
Yury Selivanov13f77232015-05-29 16:19:18 -0400200 # The following code is primarily to support functions that
201 # return generator-like objects (for instance generators
202 # compiled with Cython).
203
204 class GeneratorWrapper:
205 def __init__(self, gen):
206 self.__wrapped__ = gen
Yury Selivanov13f77232015-05-29 16:19:18 -0400207 self.__name__ = getattr(gen, '__name__', None)
208 self.__qualname__ = getattr(gen, '__qualname__', None)
Yury Selivanov5376ba92015-06-22 12:19:30 -0400209 def send(self, val):
210 return self.__wrapped__.send(val)
211 def throw(self, *args):
212 return self.__wrapped__.throw(*args)
213 def close(self):
214 return self.__wrapped__.close()
Yury Selivanov13f77232015-05-29 16:19:18 -0400215 @property
216 def gi_code(self):
217 return self.__wrapped__.gi_code
218 @property
219 def gi_frame(self):
220 return self.__wrapped__.gi_frame
221 @property
222 def gi_running(self):
223 return self.__wrapped__.gi_running
Yury Selivanov5376ba92015-06-22 12:19:30 -0400224 cr_code = gi_code
225 cr_frame = gi_frame
226 cr_running = gi_running
Yury Selivanov13f77232015-05-29 16:19:18 -0400227 def __next__(self):
228 return next(self.__wrapped__)
229 def __iter__(self):
230 return self.__wrapped__
Yury Selivanov5376ba92015-06-22 12:19:30 -0400231 def __await__(self):
232 return self.__wrapped__
Yury Selivanov13f77232015-05-29 16:19:18 -0400233
Yury Selivanovc565cd52015-05-29 09:06:05 -0400234 @_functools.wraps(func)
235 def wrapped(*args, **kwargs):
236 coro = func(*args, **kwargs)
Yury Selivanov5376ba92015-06-22 12:19:30 -0400237 if coro.__class__ is CoroutineType:
238 # 'coro' is a native coroutine object.
239 return coro
240 if (coro.__class__ is GeneratorType or
241 (isinstance(coro, _collections_abc.Generator) and
242 not isinstance(coro, _collections_abc.Coroutine))):
243 # 'coro' is either a pure Python generator iterator, or it
244 # implements collections.abc.Generator (and does not implement
245 # collections.abc.Coroutine).
Yury Selivanov13f77232015-05-29 16:19:18 -0400246 return GeneratorWrapper(coro)
Yury Selivanov5376ba92015-06-22 12:19:30 -0400247 # 'coro' is either an instance of collections.abc.Coroutine or
248 # some other object -- pass it through.
Yury Selivanovc565cd52015-05-29 09:06:05 -0400249 return coro
250
251 return wrapped
252
253
Serhiy Storchaka7beb4f92015-03-04 09:43:27 +0200254__all__ = [n for n in globals() if n[:1] != '_']