blob: 19d388eeebfe491283f9175f372b4a9009914194 [file] [log] [blame]
Martin v. Löwise440e472004-06-01 15:22:42 +00001/* Generator object implementation */
2
3#include "Python.h"
4#include "frameobject.h"
Martin v. Löwise440e472004-06-01 15:22:42 +00005#include "structmember.h"
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00006#include "opcode.h"
Martin v. Löwise440e472004-06-01 15:22:42 +00007
Nick Coghlan1f7ce622012-01-13 21:43:40 +10008static PyObject *gen_close(PyGenObject *gen, PyObject *args);
Nick Coghlan1f7ce622012-01-13 21:43:40 +10009
Martin v. Löwise440e472004-06-01 15:22:42 +000010static int
11gen_traverse(PyGenObject *gen, visitproc visit, void *arg)
12{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000013 Py_VISIT((PyObject *)gen->gi_frame);
14 Py_VISIT(gen->gi_code);
Victor Stinner40ee3012014-06-16 15:59:28 +020015 Py_VISIT(gen->gi_name);
16 Py_VISIT(gen->gi_qualname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000017 return 0;
Martin v. Löwise440e472004-06-01 15:22:42 +000018}
19
Antoine Pitrou58720d62013-08-05 23:26:40 +020020void
21_PyGen_Finalize(PyObject *self)
Antoine Pitrou796564c2013-07-30 19:59:21 +020022{
23 PyGenObject *gen = (PyGenObject *)self;
Benjamin Petersonb88db872016-09-07 08:46:59 -070024 PyObject *res = NULL;
Antoine Pitrou796564c2013-07-30 19:59:21 +020025 PyObject *error_type, *error_value, *error_traceback;
26
27 if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL)
28 /* Generator isn't paused, so no need to close */
29 return;
30
31 /* Save the current exception, if any. */
32 PyErr_Fetch(&error_type, &error_value, &error_traceback);
33
Benjamin Peterson2f40ed42016-09-05 10:14:54 -070034 /* If `gen` is a coroutine, and if it was never awaited on,
35 issue a RuntimeWarning. */
Benjamin Petersonb88db872016-09-07 08:46:59 -070036 if (gen->gi_code != NULL &&
37 ((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE &&
38 gen->gi_frame->f_lasti == -1) {
39 if (!error_value) {
40 PyErr_WarnFormat(PyExc_RuntimeWarning, 1,
41 "coroutine '%.50S' was never awaited",
42 gen->gi_qualname);
43 }
Benjamin Peterson2f40ed42016-09-05 10:14:54 -070044 }
45 else {
46 res = gen_close(gen, NULL);
47 }
Antoine Pitrou796564c2013-07-30 19:59:21 +020048
Benjamin Petersonb88db872016-09-07 08:46:59 -070049 if (res == NULL) {
50 if (PyErr_Occurred())
51 PyErr_WriteUnraisable(self);
52 }
53 else {
Antoine Pitrou796564c2013-07-30 19:59:21 +020054 Py_DECREF(res);
Benjamin Petersonb88db872016-09-07 08:46:59 -070055 }
Antoine Pitrou796564c2013-07-30 19:59:21 +020056
57 /* Restore the saved exception. */
58 PyErr_Restore(error_type, error_value, error_traceback);
59}
60
61static void
Martin v. Löwise440e472004-06-01 15:22:42 +000062gen_dealloc(PyGenObject *gen)
63{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000064 PyObject *self = (PyObject *) gen;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000065
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000066 _PyObject_GC_UNTRACK(gen);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000067
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000068 if (gen->gi_weakreflist != NULL)
69 PyObject_ClearWeakRefs(self);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000070
Antoine Pitrou93963562013-05-14 20:37:52 +020071 _PyObject_GC_TRACK(self);
72
Antoine Pitrou796564c2013-07-30 19:59:21 +020073 if (PyObject_CallFinalizerFromDealloc(self))
74 return; /* resurrected. :( */
Antoine Pitrou93963562013-05-14 20:37:52 +020075
76 _PyObject_GC_UNTRACK(self);
Benjamin Petersonbdddb112016-09-05 10:39:57 -070077 if (gen->gi_frame != NULL) {
78 gen->gi_frame->f_gen = NULL;
79 Py_CLEAR(gen->gi_frame);
80 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000081 Py_CLEAR(gen->gi_code);
Victor Stinner40ee3012014-06-16 15:59:28 +020082 Py_CLEAR(gen->gi_name);
83 Py_CLEAR(gen->gi_qualname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000084 PyObject_GC_Del(gen);
Martin v. Löwise440e472004-06-01 15:22:42 +000085}
86
87static PyObject *
Yury Selivanov77c96812016-02-13 17:59:05 -050088gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
Martin v. Löwise440e472004-06-01 15:22:42 +000089{
Antoine Pitrou93963562013-05-14 20:37:52 +020090 PyThreadState *tstate = PyThreadState_GET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000091 PyFrameObject *f = gen->gi_frame;
Antoine Pitrou93963562013-05-14 20:37:52 +020092 PyObject *result;
Martin v. Löwise440e472004-06-01 15:22:42 +000093
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -050094 if (gen->gi_running) {
Yury Selivanov5376ba92015-06-22 12:19:30 -040095 char *msg = "generator already executing";
96 if (PyCoro_CheckExact(gen))
97 msg = "coroutine already executing";
98 PyErr_SetString(PyExc_ValueError, msg);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -050099 return NULL;
100 }
Antoine Pitrou93963562013-05-14 20:37:52 +0200101 if (f == NULL || f->f_stacktop == NULL) {
Yury Selivanov77c96812016-02-13 17:59:05 -0500102 if (PyCoro_CheckExact(gen) && !closing) {
103 /* `gen` is an exhausted coroutine: raise an error,
104 except when called from gen_close(), which should
105 always be a silent method. */
106 PyErr_SetString(
107 PyExc_RuntimeError,
108 "cannot reuse already awaited coroutine");
109 } else if (arg && !exc) {
110 /* `gen` is an exhausted generator:
111 only set exception if called from send(). */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000112 PyErr_SetNone(PyExc_StopIteration);
Yury Selivanov77c96812016-02-13 17:59:05 -0500113 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000114 return NULL;
115 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000116
Antoine Pitrou93963562013-05-14 20:37:52 +0200117 if (f->f_lasti == -1) {
118 if (arg && arg != Py_None) {
Yury Selivanov5376ba92015-06-22 12:19:30 -0400119 char *msg = "can't send non-None value to a "
120 "just-started generator";
121 if (PyCoro_CheckExact(gen))
122 msg = "can't send non-None value to a "
123 "just-started coroutine";
124 PyErr_SetString(PyExc_TypeError, msg);
Antoine Pitrou93963562013-05-14 20:37:52 +0200125 return NULL;
126 }
127 } else {
128 /* Push arg onto the frame's value stack */
129 result = arg ? arg : Py_None;
130 Py_INCREF(result);
131 *(f->f_stacktop++) = result;
132 }
133
134 /* Generators always return to their most recent caller, not
135 * necessarily their creator. */
136 Py_XINCREF(tstate->frame);
137 assert(f->f_back == NULL);
138 f->f_back = tstate->frame;
139
140 gen->gi_running = 1;
141 result = PyEval_EvalFrameEx(f, exc);
142 gen->gi_running = 0;
143
144 /* Don't keep the reference to f_back any longer than necessary. It
145 * may keep a chain of frames alive or it could create a reference
146 * cycle. */
147 assert(f->f_back == tstate->frame);
148 Py_CLEAR(f->f_back);
149
150 /* If the generator just returned (as opposed to yielding), signal
151 * that the generator is exhausted. */
152 if (result && f->f_stacktop == NULL) {
153 if (result == Py_None) {
154 /* Delay exception instantiation if we can */
155 PyErr_SetNone(PyExc_StopIteration);
156 } else {
157 PyObject *e = PyObject_CallFunctionObjArgs(
158 PyExc_StopIteration, result, NULL);
159 if (e != NULL) {
160 PyErr_SetObject(PyExc_StopIteration, e);
161 Py_DECREF(e);
162 }
163 }
164 Py_CLEAR(result);
165 }
Yury Selivanov68333392015-05-22 11:16:47 -0400166 else if (!result && PyErr_ExceptionMatches(PyExc_StopIteration)) {
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400167 /* Check for __future__ generator_stop and conditionally turn
168 * a leaking StopIteration into RuntimeError (with its cause
169 * set appropriately). */
Christian Heimes884332b2016-09-09 00:20:13 +0200170 if (gen->gi_code != NULL && ((PyCodeObject *)gen->gi_code)->co_flags &
Yury Selivanov75445082015-05-11 22:57:16 -0400171 (CO_FUTURE_GENERATOR_STOP | CO_COROUTINE | CO_ITERABLE_COROUTINE))
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400172 {
173 PyObject *exc, *val, *val2, *tb;
Yury Selivanov5376ba92015-06-22 12:19:30 -0400174 char *msg = "generator raised StopIteration";
175 if (PyCoro_CheckExact(gen))
176 msg = "coroutine raised StopIteration";
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400177 PyErr_Fetch(&exc, &val, &tb);
178 PyErr_NormalizeException(&exc, &val, &tb);
179 if (tb != NULL)
180 PyException_SetTraceback(val, tb);
181 Py_DECREF(exc);
182 Py_XDECREF(tb);
Yury Selivanov5376ba92015-06-22 12:19:30 -0400183 PyErr_SetString(PyExc_RuntimeError, msg);
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400184 PyErr_Fetch(&exc, &val2, &tb);
185 PyErr_NormalizeException(&exc, &val2, &tb);
Yury Selivanov18c30a22015-05-10 15:09:46 -0400186 Py_INCREF(val);
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400187 PyException_SetCause(val2, val);
188 PyException_SetContext(val2, val);
189 PyErr_Restore(exc, val2, tb);
190 }
Yury Selivanov68333392015-05-22 11:16:47 -0400191 else {
192 PyObject *exc, *val, *tb;
193
194 /* Pop the exception before issuing a warning. */
195 PyErr_Fetch(&exc, &val, &tb);
196
Martin Panter7e3a91a2016-02-10 04:40:48 +0000197 if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
Yury Selivanov68333392015-05-22 11:16:47 -0400198 "generator '%.50S' raised StopIteration",
199 gen->gi_qualname)) {
200 /* Warning was converted to an error. */
201 Py_XDECREF(exc);
202 Py_XDECREF(val);
203 Py_XDECREF(tb);
204 }
205 else {
206 PyErr_Restore(exc, val, tb);
207 }
208 }
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400209 }
Antoine Pitrou93963562013-05-14 20:37:52 +0200210
211 if (!result || f->f_stacktop == NULL) {
212 /* generator can't be rerun, so release the frame */
213 /* first clean reference cycle through stored exception traceback */
214 PyObject *t, *v, *tb;
215 t = f->f_exc_type;
216 v = f->f_exc_value;
217 tb = f->f_exc_traceback;
218 f->f_exc_type = NULL;
219 f->f_exc_value = NULL;
220 f->f_exc_traceback = NULL;
221 Py_XDECREF(t);
222 Py_XDECREF(v);
223 Py_XDECREF(tb);
Antoine Pitrou58720d62013-08-05 23:26:40 +0200224 gen->gi_frame->f_gen = NULL;
Antoine Pitrou93963562013-05-14 20:37:52 +0200225 gen->gi_frame = NULL;
226 Py_DECREF(f);
227 }
228
229 return result;
Martin v. Löwise440e472004-06-01 15:22:42 +0000230}
231
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000232PyDoc_STRVAR(send_doc,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000233"send(arg) -> send 'arg' into generator,\n\
234return next yielded value or raise StopIteration.");
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000235
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500236PyObject *
237_PyGen_Send(PyGenObject *gen, PyObject *arg)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000238{
Yury Selivanov77c96812016-02-13 17:59:05 -0500239 return gen_send_ex(gen, arg, 0, 0);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000240}
241
242PyDoc_STRVAR(close_doc,
Benjamin Petersonab3da292012-05-03 18:44:09 -0400243"close() -> raise GeneratorExit inside generator.");
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000244
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000245/*
246 * This helper function is used by gen_close and gen_throw to
247 * close a subiterator being delegated to by yield-from.
248 */
249
Antoine Pitrou93963562013-05-14 20:37:52 +0200250static int
251gen_close_iter(PyObject *yf)
252{
253 PyObject *retval = NULL;
254 _Py_IDENTIFIER(close);
255
256 if (PyGen_CheckExact(yf)) {
257 retval = gen_close((PyGenObject *)yf, NULL);
258 if (retval == NULL)
259 return -1;
260 } else {
261 PyObject *meth = _PyObject_GetAttrId(yf, &PyId_close);
262 if (meth == NULL) {
263 if (!PyErr_ExceptionMatches(PyExc_AttributeError))
264 PyErr_WriteUnraisable(yf);
265 PyErr_Clear();
266 } else {
Victor Stinner3466bde2016-09-05 18:16:01 -0700267 retval = _PyObject_CallNoArg(meth);
Antoine Pitrou93963562013-05-14 20:37:52 +0200268 Py_DECREF(meth);
269 if (retval == NULL)
270 return -1;
271 }
272 }
273 Py_XDECREF(retval);
274 return 0;
275}
276
Yury Selivanovc724bae2016-03-02 11:30:46 -0500277PyObject *
278_PyGen_yf(PyGenObject *gen)
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500279{
Antoine Pitrou93963562013-05-14 20:37:52 +0200280 PyObject *yf = NULL;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500281 PyFrameObject *f = gen->gi_frame;
Antoine Pitrou93963562013-05-14 20:37:52 +0200282
283 if (f && f->f_stacktop) {
284 PyObject *bytecode = f->f_code->co_code;
285 unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode);
286
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300287 if (code[f->f_lasti + 2] != YIELD_FROM)
Antoine Pitrou93963562013-05-14 20:37:52 +0200288 return NULL;
289 yf = f->f_stacktop[-1];
290 Py_INCREF(yf);
291 }
292
293 return yf;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500294}
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000295
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000296static PyObject *
297gen_close(PyGenObject *gen, PyObject *args)
298{
Antoine Pitrou93963562013-05-14 20:37:52 +0200299 PyObject *retval;
Yury Selivanovc724bae2016-03-02 11:30:46 -0500300 PyObject *yf = _PyGen_yf(gen);
Antoine Pitrou93963562013-05-14 20:37:52 +0200301 int err = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000302
Antoine Pitrou93963562013-05-14 20:37:52 +0200303 if (yf) {
304 gen->gi_running = 1;
305 err = gen_close_iter(yf);
306 gen->gi_running = 0;
307 Py_DECREF(yf);
308 }
309 if (err == 0)
310 PyErr_SetNone(PyExc_GeneratorExit);
Yury Selivanov77c96812016-02-13 17:59:05 -0500311 retval = gen_send_ex(gen, Py_None, 1, 1);
Antoine Pitrou93963562013-05-14 20:37:52 +0200312 if (retval) {
Yury Selivanov5376ba92015-06-22 12:19:30 -0400313 char *msg = "generator ignored GeneratorExit";
314 if (PyCoro_CheckExact(gen))
315 msg = "coroutine ignored GeneratorExit";
Antoine Pitrou93963562013-05-14 20:37:52 +0200316 Py_DECREF(retval);
Yury Selivanov5376ba92015-06-22 12:19:30 -0400317 PyErr_SetString(PyExc_RuntimeError, msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000318 return NULL;
319 }
Antoine Pitrou93963562013-05-14 20:37:52 +0200320 if (PyErr_ExceptionMatches(PyExc_StopIteration)
321 || PyErr_ExceptionMatches(PyExc_GeneratorExit)) {
322 PyErr_Clear(); /* ignore these errors */
323 Py_INCREF(Py_None);
324 return Py_None;
325 }
326 return NULL;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000327}
328
Antoine Pitrou93963562013-05-14 20:37:52 +0200329
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000330PyDoc_STRVAR(throw_doc,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000331"throw(typ[,val[,tb]]) -> raise exception in generator,\n\
332return next yielded value or raise StopIteration.");
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000333
334static PyObject *
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000335gen_throw(PyGenObject *gen, PyObject *args)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000336{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000337 PyObject *typ;
338 PyObject *tb = NULL;
339 PyObject *val = NULL;
Yury Selivanovc724bae2016-03-02 11:30:46 -0500340 PyObject *yf = _PyGen_yf(gen);
Nick Coghlan5b0dac12012-06-17 15:45:11 +1000341 _Py_IDENTIFIER(throw);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000343 if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb))
344 return NULL;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000345
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000346 if (yf) {
347 PyObject *ret;
348 int err;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000349 if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit)) {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500350 gen->gi_running = 1;
Antoine Pitrou93963562013-05-14 20:37:52 +0200351 err = gen_close_iter(yf);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500352 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000353 Py_DECREF(yf);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000354 if (err < 0)
Yury Selivanov77c96812016-02-13 17:59:05 -0500355 return gen_send_ex(gen, Py_None, 1, 0);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000356 goto throw_here;
357 }
358 if (PyGen_CheckExact(yf)) {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500359 gen->gi_running = 1;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000360 ret = gen_throw((PyGenObject *)yf, args);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500361 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000362 } else {
Nick Coghlan5b0dac12012-06-17 15:45:11 +1000363 PyObject *meth = _PyObject_GetAttrId(yf, &PyId_throw);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000364 if (meth == NULL) {
365 if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
366 Py_DECREF(yf);
367 return NULL;
368 }
369 PyErr_Clear();
370 Py_DECREF(yf);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000371 goto throw_here;
372 }
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500373 gen->gi_running = 1;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000374 ret = PyObject_CallObject(meth, args);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500375 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000376 Py_DECREF(meth);
377 }
378 Py_DECREF(yf);
379 if (!ret) {
380 PyObject *val;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500381 /* Pop subiterator from stack */
382 ret = *(--gen->gi_frame->f_stacktop);
383 assert(ret == yf);
384 Py_DECREF(ret);
385 /* Termination repetition of YIELD_FROM */
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300386 gen->gi_frame->f_lasti += 2;
Nick Coghlanc40bc092012-06-17 15:15:49 +1000387 if (_PyGen_FetchStopIterationValue(&val) == 0) {
Yury Selivanov77c96812016-02-13 17:59:05 -0500388 ret = gen_send_ex(gen, val, 0, 0);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000389 Py_DECREF(val);
390 } else {
Yury Selivanov77c96812016-02-13 17:59:05 -0500391 ret = gen_send_ex(gen, Py_None, 1, 0);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000392 }
393 }
394 return ret;
395 }
396
397throw_here:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000398 /* First, check the traceback argument, replacing None with
399 NULL. */
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400400 if (tb == Py_None) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000401 tb = NULL;
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400402 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000403 else if (tb != NULL && !PyTraceBack_Check(tb)) {
404 PyErr_SetString(PyExc_TypeError,
405 "throw() third argument must be a traceback object");
406 return NULL;
407 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000409 Py_INCREF(typ);
410 Py_XINCREF(val);
411 Py_XINCREF(tb);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000412
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400413 if (PyExceptionClass_Check(typ))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000414 PyErr_NormalizeException(&typ, &val, &tb);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000415
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000416 else if (PyExceptionInstance_Check(typ)) {
417 /* Raising an instance. The value should be a dummy. */
418 if (val && val != Py_None) {
419 PyErr_SetString(PyExc_TypeError,
420 "instance exception may not have a separate value");
421 goto failed_throw;
422 }
423 else {
424 /* Normalize to raise <class>, <instance> */
425 Py_XDECREF(val);
426 val = typ;
427 typ = PyExceptionInstance_Class(typ);
428 Py_INCREF(typ);
Antoine Pitrou551ba202011-10-18 16:40:50 +0200429
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400430 if (tb == NULL)
Antoine Pitrou551ba202011-10-18 16:40:50 +0200431 /* Returns NULL if there's no traceback */
432 tb = PyException_GetTraceback(val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000433 }
434 }
435 else {
436 /* Not something you can raise. throw() fails. */
437 PyErr_Format(PyExc_TypeError,
438 "exceptions must be classes or instances "
439 "deriving from BaseException, not %s",
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000440 Py_TYPE(typ)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000441 goto failed_throw;
442 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000443
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000444 PyErr_Restore(typ, val, tb);
Yury Selivanov77c96812016-02-13 17:59:05 -0500445 return gen_send_ex(gen, Py_None, 1, 0);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000446
447failed_throw:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000448 /* Didn't use our arguments, so restore their original refcounts */
449 Py_DECREF(typ);
450 Py_XDECREF(val);
451 Py_XDECREF(tb);
452 return NULL;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000453}
454
455
456static PyObject *
457gen_iternext(PyGenObject *gen)
458{
Yury Selivanov77c96812016-02-13 17:59:05 -0500459 return gen_send_ex(gen, NULL, 0, 0);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000460}
461
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000462/*
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000463 * If StopIteration exception is set, fetches its 'value'
464 * attribute if any, otherwise sets pvalue to None.
465 *
466 * Returns 0 if no exception or StopIteration is set.
467 * If any other exception is set, returns -1 and leaves
468 * pvalue unchanged.
469 */
470
471int
Nick Coghlanc40bc092012-06-17 15:15:49 +1000472_PyGen_FetchStopIterationValue(PyObject **pvalue) {
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000473 PyObject *et, *ev, *tb;
474 PyObject *value = NULL;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500475
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000476 if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
477 PyErr_Fetch(&et, &ev, &tb);
Antoine Pitrou7403e912015-04-26 18:46:40 +0200478 if (ev) {
479 /* exception will usually be normalised already */
Serhiy Storchaka08d230a2015-05-22 11:02:49 +0300480 if (PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
Antoine Pitrou7403e912015-04-26 18:46:40 +0200481 value = ((PyStopIterationObject *)ev)->value;
482 Py_INCREF(value);
483 Py_DECREF(ev);
484 } else if (et == PyExc_StopIteration) {
485 /* avoid normalisation and take ev as value */
486 value = ev;
487 } else {
488 /* normalisation required */
489 PyErr_NormalizeException(&et, &ev, &tb);
Serhiy Storchaka08d230a2015-05-22 11:02:49 +0300490 if (!PyObject_TypeCheck(ev, (PyTypeObject *)PyExc_StopIteration)) {
Antoine Pitrou7403e912015-04-26 18:46:40 +0200491 PyErr_Restore(et, ev, tb);
492 return -1;
493 }
494 value = ((PyStopIterationObject *)ev)->value;
495 Py_INCREF(value);
496 Py_DECREF(ev);
497 }
498 }
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000499 Py_XDECREF(et);
500 Py_XDECREF(tb);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000501 } else if (PyErr_Occurred()) {
502 return -1;
503 }
504 if (value == NULL) {
505 value = Py_None;
Amaury Forgeot d'Arce557da82012-01-13 21:06:12 +0100506 Py_INCREF(value);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000507 }
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000508 *pvalue = value;
509 return 0;
510}
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000511
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000512static PyObject *
513gen_repr(PyGenObject *gen)
514{
Yury Selivanov5376ba92015-06-22 12:19:30 -0400515 return PyUnicode_FromFormat("<generator object %S at %p>",
516 gen->gi_qualname, gen);
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000517}
518
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000519static PyObject *
Victor Stinner40ee3012014-06-16 15:59:28 +0200520gen_get_name(PyGenObject *op)
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000521{
Victor Stinner40ee3012014-06-16 15:59:28 +0200522 Py_INCREF(op->gi_name);
523 return op->gi_name;
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000524}
525
Victor Stinner40ee3012014-06-16 15:59:28 +0200526static int
527gen_set_name(PyGenObject *op, PyObject *value)
528{
Victor Stinner40ee3012014-06-16 15:59:28 +0200529 /* Not legal to del gen.gi_name or to set it to anything
530 * other than a string object. */
531 if (value == NULL || !PyUnicode_Check(value)) {
532 PyErr_SetString(PyExc_TypeError,
533 "__name__ must be set to a string object");
534 return -1;
535 }
Victor Stinner40ee3012014-06-16 15:59:28 +0200536 Py_INCREF(value);
Serhiy Storchakaec397562016-04-06 09:50:03 +0300537 Py_XSETREF(op->gi_name, value);
Victor Stinner40ee3012014-06-16 15:59:28 +0200538 return 0;
539}
540
541static PyObject *
542gen_get_qualname(PyGenObject *op)
543{
544 Py_INCREF(op->gi_qualname);
545 return op->gi_qualname;
546}
547
548static int
549gen_set_qualname(PyGenObject *op, PyObject *value)
550{
Victor Stinner40ee3012014-06-16 15:59:28 +0200551 /* Not legal to del gen.__qualname__ or to set it to anything
552 * other than a string object. */
553 if (value == NULL || !PyUnicode_Check(value)) {
554 PyErr_SetString(PyExc_TypeError,
555 "__qualname__ must be set to a string object");
556 return -1;
557 }
Victor Stinner40ee3012014-06-16 15:59:28 +0200558 Py_INCREF(value);
Serhiy Storchakaec397562016-04-06 09:50:03 +0300559 Py_XSETREF(op->gi_qualname, value);
Victor Stinner40ee3012014-06-16 15:59:28 +0200560 return 0;
561}
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000562
Yury Selivanove13f8f32015-07-03 00:23:30 -0400563static PyObject *
564gen_getyieldfrom(PyGenObject *gen)
565{
Yury Selivanovc724bae2016-03-02 11:30:46 -0500566 PyObject *yf = _PyGen_yf(gen);
Yury Selivanove13f8f32015-07-03 00:23:30 -0400567 if (yf == NULL)
568 Py_RETURN_NONE;
569 return yf;
570}
571
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000572static PyGetSetDef gen_getsetlist[] = {
Victor Stinner40ee3012014-06-16 15:59:28 +0200573 {"__name__", (getter)gen_get_name, (setter)gen_set_name,
574 PyDoc_STR("name of the generator")},
575 {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
576 PyDoc_STR("qualified name of the generator")},
Yury Selivanove13f8f32015-07-03 00:23:30 -0400577 {"gi_yieldfrom", (getter)gen_getyieldfrom, NULL,
578 PyDoc_STR("object being iterated by yield from, or None")},
Victor Stinner40ee3012014-06-16 15:59:28 +0200579 {NULL} /* Sentinel */
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000580};
581
Martin v. Löwise440e472004-06-01 15:22:42 +0000582static PyMemberDef gen_memberlist[] = {
Victor Stinner40ee3012014-06-16 15:59:28 +0200583 {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), READONLY},
584 {"gi_running", T_BOOL, offsetof(PyGenObject, gi_running), READONLY},
585 {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), READONLY},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000586 {NULL} /* Sentinel */
Martin v. Löwise440e472004-06-01 15:22:42 +0000587};
588
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000589static PyMethodDef gen_methods[] = {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500590 {"send",(PyCFunction)_PyGen_Send, METH_O, send_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc},
592 {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc},
593 {NULL, NULL} /* Sentinel */
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000594};
595
Martin v. Löwise440e472004-06-01 15:22:42 +0000596PyTypeObject PyGen_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000597 PyVarObject_HEAD_INIT(&PyType_Type, 0)
598 "generator", /* tp_name */
599 sizeof(PyGenObject), /* tp_basicsize */
600 0, /* tp_itemsize */
601 /* methods */
602 (destructor)gen_dealloc, /* tp_dealloc */
603 0, /* tp_print */
604 0, /* tp_getattr */
605 0, /* tp_setattr */
Yury Selivanov75445082015-05-11 22:57:16 -0400606 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 (reprfunc)gen_repr, /* tp_repr */
608 0, /* tp_as_number */
609 0, /* tp_as_sequence */
610 0, /* tp_as_mapping */
611 0, /* tp_hash */
612 0, /* tp_call */
613 0, /* tp_str */
614 PyObject_GenericGetAttr, /* tp_getattro */
615 0, /* tp_setattro */
616 0, /* tp_as_buffer */
Antoine Pitrou796564c2013-07-30 19:59:21 +0200617 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
618 Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000619 0, /* tp_doc */
620 (traverseproc)gen_traverse, /* tp_traverse */
621 0, /* tp_clear */
622 0, /* tp_richcompare */
623 offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */
Yury Selivanov5376ba92015-06-22 12:19:30 -0400624 PyObject_SelfIter, /* tp_iter */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000625 (iternextfunc)gen_iternext, /* tp_iternext */
626 gen_methods, /* tp_methods */
627 gen_memberlist, /* tp_members */
628 gen_getsetlist, /* tp_getset */
629 0, /* tp_base */
630 0, /* tp_dict */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 0, /* tp_descr_get */
633 0, /* tp_descr_set */
634 0, /* tp_dictoffset */
635 0, /* tp_init */
636 0, /* tp_alloc */
637 0, /* tp_new */
638 0, /* tp_free */
639 0, /* tp_is_gc */
640 0, /* tp_bases */
641 0, /* tp_mro */
642 0, /* tp_cache */
643 0, /* tp_subclasses */
644 0, /* tp_weaklist */
Antoine Pitrou796564c2013-07-30 19:59:21 +0200645 0, /* tp_del */
646 0, /* tp_version_tag */
Antoine Pitrou58720d62013-08-05 23:26:40 +0200647 _PyGen_Finalize, /* tp_finalize */
Martin v. Löwise440e472004-06-01 15:22:42 +0000648};
649
Yury Selivanov5376ba92015-06-22 12:19:30 -0400650static PyObject *
651gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,
652 PyObject *name, PyObject *qualname)
Martin v. Löwise440e472004-06-01 15:22:42 +0000653{
Yury Selivanov5376ba92015-06-22 12:19:30 -0400654 PyGenObject *gen = PyObject_GC_New(PyGenObject, type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000655 if (gen == NULL) {
656 Py_DECREF(f);
657 return NULL;
658 }
659 gen->gi_frame = f;
Antoine Pitrou58720d62013-08-05 23:26:40 +0200660 f->f_gen = (PyObject *) gen;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000661 Py_INCREF(f->f_code);
662 gen->gi_code = (PyObject *)(f->f_code);
663 gen->gi_running = 0;
664 gen->gi_weakreflist = NULL;
Victor Stinner40ee3012014-06-16 15:59:28 +0200665 if (name != NULL)
666 gen->gi_name = name;
667 else
668 gen->gi_name = ((PyCodeObject *)gen->gi_code)->co_name;
669 Py_INCREF(gen->gi_name);
670 if (qualname != NULL)
671 gen->gi_qualname = qualname;
672 else
673 gen->gi_qualname = gen->gi_name;
674 Py_INCREF(gen->gi_qualname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000675 _PyObject_GC_TRACK(gen);
676 return (PyObject *)gen;
Martin v. Löwise440e472004-06-01 15:22:42 +0000677}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000678
Victor Stinner40ee3012014-06-16 15:59:28 +0200679PyObject *
Yury Selivanov5376ba92015-06-22 12:19:30 -0400680PyGen_NewWithQualName(PyFrameObject *f, PyObject *name, PyObject *qualname)
681{
682 return gen_new_with_qualname(&PyGen_Type, f, name, qualname);
683}
684
685PyObject *
Victor Stinner40ee3012014-06-16 15:59:28 +0200686PyGen_New(PyFrameObject *f)
687{
Yury Selivanov5376ba92015-06-22 12:19:30 -0400688 return gen_new_with_qualname(&PyGen_Type, f, NULL, NULL);
Victor Stinner40ee3012014-06-16 15:59:28 +0200689}
690
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000691int
692PyGen_NeedsFinalizing(PyGenObject *gen)
693{
Antoine Pitrou93963562013-05-14 20:37:52 +0200694 int i;
695 PyFrameObject *f = gen->gi_frame;
696
697 if (f == NULL || f->f_stacktop == NULL)
698 return 0; /* no frame or empty blockstack == no finalization */
699
700 /* Any block type besides a loop requires cleanup. */
701 for (i = 0; i < f->f_iblock; i++)
702 if (f->f_blockstack[i].b_type != SETUP_LOOP)
703 return 1;
704
705 /* No blocks except loops, it's safe to skip finalization. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 return 0;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000707}
Yury Selivanov75445082015-05-11 22:57:16 -0400708
Yury Selivanov5376ba92015-06-22 12:19:30 -0400709/* Coroutine Object */
710
711typedef struct {
712 PyObject_HEAD
713 PyCoroObject *cw_coroutine;
714} PyCoroWrapper;
715
716static int
717gen_is_coroutine(PyObject *o)
718{
719 if (PyGen_CheckExact(o)) {
720 PyCodeObject *code = (PyCodeObject *)((PyGenObject*)o)->gi_code;
721 if (code->co_flags & CO_ITERABLE_COROUTINE) {
722 return 1;
723 }
724 }
725 return 0;
726}
727
Yury Selivanov75445082015-05-11 22:57:16 -0400728/*
729 * This helper function returns an awaitable for `o`:
730 * - `o` if `o` is a coroutine-object;
731 * - `type(o)->tp_as_async->am_await(o)`
732 *
733 * Raises a TypeError if it's not possible to return
734 * an awaitable and returns NULL.
735 */
736PyObject *
Yury Selivanov5376ba92015-06-22 12:19:30 -0400737_PyCoro_GetAwaitableIter(PyObject *o)
Yury Selivanov75445082015-05-11 22:57:16 -0400738{
Yury Selivanov6ef05902015-05-28 11:21:31 -0400739 unaryfunc getter = NULL;
Yury Selivanov75445082015-05-11 22:57:16 -0400740 PyTypeObject *ot;
741
Yury Selivanov5376ba92015-06-22 12:19:30 -0400742 if (PyCoro_CheckExact(o) || gen_is_coroutine(o)) {
743 /* 'o' is a coroutine. */
Yury Selivanov75445082015-05-11 22:57:16 -0400744 Py_INCREF(o);
745 return o;
746 }
747
748 ot = Py_TYPE(o);
749 if (ot->tp_as_async != NULL) {
750 getter = ot->tp_as_async->am_await;
751 }
752 if (getter != NULL) {
753 PyObject *res = (*getter)(o);
754 if (res != NULL) {
Yury Selivanov5376ba92015-06-22 12:19:30 -0400755 if (PyCoro_CheckExact(res) || gen_is_coroutine(res)) {
756 /* __await__ must return an *iterator*, not
757 a coroutine or another awaitable (see PEP 492) */
758 PyErr_SetString(PyExc_TypeError,
759 "__await__() returned a coroutine");
760 Py_CLEAR(res);
761 } else if (!PyIter_Check(res)) {
Yury Selivanov75445082015-05-11 22:57:16 -0400762 PyErr_Format(PyExc_TypeError,
763 "__await__() returned non-iterator "
764 "of type '%.100s'",
765 Py_TYPE(res)->tp_name);
766 Py_CLEAR(res);
767 }
Yury Selivanov75445082015-05-11 22:57:16 -0400768 }
769 return res;
770 }
771
772 PyErr_Format(PyExc_TypeError,
773 "object %.100s can't be used in 'await' expression",
774 ot->tp_name);
Yury Selivanov75445082015-05-11 22:57:16 -0400775 return NULL;
776}
Yury Selivanov5376ba92015-06-22 12:19:30 -0400777
778static PyObject *
779coro_repr(PyCoroObject *coro)
780{
781 return PyUnicode_FromFormat("<coroutine object %S at %p>",
782 coro->cr_qualname, coro);
783}
784
785static PyObject *
786coro_await(PyCoroObject *coro)
787{
788 PyCoroWrapper *cw = PyObject_GC_New(PyCoroWrapper, &_PyCoroWrapper_Type);
789 if (cw == NULL) {
790 return NULL;
791 }
792 Py_INCREF(coro);
793 cw->cw_coroutine = coro;
794 _PyObject_GC_TRACK(cw);
795 return (PyObject *)cw;
796}
797
Yury Selivanove13f8f32015-07-03 00:23:30 -0400798static PyObject *
799coro_get_cr_await(PyCoroObject *coro)
800{
Yury Selivanovc724bae2016-03-02 11:30:46 -0500801 PyObject *yf = _PyGen_yf((PyGenObject *) coro);
Yury Selivanove13f8f32015-07-03 00:23:30 -0400802 if (yf == NULL)
803 Py_RETURN_NONE;
804 return yf;
805}
806
Yury Selivanov5376ba92015-06-22 12:19:30 -0400807static PyGetSetDef coro_getsetlist[] = {
808 {"__name__", (getter)gen_get_name, (setter)gen_set_name,
809 PyDoc_STR("name of the coroutine")},
810 {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
811 PyDoc_STR("qualified name of the coroutine")},
Yury Selivanove13f8f32015-07-03 00:23:30 -0400812 {"cr_await", (getter)coro_get_cr_await, NULL,
813 PyDoc_STR("object being awaited on, or None")},
Yury Selivanov5376ba92015-06-22 12:19:30 -0400814 {NULL} /* Sentinel */
815};
816
817static PyMemberDef coro_memberlist[] = {
818 {"cr_frame", T_OBJECT, offsetof(PyCoroObject, cr_frame), READONLY},
819 {"cr_running", T_BOOL, offsetof(PyCoroObject, cr_running), READONLY},
820 {"cr_code", T_OBJECT, offsetof(PyCoroObject, cr_code), READONLY},
821 {NULL} /* Sentinel */
822};
823
824PyDoc_STRVAR(coro_send_doc,
825"send(arg) -> send 'arg' into coroutine,\n\
Yury Selivanov66f88282015-06-24 11:04:15 -0400826return next iterated value or raise StopIteration.");
Yury Selivanov5376ba92015-06-22 12:19:30 -0400827
828PyDoc_STRVAR(coro_throw_doc,
829"throw(typ[,val[,tb]]) -> raise exception in coroutine,\n\
Yury Selivanov66f88282015-06-24 11:04:15 -0400830return next iterated value or raise StopIteration.");
Yury Selivanov5376ba92015-06-22 12:19:30 -0400831
832PyDoc_STRVAR(coro_close_doc,
833"close() -> raise GeneratorExit inside coroutine.");
834
835static PyMethodDef coro_methods[] = {
836 {"send",(PyCFunction)_PyGen_Send, METH_O, coro_send_doc},
837 {"throw",(PyCFunction)gen_throw, METH_VARARGS, coro_throw_doc},
838 {"close",(PyCFunction)gen_close, METH_NOARGS, coro_close_doc},
839 {NULL, NULL} /* Sentinel */
840};
841
842static PyAsyncMethods coro_as_async = {
843 (unaryfunc)coro_await, /* am_await */
844 0, /* am_aiter */
845 0 /* am_anext */
846};
847
848PyTypeObject PyCoro_Type = {
849 PyVarObject_HEAD_INIT(&PyType_Type, 0)
850 "coroutine", /* tp_name */
851 sizeof(PyCoroObject), /* tp_basicsize */
852 0, /* tp_itemsize */
853 /* methods */
854 (destructor)gen_dealloc, /* tp_dealloc */
855 0, /* tp_print */
856 0, /* tp_getattr */
857 0, /* tp_setattr */
858 &coro_as_async, /* tp_as_async */
859 (reprfunc)coro_repr, /* tp_repr */
860 0, /* tp_as_number */
861 0, /* tp_as_sequence */
862 0, /* tp_as_mapping */
863 0, /* tp_hash */
864 0, /* tp_call */
865 0, /* tp_str */
866 PyObject_GenericGetAttr, /* tp_getattro */
867 0, /* tp_setattro */
868 0, /* tp_as_buffer */
869 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
870 Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
871 0, /* tp_doc */
872 (traverseproc)gen_traverse, /* tp_traverse */
873 0, /* tp_clear */
874 0, /* tp_richcompare */
875 offsetof(PyCoroObject, cr_weakreflist), /* tp_weaklistoffset */
876 0, /* tp_iter */
877 0, /* tp_iternext */
878 coro_methods, /* tp_methods */
879 coro_memberlist, /* tp_members */
880 coro_getsetlist, /* tp_getset */
881 0, /* tp_base */
882 0, /* tp_dict */
883 0, /* tp_descr_get */
884 0, /* tp_descr_set */
885 0, /* tp_dictoffset */
886 0, /* tp_init */
887 0, /* tp_alloc */
888 0, /* tp_new */
889 0, /* tp_free */
890 0, /* tp_is_gc */
891 0, /* tp_bases */
892 0, /* tp_mro */
893 0, /* tp_cache */
894 0, /* tp_subclasses */
895 0, /* tp_weaklist */
896 0, /* tp_del */
897 0, /* tp_version_tag */
898 _PyGen_Finalize, /* tp_finalize */
899};
900
901static void
902coro_wrapper_dealloc(PyCoroWrapper *cw)
903{
904 _PyObject_GC_UNTRACK((PyObject *)cw);
905 Py_CLEAR(cw->cw_coroutine);
906 PyObject_GC_Del(cw);
907}
908
909static PyObject *
910coro_wrapper_iternext(PyCoroWrapper *cw)
911{
Yury Selivanov77c96812016-02-13 17:59:05 -0500912 return gen_send_ex((PyGenObject *)cw->cw_coroutine, NULL, 0, 0);
Yury Selivanov5376ba92015-06-22 12:19:30 -0400913}
914
915static PyObject *
916coro_wrapper_send(PyCoroWrapper *cw, PyObject *arg)
917{
Yury Selivanov77c96812016-02-13 17:59:05 -0500918 return gen_send_ex((PyGenObject *)cw->cw_coroutine, arg, 0, 0);
Yury Selivanov5376ba92015-06-22 12:19:30 -0400919}
920
921static PyObject *
922coro_wrapper_throw(PyCoroWrapper *cw, PyObject *args)
923{
924 return gen_throw((PyGenObject *)cw->cw_coroutine, args);
925}
926
927static PyObject *
928coro_wrapper_close(PyCoroWrapper *cw, PyObject *args)
929{
930 return gen_close((PyGenObject *)cw->cw_coroutine, args);
931}
932
933static int
934coro_wrapper_traverse(PyCoroWrapper *cw, visitproc visit, void *arg)
935{
936 Py_VISIT((PyObject *)cw->cw_coroutine);
937 return 0;
938}
939
940static PyMethodDef coro_wrapper_methods[] = {
Yury Selivanov66f88282015-06-24 11:04:15 -0400941 {"send",(PyCFunction)coro_wrapper_send, METH_O, coro_send_doc},
942 {"throw",(PyCFunction)coro_wrapper_throw, METH_VARARGS, coro_throw_doc},
943 {"close",(PyCFunction)coro_wrapper_close, METH_NOARGS, coro_close_doc},
Yury Selivanov5376ba92015-06-22 12:19:30 -0400944 {NULL, NULL} /* Sentinel */
945};
946
947PyTypeObject _PyCoroWrapper_Type = {
948 PyVarObject_HEAD_INIT(&PyType_Type, 0)
949 "coroutine_wrapper",
950 sizeof(PyCoroWrapper), /* tp_basicsize */
951 0, /* tp_itemsize */
952 (destructor)coro_wrapper_dealloc, /* destructor tp_dealloc */
953 0, /* tp_print */
954 0, /* tp_getattr */
955 0, /* tp_setattr */
956 0, /* tp_as_async */
957 0, /* tp_repr */
958 0, /* tp_as_number */
959 0, /* tp_as_sequence */
960 0, /* tp_as_mapping */
961 0, /* tp_hash */
962 0, /* tp_call */
963 0, /* tp_str */
964 PyObject_GenericGetAttr, /* tp_getattro */
965 0, /* tp_setattro */
966 0, /* tp_as_buffer */
967 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
968 "A wrapper object implementing __await__ for coroutines.",
969 (traverseproc)coro_wrapper_traverse, /* tp_traverse */
970 0, /* tp_clear */
971 0, /* tp_richcompare */
972 0, /* tp_weaklistoffset */
973 PyObject_SelfIter, /* tp_iter */
974 (iternextfunc)coro_wrapper_iternext, /* tp_iternext */
975 coro_wrapper_methods, /* tp_methods */
976 0, /* tp_members */
977 0, /* tp_getset */
978 0, /* tp_base */
979 0, /* tp_dict */
980 0, /* tp_descr_get */
981 0, /* tp_descr_set */
982 0, /* tp_dictoffset */
983 0, /* tp_init */
984 0, /* tp_alloc */
985 0, /* tp_new */
986 PyObject_Del, /* tp_free */
987};
988
989PyObject *
990PyCoro_New(PyFrameObject *f, PyObject *name, PyObject *qualname)
991{
992 return gen_new_with_qualname(&PyCoro_Type, f, name, qualname);
993}
Yury Selivanova6f6edb2016-06-09 15:08:31 -0400994
995
996/* __aiter__ wrapper; see http://bugs.python.org/issue27243 for details. */
997
998typedef struct {
999 PyObject_HEAD
1000 PyObject *aw_aiter;
1001} PyAIterWrapper;
1002
1003
1004static PyObject *
1005aiter_wrapper_iternext(PyAIterWrapper *aw)
1006{
1007 PyErr_SetObject(PyExc_StopIteration, aw->aw_aiter);
1008 return NULL;
1009}
1010
1011static int
1012aiter_wrapper_traverse(PyAIterWrapper *aw, visitproc visit, void *arg)
1013{
1014 Py_VISIT((PyObject *)aw->aw_aiter);
1015 return 0;
1016}
1017
1018static void
1019aiter_wrapper_dealloc(PyAIterWrapper *aw)
1020{
1021 _PyObject_GC_UNTRACK((PyObject *)aw);
1022 Py_CLEAR(aw->aw_aiter);
1023 PyObject_GC_Del(aw);
1024}
1025
1026static PyAsyncMethods aiter_wrapper_as_async = {
1027 PyObject_SelfIter, /* am_await */
1028 0, /* am_aiter */
1029 0 /* am_anext */
1030};
1031
1032PyTypeObject _PyAIterWrapper_Type = {
1033 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1034 "aiter_wrapper",
1035 sizeof(PyAIterWrapper), /* tp_basicsize */
1036 0, /* tp_itemsize */
1037 (destructor)aiter_wrapper_dealloc, /* destructor tp_dealloc */
1038 0, /* tp_print */
1039 0, /* tp_getattr */
1040 0, /* tp_setattr */
1041 &aiter_wrapper_as_async, /* tp_as_async */
1042 0, /* tp_repr */
1043 0, /* tp_as_number */
1044 0, /* tp_as_sequence */
1045 0, /* tp_as_mapping */
1046 0, /* tp_hash */
1047 0, /* tp_call */
1048 0, /* tp_str */
1049 PyObject_GenericGetAttr, /* tp_getattro */
1050 0, /* tp_setattro */
1051 0, /* tp_as_buffer */
1052 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1053 "A wrapper object for __aiter__ bakwards compatibility.",
1054 (traverseproc)aiter_wrapper_traverse, /* tp_traverse */
1055 0, /* tp_clear */
1056 0, /* tp_richcompare */
1057 0, /* tp_weaklistoffset */
1058 PyObject_SelfIter, /* tp_iter */
1059 (iternextfunc)aiter_wrapper_iternext, /* tp_iternext */
1060 0, /* tp_methods */
1061 0, /* tp_members */
1062 0, /* tp_getset */
1063 0, /* tp_base */
1064 0, /* tp_dict */
1065 0, /* tp_descr_get */
1066 0, /* tp_descr_set */
1067 0, /* tp_dictoffset */
1068 0, /* tp_init */
1069 0, /* tp_alloc */
1070 0, /* tp_new */
1071 PyObject_Del, /* tp_free */
1072};
1073
1074
1075PyObject *
1076_PyAIterWrapper_New(PyObject *aiter)
1077{
1078 PyAIterWrapper *aw = PyObject_GC_New(PyAIterWrapper,
1079 &_PyAIterWrapper_Type);
1080 if (aw == NULL) {
1081 return NULL;
1082 }
1083 Py_INCREF(aiter);
1084 aw->aw_aiter = aiter;
1085 _PyObject_GC_TRACK(aw);
1086 return (PyObject *)aw;
1087}