blob: 48891cd3f60dab5738c8aff627d094a4905bdbb3 [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):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400172 self.__wrapped = gen
173 self.__isgen = gen.__class__ is GeneratorType
Yury Selivanov00e33722015-06-24 11:44:51 -0400174 self.__name__ = getattr(gen, '__name__', None)
175 self.__qualname__ = getattr(gen, '__qualname__', None)
176 def send(self, val):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400177 return self.__wrapped.send(val)
Yury Selivanov00e33722015-06-24 11:44:51 -0400178 def throw(self, tp, *rest):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400179 return self.__wrapped.throw(tp, *rest)
Yury Selivanov00e33722015-06-24 11:44:51 -0400180 def close(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400181 return self.__wrapped.close()
Yury Selivanov00e33722015-06-24 11:44:51 -0400182 @property
183 def gi_code(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400184 return self.__wrapped.gi_code
Yury Selivanov00e33722015-06-24 11:44:51 -0400185 @property
186 def gi_frame(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400187 return self.__wrapped.gi_frame
Yury Selivanov00e33722015-06-24 11:44:51 -0400188 @property
189 def gi_running(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400190 return self.__wrapped.gi_running
Yury Selivanov53e62302015-07-03 00:35:02 -0400191 @property
192 def gi_yieldfrom(self):
193 return self.__wrapped.gi_yieldfrom
Yury Selivanov00e33722015-06-24 11:44:51 -0400194 cr_code = gi_code
195 cr_frame = gi_frame
196 cr_running = gi_running
Yury Selivanov53e62302015-07-03 00:35:02 -0400197 cr_await = gi_yieldfrom
Yury Selivanov00e33722015-06-24 11:44:51 -0400198 def __next__(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400199 return next(self.__wrapped)
Yury Selivanov00e33722015-06-24 11:44:51 -0400200 def __iter__(self):
Yury Selivanovf847f1f2015-06-24 12:49:28 -0400201 if self.__isgen:
202 return self.__wrapped
Yury Selivanov00e33722015-06-24 11:44:51 -0400203 return self
204 __await__ = __iter__
205
Yury Selivanovc565cd52015-05-29 09:06:05 -0400206def coroutine(func):
207 """Convert regular generator function to a coroutine."""
208
Yury Selivanovc565cd52015-05-29 09:06:05 -0400209 if not callable(func):
210 raise TypeError('types.coroutine() expects a callable')
211
Yury Selivanov5376ba92015-06-22 12:19:30 -0400212 if (func.__class__ is FunctionType and
213 getattr(func, '__code__', None).__class__ is CodeType):
Yury Selivanovc565cd52015-05-29 09:06:05 -0400214
Yury Selivanov5376ba92015-06-22 12:19:30 -0400215 co_flags = func.__code__.co_flags
216
217 # Check if 'func' is a coroutine function.
218 # (0x180 == CO_COROUTINE | CO_ITERABLE_COROUTINE)
219 if co_flags & 0x180:
220 return func
221
222 # Check if 'func' is a generator function.
223 # (0x20 == CO_GENERATOR)
224 if co_flags & 0x20:
225 # TODO: Implement this in C.
226 co = func.__code__
227 func.__code__ = CodeType(
228 co.co_argcount, co.co_kwonlyargcount, co.co_nlocals,
229 co.co_stacksize,
230 co.co_flags | 0x100, # 0x100 == CO_ITERABLE_COROUTINE
231 co.co_code,
232 co.co_consts, co.co_names, co.co_varnames, co.co_filename,
233 co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars,
234 co.co_cellvars)
235 return func
Yury Selivanovc565cd52015-05-29 09:06:05 -0400236
Yury Selivanov13f77232015-05-29 16:19:18 -0400237 # The following code is primarily to support functions that
238 # return generator-like objects (for instance generators
239 # compiled with Cython).
240
Yury Selivanovc565cd52015-05-29 09:06:05 -0400241 @_functools.wraps(func)
242 def wrapped(*args, **kwargs):
243 coro = func(*args, **kwargs)
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400244 if (coro.__class__ is CoroutineType or
245 coro.__class__ is GeneratorType and coro.gi_code.co_flags & 0x100):
246 # 'coro' is a native coroutine object or an iterable coroutine
Yury Selivanov5376ba92015-06-22 12:19:30 -0400247 return coro
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400248 if (isinstance(coro, _collections_abc.Generator) and
249 not isinstance(coro, _collections_abc.Coroutine)):
Yury Selivanov5376ba92015-06-22 12:19:30 -0400250 # 'coro' is either a pure Python generator iterator, or it
251 # implements collections.abc.Generator (and does not implement
252 # collections.abc.Coroutine).
Yury Selivanov00e33722015-06-24 11:44:51 -0400253 return _GeneratorWrapper(coro)
Yury Selivanov5376ba92015-06-22 12:19:30 -0400254 # 'coro' is either an instance of collections.abc.Coroutine or
255 # some other object -- pass it through.
Yury Selivanovc565cd52015-05-29 09:06:05 -0400256 return coro
257
258 return wrapped
259
260
Serhiy Storchaka7beb4f92015-03-04 09:43:27 +0200261__all__ = [n for n in globals() if n[:1] != '_']