blob: 1d44653ef9749d513e8c5f3b95ba27b54c2b459d [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
Yury Selivanov00e33722015-06-24 11:44:51 -0400169class _GeneratorWrapper:
170 # TODO: Implement this in C.
171 def __init__(self, gen):
172 self.__wrapped__ = gen
173 self.__isgen__ = gen.__class__ is GeneratorType
174 self.__name__ = getattr(gen, '__name__', None)
175 self.__qualname__ = getattr(gen, '__qualname__', None)
176 def send(self, val):
177 return self.__wrapped__.send(val)
178 def throw(self, tp, *rest):
179 return self.__wrapped__.throw(tp, *rest)
180 def close(self):
181 return self.__wrapped__.close()
182 @property
183 def gi_code(self):
184 return self.__wrapped__.gi_code
185 @property
186 def gi_frame(self):
187 return self.__wrapped__.gi_frame
188 @property
189 def gi_running(self):
190 return self.__wrapped__.gi_running
191 cr_code = gi_code
192 cr_frame = gi_frame
193 cr_running = gi_running
194 def __next__(self):
195 return next(self.__wrapped__)
196 def __iter__(self):
197 if self.__isgen__:
198 return self.__wrapped__
199 return self
200 __await__ = __iter__
201
Yury Selivanovc565cd52015-05-29 09:06:05 -0400202def coroutine(func):
203 """Convert regular generator function to a coroutine."""
204
Yury Selivanovc565cd52015-05-29 09:06:05 -0400205 if not callable(func):
206 raise TypeError('types.coroutine() expects a callable')
207
Yury Selivanov5376ba92015-06-22 12:19:30 -0400208 if (func.__class__ is FunctionType and
209 getattr(func, '__code__', None).__class__ is CodeType):
Yury Selivanovc565cd52015-05-29 09:06:05 -0400210
Yury Selivanov5376ba92015-06-22 12:19:30 -0400211 co_flags = func.__code__.co_flags
212
213 # Check if 'func' is a coroutine function.
214 # (0x180 == CO_COROUTINE | CO_ITERABLE_COROUTINE)
215 if co_flags & 0x180:
216 return func
217
218 # Check if 'func' is a generator function.
219 # (0x20 == CO_GENERATOR)
220 if co_flags & 0x20:
221 # TODO: Implement this in C.
222 co = func.__code__
223 func.__code__ = CodeType(
224 co.co_argcount, co.co_kwonlyargcount, co.co_nlocals,
225 co.co_stacksize,
226 co.co_flags | 0x100, # 0x100 == CO_ITERABLE_COROUTINE
227 co.co_code,
228 co.co_consts, co.co_names, co.co_varnames, co.co_filename,
229 co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars,
230 co.co_cellvars)
231 return func
Yury Selivanovc565cd52015-05-29 09:06:05 -0400232
Yury Selivanov13f77232015-05-29 16:19:18 -0400233 # The following code is primarily to support functions that
234 # return generator-like objects (for instance generators
235 # compiled with Cython).
236
Yury Selivanovc565cd52015-05-29 09:06:05 -0400237 @_functools.wraps(func)
238 def wrapped(*args, **kwargs):
239 coro = func(*args, **kwargs)
Yury Selivanov5376ba92015-06-22 12:19:30 -0400240 if coro.__class__ is CoroutineType:
241 # 'coro' is a native coroutine object.
242 return coro
243 if (coro.__class__ is GeneratorType or
244 (isinstance(coro, _collections_abc.Generator) and
245 not isinstance(coro, _collections_abc.Coroutine))):
246 # 'coro' is either a pure Python generator iterator, or it
247 # implements collections.abc.Generator (and does not implement
248 # collections.abc.Coroutine).
Yury Selivanov00e33722015-06-24 11:44:51 -0400249 return _GeneratorWrapper(coro)
Yury Selivanov5376ba92015-06-22 12:19:30 -0400250 # 'coro' is either an instance of collections.abc.Coroutine or
251 # some other object -- pass it through.
Yury Selivanovc565cd52015-05-29 09:06:05 -0400252 return coro
253
254 return wrapped
255
256
Serhiy Storchaka7beb4f92015-03-04 09:43:27 +0200257__all__ = [n for n in globals() if n[:1] != '_']