blob: 01c59c24a968c717806fe18f23b2975c22fe226b [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;
24 PyObject *res;
25 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. */
36 if (gen->gi_code != NULL
37 && ((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE
38 && gen->gi_frame->f_lasti == -1
39 && !PyErr_Occurred()
40 && PyErr_WarnFormat(PyExc_RuntimeWarning, 1,
41 "coroutine '%.50S' was never awaited",
42 gen->gi_qualname)) {
43 res = NULL; /* oops, exception */
44 }
45 else {
46 res = gen_close(gen, NULL);
47 }
Antoine Pitrou796564c2013-07-30 19:59:21 +020048
49 if (res == NULL)
50 PyErr_WriteUnraisable(self);
51 else
52 Py_DECREF(res);
53
54 /* Restore the saved exception. */
55 PyErr_Restore(error_type, error_value, error_traceback);
56}
57
58static void
Martin v. Löwise440e472004-06-01 15:22:42 +000059gen_dealloc(PyGenObject *gen)
60{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000061 PyObject *self = (PyObject *) gen;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000062
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000063 _PyObject_GC_UNTRACK(gen);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 if (gen->gi_weakreflist != NULL)
66 PyObject_ClearWeakRefs(self);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000067
Antoine Pitrou93963562013-05-14 20:37:52 +020068 _PyObject_GC_TRACK(self);
69
Antoine Pitrou796564c2013-07-30 19:59:21 +020070 if (PyObject_CallFinalizerFromDealloc(self))
71 return; /* resurrected. :( */
Antoine Pitrou93963562013-05-14 20:37:52 +020072
73 _PyObject_GC_UNTRACK(self);
Benjamin Petersonbdddb112016-09-05 10:39:57 -070074 if (gen->gi_frame != NULL) {
75 gen->gi_frame->f_gen = NULL;
76 Py_CLEAR(gen->gi_frame);
77 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000078 Py_CLEAR(gen->gi_code);
Victor Stinner40ee3012014-06-16 15:59:28 +020079 Py_CLEAR(gen->gi_name);
80 Py_CLEAR(gen->gi_qualname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000081 PyObject_GC_Del(gen);
Martin v. Löwise440e472004-06-01 15:22:42 +000082}
83
84static PyObject *
Yury Selivanov77c96812016-02-13 17:59:05 -050085gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
Martin v. Löwise440e472004-06-01 15:22:42 +000086{
Antoine Pitrou93963562013-05-14 20:37:52 +020087 PyThreadState *tstate = PyThreadState_GET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000088 PyFrameObject *f = gen->gi_frame;
Antoine Pitrou93963562013-05-14 20:37:52 +020089 PyObject *result;
Martin v. Löwise440e472004-06-01 15:22:42 +000090
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -050091 if (gen->gi_running) {
Yury Selivanov5376ba92015-06-22 12:19:30 -040092 char *msg = "generator already executing";
93 if (PyCoro_CheckExact(gen))
94 msg = "coroutine already executing";
95 PyErr_SetString(PyExc_ValueError, msg);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -050096 return NULL;
97 }
Antoine Pitrou93963562013-05-14 20:37:52 +020098 if (f == NULL || f->f_stacktop == NULL) {
Yury Selivanov77c96812016-02-13 17:59:05 -050099 if (PyCoro_CheckExact(gen) && !closing) {
100 /* `gen` is an exhausted coroutine: raise an error,
101 except when called from gen_close(), which should
102 always be a silent method. */
103 PyErr_SetString(
104 PyExc_RuntimeError,
105 "cannot reuse already awaited coroutine");
106 } else if (arg && !exc) {
107 /* `gen` is an exhausted generator:
108 only set exception if called from send(). */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000109 PyErr_SetNone(PyExc_StopIteration);
Yury Selivanov77c96812016-02-13 17:59:05 -0500110 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000111 return NULL;
112 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000113
Antoine Pitrou93963562013-05-14 20:37:52 +0200114 if (f->f_lasti == -1) {
115 if (arg && arg != Py_None) {
Yury Selivanov5376ba92015-06-22 12:19:30 -0400116 char *msg = "can't send non-None value to a "
117 "just-started generator";
118 if (PyCoro_CheckExact(gen))
119 msg = "can't send non-None value to a "
120 "just-started coroutine";
121 PyErr_SetString(PyExc_TypeError, msg);
Antoine Pitrou93963562013-05-14 20:37:52 +0200122 return NULL;
123 }
124 } else {
125 /* Push arg onto the frame's value stack */
126 result = arg ? arg : Py_None;
127 Py_INCREF(result);
128 *(f->f_stacktop++) = result;
129 }
130
131 /* Generators always return to their most recent caller, not
132 * necessarily their creator. */
133 Py_XINCREF(tstate->frame);
134 assert(f->f_back == NULL);
135 f->f_back = tstate->frame;
136
137 gen->gi_running = 1;
138 result = PyEval_EvalFrameEx(f, exc);
139 gen->gi_running = 0;
140
141 /* Don't keep the reference to f_back any longer than necessary. It
142 * may keep a chain of frames alive or it could create a reference
143 * cycle. */
144 assert(f->f_back == tstate->frame);
145 Py_CLEAR(f->f_back);
146
147 /* If the generator just returned (as opposed to yielding), signal
148 * that the generator is exhausted. */
149 if (result && f->f_stacktop == NULL) {
150 if (result == Py_None) {
151 /* Delay exception instantiation if we can */
152 PyErr_SetNone(PyExc_StopIteration);
153 } else {
154 PyObject *e = PyObject_CallFunctionObjArgs(
155 PyExc_StopIteration, result, NULL);
156 if (e != NULL) {
157 PyErr_SetObject(PyExc_StopIteration, e);
158 Py_DECREF(e);
159 }
160 }
161 Py_CLEAR(result);
162 }
Yury Selivanov68333392015-05-22 11:16:47 -0400163 else if (!result && PyErr_ExceptionMatches(PyExc_StopIteration)) {
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400164 /* Check for __future__ generator_stop and conditionally turn
165 * a leaking StopIteration into RuntimeError (with its cause
166 * set appropriately). */
Yury Selivanov68333392015-05-22 11:16:47 -0400167 if (((PyCodeObject *)gen->gi_code)->co_flags &
Yury Selivanov75445082015-05-11 22:57:16 -0400168 (CO_FUTURE_GENERATOR_STOP | CO_COROUTINE | CO_ITERABLE_COROUTINE))
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400169 {
170 PyObject *exc, *val, *val2, *tb;
Yury Selivanov5376ba92015-06-22 12:19:30 -0400171 char *msg = "generator raised StopIteration";
172 if (PyCoro_CheckExact(gen))
173 msg = "coroutine raised StopIteration";
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400174 PyErr_Fetch(&exc, &val, &tb);
175 PyErr_NormalizeException(&exc, &val, &tb);
176 if (tb != NULL)
177 PyException_SetTraceback(val, tb);
178 Py_DECREF(exc);
179 Py_XDECREF(tb);
Yury Selivanov5376ba92015-06-22 12:19:30 -0400180 PyErr_SetString(PyExc_RuntimeError, msg);
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400181 PyErr_Fetch(&exc, &val2, &tb);
182 PyErr_NormalizeException(&exc, &val2, &tb);
Yury Selivanov18c30a22015-05-10 15:09:46 -0400183 Py_INCREF(val);
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400184 PyException_SetCause(val2, val);
185 PyException_SetContext(val2, val);
186 PyErr_Restore(exc, val2, tb);
187 }
Yury Selivanov68333392015-05-22 11:16:47 -0400188 else {
189 PyObject *exc, *val, *tb;
190
191 /* Pop the exception before issuing a warning. */
192 PyErr_Fetch(&exc, &val, &tb);
193
194 if (PyErr_WarnFormat(PyExc_PendingDeprecationWarning, 1,
195 "generator '%.50S' raised StopIteration",
196 gen->gi_qualname)) {
197 /* Warning was converted to an error. */
198 Py_XDECREF(exc);
199 Py_XDECREF(val);
200 Py_XDECREF(tb);
201 }
202 else {
203 PyErr_Restore(exc, val, tb);
204 }
205 }
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400206 }
Antoine Pitrou93963562013-05-14 20:37:52 +0200207
208 if (!result || f->f_stacktop == NULL) {
209 /* generator can't be rerun, so release the frame */
210 /* first clean reference cycle through stored exception traceback */
211 PyObject *t, *v, *tb;
212 t = f->f_exc_type;
213 v = f->f_exc_value;
214 tb = f->f_exc_traceback;
215 f->f_exc_type = NULL;
216 f->f_exc_value = NULL;
217 f->f_exc_traceback = NULL;
218 Py_XDECREF(t);
219 Py_XDECREF(v);
220 Py_XDECREF(tb);
Antoine Pitrou58720d62013-08-05 23:26:40 +0200221 gen->gi_frame->f_gen = NULL;
Antoine Pitrou93963562013-05-14 20:37:52 +0200222 gen->gi_frame = NULL;
223 Py_DECREF(f);
224 }
225
226 return result;
Martin v. Löwise440e472004-06-01 15:22:42 +0000227}
228
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000229PyDoc_STRVAR(send_doc,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000230"send(arg) -> send 'arg' into generator,\n\
231return next yielded value or raise StopIteration.");
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000232
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500233PyObject *
234_PyGen_Send(PyGenObject *gen, PyObject *arg)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000235{
Yury Selivanov77c96812016-02-13 17:59:05 -0500236 return gen_send_ex(gen, arg, 0, 0);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000237}
238
239PyDoc_STRVAR(close_doc,
Benjamin Petersonab3da292012-05-03 18:44:09 -0400240"close() -> raise GeneratorExit inside generator.");
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000241
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000242/*
243 * This helper function is used by gen_close and gen_throw to
244 * close a subiterator being delegated to by yield-from.
245 */
246
Antoine Pitrou93963562013-05-14 20:37:52 +0200247static int
248gen_close_iter(PyObject *yf)
249{
250 PyObject *retval = NULL;
251 _Py_IDENTIFIER(close);
252
253 if (PyGen_CheckExact(yf)) {
254 retval = gen_close((PyGenObject *)yf, NULL);
255 if (retval == NULL)
256 return -1;
257 } else {
258 PyObject *meth = _PyObject_GetAttrId(yf, &PyId_close);
259 if (meth == NULL) {
260 if (!PyErr_ExceptionMatches(PyExc_AttributeError))
261 PyErr_WriteUnraisable(yf);
262 PyErr_Clear();
263 } else {
264 retval = PyObject_CallFunction(meth, "");
265 Py_DECREF(meth);
266 if (retval == NULL)
267 return -1;
268 }
269 }
270 Py_XDECREF(retval);
271 return 0;
272}
273
Yury Selivanovc724bae2016-03-02 11:30:46 -0500274PyObject *
275_PyGen_yf(PyGenObject *gen)
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500276{
Antoine Pitrou93963562013-05-14 20:37:52 +0200277 PyObject *yf = NULL;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500278 PyFrameObject *f = gen->gi_frame;
Antoine Pitrou93963562013-05-14 20:37:52 +0200279
280 if (f && f->f_stacktop) {
281 PyObject *bytecode = f->f_code->co_code;
282 unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode);
283
284 if (code[f->f_lasti + 1] != YIELD_FROM)
285 return NULL;
286 yf = f->f_stacktop[-1];
287 Py_INCREF(yf);
288 }
289
290 return yf;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500291}
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000292
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000293static PyObject *
294gen_close(PyGenObject *gen, PyObject *args)
295{
Antoine Pitrou93963562013-05-14 20:37:52 +0200296 PyObject *retval;
Yury Selivanovc724bae2016-03-02 11:30:46 -0500297 PyObject *yf = _PyGen_yf(gen);
Antoine Pitrou93963562013-05-14 20:37:52 +0200298 int err = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000299
Antoine Pitrou93963562013-05-14 20:37:52 +0200300 if (yf) {
301 gen->gi_running = 1;
302 err = gen_close_iter(yf);
303 gen->gi_running = 0;
304 Py_DECREF(yf);
305 }
306 if (err == 0)
307 PyErr_SetNone(PyExc_GeneratorExit);
Yury Selivanov77c96812016-02-13 17:59:05 -0500308 retval = gen_send_ex(gen, Py_None, 1, 1);
Antoine Pitrou93963562013-05-14 20:37:52 +0200309 if (retval) {
Yury Selivanov5376ba92015-06-22 12:19:30 -0400310 char *msg = "generator ignored GeneratorExit";
311 if (PyCoro_CheckExact(gen))
312 msg = "coroutine ignored GeneratorExit";
Antoine Pitrou93963562013-05-14 20:37:52 +0200313 Py_DECREF(retval);
Yury Selivanov5376ba92015-06-22 12:19:30 -0400314 PyErr_SetString(PyExc_RuntimeError, msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000315 return NULL;
316 }
Antoine Pitrou93963562013-05-14 20:37:52 +0200317 if (PyErr_ExceptionMatches(PyExc_StopIteration)
318 || PyErr_ExceptionMatches(PyExc_GeneratorExit)) {
319 PyErr_Clear(); /* ignore these errors */
320 Py_INCREF(Py_None);
321 return Py_None;
322 }
323 return NULL;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000324}
325
Antoine Pitrou93963562013-05-14 20:37:52 +0200326
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000327PyDoc_STRVAR(throw_doc,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000328"throw(typ[,val[,tb]]) -> raise exception in generator,\n\
329return next yielded value or raise StopIteration.");
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000330
331static PyObject *
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000332gen_throw(PyGenObject *gen, PyObject *args)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000333{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334 PyObject *typ;
335 PyObject *tb = NULL;
336 PyObject *val = NULL;
Yury Selivanovc724bae2016-03-02 11:30:46 -0500337 PyObject *yf = _PyGen_yf(gen);
Nick Coghlan5b0dac12012-06-17 15:45:11 +1000338 _Py_IDENTIFIER(throw);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000339
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000340 if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb))
341 return NULL;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000342
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000343 if (yf) {
344 PyObject *ret;
345 int err;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000346 if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit)) {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500347 gen->gi_running = 1;
Antoine Pitrou93963562013-05-14 20:37:52 +0200348 err = gen_close_iter(yf);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500349 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000350 Py_DECREF(yf);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000351 if (err < 0)
Yury Selivanov77c96812016-02-13 17:59:05 -0500352 return gen_send_ex(gen, Py_None, 1, 0);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000353 goto throw_here;
354 }
355 if (PyGen_CheckExact(yf)) {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500356 gen->gi_running = 1;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000357 ret = gen_throw((PyGenObject *)yf, args);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500358 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000359 } else {
Nick Coghlan5b0dac12012-06-17 15:45:11 +1000360 PyObject *meth = _PyObject_GetAttrId(yf, &PyId_throw);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000361 if (meth == NULL) {
362 if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
363 Py_DECREF(yf);
364 return NULL;
365 }
366 PyErr_Clear();
367 Py_DECREF(yf);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000368 goto throw_here;
369 }
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500370 gen->gi_running = 1;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000371 ret = PyObject_CallObject(meth, args);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500372 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000373 Py_DECREF(meth);
374 }
375 Py_DECREF(yf);
376 if (!ret) {
377 PyObject *val;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500378 /* Pop subiterator from stack */
379 ret = *(--gen->gi_frame->f_stacktop);
380 assert(ret == yf);
381 Py_DECREF(ret);
382 /* Termination repetition of YIELD_FROM */
383 gen->gi_frame->f_lasti++;
Nick Coghlanc40bc092012-06-17 15:15:49 +1000384 if (_PyGen_FetchStopIterationValue(&val) == 0) {
Yury Selivanov77c96812016-02-13 17:59:05 -0500385 ret = gen_send_ex(gen, val, 0, 0);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000386 Py_DECREF(val);
387 } else {
Yury Selivanov77c96812016-02-13 17:59:05 -0500388 ret = gen_send_ex(gen, Py_None, 1, 0);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000389 }
390 }
391 return ret;
392 }
393
394throw_here:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000395 /* First, check the traceback argument, replacing None with
396 NULL. */
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400397 if (tb == Py_None) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000398 tb = NULL;
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400399 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000400 else if (tb != NULL && !PyTraceBack_Check(tb)) {
401 PyErr_SetString(PyExc_TypeError,
402 "throw() third argument must be a traceback object");
403 return NULL;
404 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000405
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000406 Py_INCREF(typ);
407 Py_XINCREF(val);
408 Py_XINCREF(tb);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000409
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400410 if (PyExceptionClass_Check(typ))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000411 PyErr_NormalizeException(&typ, &val, &tb);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000413 else if (PyExceptionInstance_Check(typ)) {
414 /* Raising an instance. The value should be a dummy. */
415 if (val && val != Py_None) {
416 PyErr_SetString(PyExc_TypeError,
417 "instance exception may not have a separate value");
418 goto failed_throw;
419 }
420 else {
421 /* Normalize to raise <class>, <instance> */
422 Py_XDECREF(val);
423 val = typ;
424 typ = PyExceptionInstance_Class(typ);
425 Py_INCREF(typ);
Antoine Pitrou551ba202011-10-18 16:40:50 +0200426
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400427 if (tb == NULL)
Antoine Pitrou551ba202011-10-18 16:40:50 +0200428 /* Returns NULL if there's no traceback */
429 tb = PyException_GetTraceback(val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000430 }
431 }
432 else {
433 /* Not something you can raise. throw() fails. */
434 PyErr_Format(PyExc_TypeError,
435 "exceptions must be classes or instances "
436 "deriving from BaseException, not %s",
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000437 Py_TYPE(typ)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000438 goto failed_throw;
439 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000440
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000441 PyErr_Restore(typ, val, tb);
Yury Selivanov77c96812016-02-13 17:59:05 -0500442 return gen_send_ex(gen, Py_None, 1, 0);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000443
444failed_throw:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000445 /* Didn't use our arguments, so restore their original refcounts */
446 Py_DECREF(typ);
447 Py_XDECREF(val);
448 Py_XDECREF(tb);
449 return NULL;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000450}
451
452
453static PyObject *
454gen_iternext(PyGenObject *gen)
455{
Yury Selivanov77c96812016-02-13 17:59:05 -0500456 return gen_send_ex(gen, NULL, 0, 0);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000457}
458
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000459/*
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000460 * If StopIteration exception is set, fetches its 'value'
461 * attribute if any, otherwise sets pvalue to None.
462 *
463 * Returns 0 if no exception or StopIteration is set.
464 * If any other exception is set, returns -1 and leaves
465 * pvalue unchanged.
466 */
467
468int
Nick Coghlanc40bc092012-06-17 15:15:49 +1000469_PyGen_FetchStopIterationValue(PyObject **pvalue) {
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000470 PyObject *et, *ev, *tb;
471 PyObject *value = NULL;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500472
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000473 if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
474 PyErr_Fetch(&et, &ev, &tb);
Antoine Pitrou7403e912015-04-26 18:46:40 +0200475 if (ev) {
476 /* exception will usually be normalised already */
Serhiy Storchaka08d230a2015-05-22 11:02:49 +0300477 if (PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
Antoine Pitrou7403e912015-04-26 18:46:40 +0200478 value = ((PyStopIterationObject *)ev)->value;
479 Py_INCREF(value);
480 Py_DECREF(ev);
481 } else if (et == PyExc_StopIteration) {
482 /* avoid normalisation and take ev as value */
483 value = ev;
484 } else {
485 /* normalisation required */
486 PyErr_NormalizeException(&et, &ev, &tb);
Serhiy Storchaka08d230a2015-05-22 11:02:49 +0300487 if (!PyObject_TypeCheck(ev, (PyTypeObject *)PyExc_StopIteration)) {
Antoine Pitrou7403e912015-04-26 18:46:40 +0200488 PyErr_Restore(et, ev, tb);
489 return -1;
490 }
491 value = ((PyStopIterationObject *)ev)->value;
492 Py_INCREF(value);
493 Py_DECREF(ev);
494 }
495 }
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000496 Py_XDECREF(et);
497 Py_XDECREF(tb);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000498 } else if (PyErr_Occurred()) {
499 return -1;
500 }
501 if (value == NULL) {
502 value = Py_None;
Amaury Forgeot d'Arce557da82012-01-13 21:06:12 +0100503 Py_INCREF(value);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000504 }
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000505 *pvalue = value;
506 return 0;
507}
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000508
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000509static PyObject *
510gen_repr(PyGenObject *gen)
511{
Yury Selivanov5376ba92015-06-22 12:19:30 -0400512 return PyUnicode_FromFormat("<generator object %S at %p>",
513 gen->gi_qualname, gen);
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000514}
515
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000516static PyObject *
Victor Stinner40ee3012014-06-16 15:59:28 +0200517gen_get_name(PyGenObject *op)
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000518{
Victor Stinner40ee3012014-06-16 15:59:28 +0200519 Py_INCREF(op->gi_name);
520 return op->gi_name;
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000521}
522
Victor Stinner40ee3012014-06-16 15:59:28 +0200523static int
524gen_set_name(PyGenObject *op, PyObject *value)
525{
526 PyObject *tmp;
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000527
Victor Stinner40ee3012014-06-16 15:59:28 +0200528 /* Not legal to del gen.gi_name or to set it to anything
529 * other than a string object. */
530 if (value == NULL || !PyUnicode_Check(value)) {
531 PyErr_SetString(PyExc_TypeError,
532 "__name__ must be set to a string object");
533 return -1;
534 }
535 tmp = op->gi_name;
536 Py_INCREF(value);
537 op->gi_name = value;
538 Py_DECREF(tmp);
539 return 0;
540}
541
542static PyObject *
543gen_get_qualname(PyGenObject *op)
544{
545 Py_INCREF(op->gi_qualname);
546 return op->gi_qualname;
547}
548
549static int
550gen_set_qualname(PyGenObject *op, PyObject *value)
551{
552 PyObject *tmp;
553
554 /* Not legal to del gen.__qualname__ or to set it to anything
555 * other than a string object. */
556 if (value == NULL || !PyUnicode_Check(value)) {
557 PyErr_SetString(PyExc_TypeError,
558 "__qualname__ must be set to a string object");
559 return -1;
560 }
561 tmp = op->gi_qualname;
562 Py_INCREF(value);
563 op->gi_qualname = value;
564 Py_DECREF(tmp);
565 return 0;
566}
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000567
Yury Selivanove13f8f32015-07-03 00:23:30 -0400568static PyObject *
569gen_getyieldfrom(PyGenObject *gen)
570{
Yury Selivanovc724bae2016-03-02 11:30:46 -0500571 PyObject *yf = _PyGen_yf(gen);
Yury Selivanove13f8f32015-07-03 00:23:30 -0400572 if (yf == NULL)
573 Py_RETURN_NONE;
574 return yf;
575}
576
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000577static PyGetSetDef gen_getsetlist[] = {
Victor Stinner40ee3012014-06-16 15:59:28 +0200578 {"__name__", (getter)gen_get_name, (setter)gen_set_name,
579 PyDoc_STR("name of the generator")},
580 {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
581 PyDoc_STR("qualified name of the generator")},
Yury Selivanove13f8f32015-07-03 00:23:30 -0400582 {"gi_yieldfrom", (getter)gen_getyieldfrom, NULL,
583 PyDoc_STR("object being iterated by yield from, or None")},
Victor Stinner40ee3012014-06-16 15:59:28 +0200584 {NULL} /* Sentinel */
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000585};
586
Martin v. Löwise440e472004-06-01 15:22:42 +0000587static PyMemberDef gen_memberlist[] = {
Victor Stinner40ee3012014-06-16 15:59:28 +0200588 {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), READONLY},
589 {"gi_running", T_BOOL, offsetof(PyGenObject, gi_running), READONLY},
590 {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), READONLY},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 {NULL} /* Sentinel */
Martin v. Löwise440e472004-06-01 15:22:42 +0000592};
593
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000594static PyMethodDef gen_methods[] = {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500595 {"send",(PyCFunction)_PyGen_Send, METH_O, send_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000596 {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc},
597 {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc},
598 {NULL, NULL} /* Sentinel */
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000599};
600
Martin v. Löwise440e472004-06-01 15:22:42 +0000601PyTypeObject PyGen_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000602 PyVarObject_HEAD_INIT(&PyType_Type, 0)
603 "generator", /* tp_name */
604 sizeof(PyGenObject), /* tp_basicsize */
605 0, /* tp_itemsize */
606 /* methods */
607 (destructor)gen_dealloc, /* tp_dealloc */
608 0, /* tp_print */
609 0, /* tp_getattr */
610 0, /* tp_setattr */
Yury Selivanov75445082015-05-11 22:57:16 -0400611 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 (reprfunc)gen_repr, /* tp_repr */
613 0, /* tp_as_number */
614 0, /* tp_as_sequence */
615 0, /* tp_as_mapping */
616 0, /* tp_hash */
617 0, /* tp_call */
618 0, /* tp_str */
619 PyObject_GenericGetAttr, /* tp_getattro */
620 0, /* tp_setattro */
621 0, /* tp_as_buffer */
Antoine Pitrou796564c2013-07-30 19:59:21 +0200622 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
623 Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000624 0, /* tp_doc */
625 (traverseproc)gen_traverse, /* tp_traverse */
626 0, /* tp_clear */
627 0, /* tp_richcompare */
628 offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */
Yury Selivanov5376ba92015-06-22 12:19:30 -0400629 PyObject_SelfIter, /* tp_iter */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 (iternextfunc)gen_iternext, /* tp_iternext */
631 gen_methods, /* tp_methods */
632 gen_memberlist, /* tp_members */
633 gen_getsetlist, /* tp_getset */
634 0, /* tp_base */
635 0, /* tp_dict */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000636
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 0, /* tp_descr_get */
638 0, /* tp_descr_set */
639 0, /* tp_dictoffset */
640 0, /* tp_init */
641 0, /* tp_alloc */
642 0, /* tp_new */
643 0, /* tp_free */
644 0, /* tp_is_gc */
645 0, /* tp_bases */
646 0, /* tp_mro */
647 0, /* tp_cache */
648 0, /* tp_subclasses */
649 0, /* tp_weaklist */
Antoine Pitrou796564c2013-07-30 19:59:21 +0200650 0, /* tp_del */
651 0, /* tp_version_tag */
Antoine Pitrou58720d62013-08-05 23:26:40 +0200652 _PyGen_Finalize, /* tp_finalize */
Martin v. Löwise440e472004-06-01 15:22:42 +0000653};
654
Yury Selivanov5376ba92015-06-22 12:19:30 -0400655static PyObject *
656gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,
657 PyObject *name, PyObject *qualname)
Martin v. Löwise440e472004-06-01 15:22:42 +0000658{
Yury Selivanov5376ba92015-06-22 12:19:30 -0400659 PyGenObject *gen = PyObject_GC_New(PyGenObject, type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 if (gen == NULL) {
661 Py_DECREF(f);
662 return NULL;
663 }
664 gen->gi_frame = f;
Antoine Pitrou58720d62013-08-05 23:26:40 +0200665 f->f_gen = (PyObject *) gen;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 Py_INCREF(f->f_code);
667 gen->gi_code = (PyObject *)(f->f_code);
668 gen->gi_running = 0;
669 gen->gi_weakreflist = NULL;
Victor Stinner40ee3012014-06-16 15:59:28 +0200670 if (name != NULL)
671 gen->gi_name = name;
672 else
673 gen->gi_name = ((PyCodeObject *)gen->gi_code)->co_name;
674 Py_INCREF(gen->gi_name);
675 if (qualname != NULL)
676 gen->gi_qualname = qualname;
677 else
678 gen->gi_qualname = gen->gi_name;
679 Py_INCREF(gen->gi_qualname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000680 _PyObject_GC_TRACK(gen);
681 return (PyObject *)gen;
Martin v. Löwise440e472004-06-01 15:22:42 +0000682}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000683
Victor Stinner40ee3012014-06-16 15:59:28 +0200684PyObject *
Yury Selivanov5376ba92015-06-22 12:19:30 -0400685PyGen_NewWithQualName(PyFrameObject *f, PyObject *name, PyObject *qualname)
686{
687 return gen_new_with_qualname(&PyGen_Type, f, name, qualname);
688}
689
690PyObject *
Victor Stinner40ee3012014-06-16 15:59:28 +0200691PyGen_New(PyFrameObject *f)
692{
Yury Selivanov5376ba92015-06-22 12:19:30 -0400693 return gen_new_with_qualname(&PyGen_Type, f, NULL, NULL);
Victor Stinner40ee3012014-06-16 15:59:28 +0200694}
695
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000696int
697PyGen_NeedsFinalizing(PyGenObject *gen)
698{
Antoine Pitrou93963562013-05-14 20:37:52 +0200699 int i;
700 PyFrameObject *f = gen->gi_frame;
701
702 if (f == NULL || f->f_stacktop == NULL)
703 return 0; /* no frame or empty blockstack == no finalization */
704
705 /* Any block type besides a loop requires cleanup. */
706 for (i = 0; i < f->f_iblock; i++)
707 if (f->f_blockstack[i].b_type != SETUP_LOOP)
708 return 1;
709
710 /* No blocks except loops, it's safe to skip finalization. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000711 return 0;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000712}
Yury Selivanov75445082015-05-11 22:57:16 -0400713
Yury Selivanov5376ba92015-06-22 12:19:30 -0400714/* Coroutine Object */
715
716typedef struct {
717 PyObject_HEAD
718 PyCoroObject *cw_coroutine;
719} PyCoroWrapper;
720
721static int
722gen_is_coroutine(PyObject *o)
723{
724 if (PyGen_CheckExact(o)) {
725 PyCodeObject *code = (PyCodeObject *)((PyGenObject*)o)->gi_code;
726 if (code->co_flags & CO_ITERABLE_COROUTINE) {
727 return 1;
728 }
729 }
730 return 0;
731}
732
Yury Selivanov75445082015-05-11 22:57:16 -0400733/*
734 * This helper function returns an awaitable for `o`:
735 * - `o` if `o` is a coroutine-object;
736 * - `type(o)->tp_as_async->am_await(o)`
737 *
738 * Raises a TypeError if it's not possible to return
739 * an awaitable and returns NULL.
740 */
741PyObject *
Yury Selivanov5376ba92015-06-22 12:19:30 -0400742_PyCoro_GetAwaitableIter(PyObject *o)
Yury Selivanov75445082015-05-11 22:57:16 -0400743{
Yury Selivanov6ef05902015-05-28 11:21:31 -0400744 unaryfunc getter = NULL;
Yury Selivanov75445082015-05-11 22:57:16 -0400745 PyTypeObject *ot;
746
Yury Selivanov5376ba92015-06-22 12:19:30 -0400747 if (PyCoro_CheckExact(o) || gen_is_coroutine(o)) {
748 /* 'o' is a coroutine. */
Yury Selivanov75445082015-05-11 22:57:16 -0400749 Py_INCREF(o);
750 return o;
751 }
752
753 ot = Py_TYPE(o);
754 if (ot->tp_as_async != NULL) {
755 getter = ot->tp_as_async->am_await;
756 }
757 if (getter != NULL) {
758 PyObject *res = (*getter)(o);
759 if (res != NULL) {
Yury Selivanov5376ba92015-06-22 12:19:30 -0400760 if (PyCoro_CheckExact(res) || gen_is_coroutine(res)) {
761 /* __await__ must return an *iterator*, not
762 a coroutine or another awaitable (see PEP 492) */
763 PyErr_SetString(PyExc_TypeError,
764 "__await__() returned a coroutine");
765 Py_CLEAR(res);
766 } else if (!PyIter_Check(res)) {
Yury Selivanov75445082015-05-11 22:57:16 -0400767 PyErr_Format(PyExc_TypeError,
768 "__await__() returned non-iterator "
769 "of type '%.100s'",
770 Py_TYPE(res)->tp_name);
771 Py_CLEAR(res);
772 }
Yury Selivanov75445082015-05-11 22:57:16 -0400773 }
774 return res;
775 }
776
777 PyErr_Format(PyExc_TypeError,
778 "object %.100s can't be used in 'await' expression",
779 ot->tp_name);
Yury Selivanov75445082015-05-11 22:57:16 -0400780 return NULL;
781}
Yury Selivanov5376ba92015-06-22 12:19:30 -0400782
783static PyObject *
784coro_repr(PyCoroObject *coro)
785{
786 return PyUnicode_FromFormat("<coroutine object %S at %p>",
787 coro->cr_qualname, coro);
788}
789
790static PyObject *
791coro_await(PyCoroObject *coro)
792{
793 PyCoroWrapper *cw = PyObject_GC_New(PyCoroWrapper, &_PyCoroWrapper_Type);
794 if (cw == NULL) {
795 return NULL;
796 }
797 Py_INCREF(coro);
798 cw->cw_coroutine = coro;
799 _PyObject_GC_TRACK(cw);
800 return (PyObject *)cw;
801}
802
Yury Selivanove13f8f32015-07-03 00:23:30 -0400803static PyObject *
804coro_get_cr_await(PyCoroObject *coro)
805{
Yury Selivanovc724bae2016-03-02 11:30:46 -0500806 PyObject *yf = _PyGen_yf((PyGenObject *) coro);
Yury Selivanove13f8f32015-07-03 00:23:30 -0400807 if (yf == NULL)
808 Py_RETURN_NONE;
809 return yf;
810}
811
Yury Selivanov5376ba92015-06-22 12:19:30 -0400812static PyGetSetDef coro_getsetlist[] = {
813 {"__name__", (getter)gen_get_name, (setter)gen_set_name,
814 PyDoc_STR("name of the coroutine")},
815 {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
816 PyDoc_STR("qualified name of the coroutine")},
Yury Selivanove13f8f32015-07-03 00:23:30 -0400817 {"cr_await", (getter)coro_get_cr_await, NULL,
818 PyDoc_STR("object being awaited on, or None")},
Yury Selivanov5376ba92015-06-22 12:19:30 -0400819 {NULL} /* Sentinel */
820};
821
822static PyMemberDef coro_memberlist[] = {
823 {"cr_frame", T_OBJECT, offsetof(PyCoroObject, cr_frame), READONLY},
824 {"cr_running", T_BOOL, offsetof(PyCoroObject, cr_running), READONLY},
825 {"cr_code", T_OBJECT, offsetof(PyCoroObject, cr_code), READONLY},
826 {NULL} /* Sentinel */
827};
828
829PyDoc_STRVAR(coro_send_doc,
830"send(arg) -> send 'arg' into coroutine,\n\
Yury Selivanov66f88282015-06-24 11:04:15 -0400831return next iterated value or raise StopIteration.");
Yury Selivanov5376ba92015-06-22 12:19:30 -0400832
833PyDoc_STRVAR(coro_throw_doc,
834"throw(typ[,val[,tb]]) -> raise exception in coroutine,\n\
Yury Selivanov66f88282015-06-24 11:04:15 -0400835return next iterated value or raise StopIteration.");
Yury Selivanov5376ba92015-06-22 12:19:30 -0400836
837PyDoc_STRVAR(coro_close_doc,
838"close() -> raise GeneratorExit inside coroutine.");
839
840static PyMethodDef coro_methods[] = {
841 {"send",(PyCFunction)_PyGen_Send, METH_O, coro_send_doc},
842 {"throw",(PyCFunction)gen_throw, METH_VARARGS, coro_throw_doc},
843 {"close",(PyCFunction)gen_close, METH_NOARGS, coro_close_doc},
844 {NULL, NULL} /* Sentinel */
845};
846
847static PyAsyncMethods coro_as_async = {
848 (unaryfunc)coro_await, /* am_await */
849 0, /* am_aiter */
850 0 /* am_anext */
851};
852
853PyTypeObject PyCoro_Type = {
854 PyVarObject_HEAD_INIT(&PyType_Type, 0)
855 "coroutine", /* tp_name */
856 sizeof(PyCoroObject), /* tp_basicsize */
857 0, /* tp_itemsize */
858 /* methods */
859 (destructor)gen_dealloc, /* tp_dealloc */
860 0, /* tp_print */
861 0, /* tp_getattr */
862 0, /* tp_setattr */
863 &coro_as_async, /* tp_as_async */
864 (reprfunc)coro_repr, /* tp_repr */
865 0, /* tp_as_number */
866 0, /* tp_as_sequence */
867 0, /* tp_as_mapping */
868 0, /* tp_hash */
869 0, /* tp_call */
870 0, /* tp_str */
871 PyObject_GenericGetAttr, /* tp_getattro */
872 0, /* tp_setattro */
873 0, /* tp_as_buffer */
874 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
875 Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
876 0, /* tp_doc */
877 (traverseproc)gen_traverse, /* tp_traverse */
878 0, /* tp_clear */
879 0, /* tp_richcompare */
880 offsetof(PyCoroObject, cr_weakreflist), /* tp_weaklistoffset */
881 0, /* tp_iter */
882 0, /* tp_iternext */
883 coro_methods, /* tp_methods */
884 coro_memberlist, /* tp_members */
885 coro_getsetlist, /* tp_getset */
886 0, /* tp_base */
887 0, /* tp_dict */
888 0, /* tp_descr_get */
889 0, /* tp_descr_set */
890 0, /* tp_dictoffset */
891 0, /* tp_init */
892 0, /* tp_alloc */
893 0, /* tp_new */
894 0, /* tp_free */
895 0, /* tp_is_gc */
896 0, /* tp_bases */
897 0, /* tp_mro */
898 0, /* tp_cache */
899 0, /* tp_subclasses */
900 0, /* tp_weaklist */
901 0, /* tp_del */
902 0, /* tp_version_tag */
903 _PyGen_Finalize, /* tp_finalize */
904};
905
906static void
907coro_wrapper_dealloc(PyCoroWrapper *cw)
908{
909 _PyObject_GC_UNTRACK((PyObject *)cw);
910 Py_CLEAR(cw->cw_coroutine);
911 PyObject_GC_Del(cw);
912}
913
914static PyObject *
915coro_wrapper_iternext(PyCoroWrapper *cw)
916{
Yury Selivanov77c96812016-02-13 17:59:05 -0500917 return gen_send_ex((PyGenObject *)cw->cw_coroutine, NULL, 0, 0);
Yury Selivanov5376ba92015-06-22 12:19:30 -0400918}
919
920static PyObject *
921coro_wrapper_send(PyCoroWrapper *cw, PyObject *arg)
922{
Yury Selivanov77c96812016-02-13 17:59:05 -0500923 return gen_send_ex((PyGenObject *)cw->cw_coroutine, arg, 0, 0);
Yury Selivanov5376ba92015-06-22 12:19:30 -0400924}
925
926static PyObject *
927coro_wrapper_throw(PyCoroWrapper *cw, PyObject *args)
928{
929 return gen_throw((PyGenObject *)cw->cw_coroutine, args);
930}
931
932static PyObject *
933coro_wrapper_close(PyCoroWrapper *cw, PyObject *args)
934{
935 return gen_close((PyGenObject *)cw->cw_coroutine, args);
936}
937
938static int
939coro_wrapper_traverse(PyCoroWrapper *cw, visitproc visit, void *arg)
940{
941 Py_VISIT((PyObject *)cw->cw_coroutine);
942 return 0;
943}
944
945static PyMethodDef coro_wrapper_methods[] = {
Yury Selivanov66f88282015-06-24 11:04:15 -0400946 {"send",(PyCFunction)coro_wrapper_send, METH_O, coro_send_doc},
947 {"throw",(PyCFunction)coro_wrapper_throw, METH_VARARGS, coro_throw_doc},
948 {"close",(PyCFunction)coro_wrapper_close, METH_NOARGS, coro_close_doc},
Yury Selivanov5376ba92015-06-22 12:19:30 -0400949 {NULL, NULL} /* Sentinel */
950};
951
952PyTypeObject _PyCoroWrapper_Type = {
953 PyVarObject_HEAD_INIT(&PyType_Type, 0)
954 "coroutine_wrapper",
955 sizeof(PyCoroWrapper), /* tp_basicsize */
956 0, /* tp_itemsize */
957 (destructor)coro_wrapper_dealloc, /* destructor tp_dealloc */
958 0, /* tp_print */
959 0, /* tp_getattr */
960 0, /* tp_setattr */
961 0, /* tp_as_async */
962 0, /* tp_repr */
963 0, /* tp_as_number */
964 0, /* tp_as_sequence */
965 0, /* tp_as_mapping */
966 0, /* tp_hash */
967 0, /* tp_call */
968 0, /* tp_str */
969 PyObject_GenericGetAttr, /* tp_getattro */
970 0, /* tp_setattro */
971 0, /* tp_as_buffer */
972 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
973 "A wrapper object implementing __await__ for coroutines.",
974 (traverseproc)coro_wrapper_traverse, /* tp_traverse */
975 0, /* tp_clear */
976 0, /* tp_richcompare */
977 0, /* tp_weaklistoffset */
978 PyObject_SelfIter, /* tp_iter */
979 (iternextfunc)coro_wrapper_iternext, /* tp_iternext */
980 coro_wrapper_methods, /* tp_methods */
981 0, /* tp_members */
982 0, /* tp_getset */
983 0, /* tp_base */
984 0, /* tp_dict */
985 0, /* tp_descr_get */
986 0, /* tp_descr_set */
987 0, /* tp_dictoffset */
988 0, /* tp_init */
989 0, /* tp_alloc */
990 0, /* tp_new */
991 PyObject_Del, /* tp_free */
992};
993
994PyObject *
995PyCoro_New(PyFrameObject *f, PyObject *name, PyObject *qualname)
996{
997 return gen_new_with_qualname(&PyCoro_Type, f, name, qualname);
998}
Yury Selivanova6f6edb2016-06-09 15:08:31 -0400999
1000
1001/* __aiter__ wrapper; see http://bugs.python.org/issue27243 for details. */
1002
1003typedef struct {
1004 PyObject_HEAD
1005 PyObject *aw_aiter;
1006} PyAIterWrapper;
1007
1008
1009static PyObject *
1010aiter_wrapper_iternext(PyAIterWrapper *aw)
1011{
1012 PyErr_SetObject(PyExc_StopIteration, aw->aw_aiter);
1013 return NULL;
1014}
1015
1016static int
1017aiter_wrapper_traverse(PyAIterWrapper *aw, visitproc visit, void *arg)
1018{
1019 Py_VISIT((PyObject *)aw->aw_aiter);
1020 return 0;
1021}
1022
1023static void
1024aiter_wrapper_dealloc(PyAIterWrapper *aw)
1025{
1026 _PyObject_GC_UNTRACK((PyObject *)aw);
1027 Py_CLEAR(aw->aw_aiter);
1028 PyObject_GC_Del(aw);
1029}
1030
1031static PyAsyncMethods aiter_wrapper_as_async = {
1032 PyObject_SelfIter, /* am_await */
1033 0, /* am_aiter */
1034 0 /* am_anext */
1035};
1036
1037PyTypeObject _PyAIterWrapper_Type = {
1038 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1039 "aiter_wrapper",
1040 sizeof(PyAIterWrapper), /* tp_basicsize */
1041 0, /* tp_itemsize */
1042 (destructor)aiter_wrapper_dealloc, /* destructor tp_dealloc */
1043 0, /* tp_print */
1044 0, /* tp_getattr */
1045 0, /* tp_setattr */
1046 &aiter_wrapper_as_async, /* tp_as_async */
1047 0, /* tp_repr */
1048 0, /* tp_as_number */
1049 0, /* tp_as_sequence */
1050 0, /* tp_as_mapping */
1051 0, /* tp_hash */
1052 0, /* tp_call */
1053 0, /* tp_str */
1054 PyObject_GenericGetAttr, /* tp_getattro */
1055 0, /* tp_setattro */
1056 0, /* tp_as_buffer */
1057 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1058 "A wrapper object for __aiter__ bakwards compatibility.",
1059 (traverseproc)aiter_wrapper_traverse, /* tp_traverse */
1060 0, /* tp_clear */
1061 0, /* tp_richcompare */
1062 0, /* tp_weaklistoffset */
1063 PyObject_SelfIter, /* tp_iter */
1064 (iternextfunc)aiter_wrapper_iternext, /* tp_iternext */
1065 0, /* tp_methods */
1066 0, /* tp_members */
1067 0, /* tp_getset */
1068 0, /* tp_base */
1069 0, /* tp_dict */
1070 0, /* tp_descr_get */
1071 0, /* tp_descr_set */
1072 0, /* tp_dictoffset */
1073 0, /* tp_init */
1074 0, /* tp_alloc */
1075 0, /* tp_new */
1076 PyObject_Del, /* tp_free */
1077};
1078
1079
1080PyObject *
1081_PyAIterWrapper_New(PyObject *aiter)
1082{
1083 PyAIterWrapper *aw = PyObject_GC_New(PyAIterWrapper,
1084 &_PyAIterWrapper_Type);
1085 if (aw == NULL) {
1086 return NULL;
1087 }
1088 Py_INCREF(aiter);
1089 aw->aw_aiter = aiter;
1090 _PyObject_GC_TRACK(aw);
1091 return (PyObject *)aw;
1092}