blob: bc5309a82a4ef3c3cc0437b379f9c4c1c046f7fb [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
Yury Selivanoveb636452016-09-08 22:01:51 -07008static PyObject *gen_close(PyGenObject *, PyObject *);
9static PyObject *async_gen_asend_new(PyAsyncGenObject *, PyObject *);
10static PyObject *async_gen_athrow_new(PyAsyncGenObject *, PyObject *);
11
12static char *NON_INIT_CORO_MSG = "can't send non-None value to a "
13 "just-started coroutine";
14
15static char *ASYNC_GEN_IGNORED_EXIT_MSG =
16 "async generator ignored GeneratorExit";
Nick Coghlan1f7ce622012-01-13 21:43:40 +100017
Martin v. Löwise440e472004-06-01 15:22:42 +000018static int
19gen_traverse(PyGenObject *gen, visitproc visit, void *arg)
20{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000021 Py_VISIT((PyObject *)gen->gi_frame);
22 Py_VISIT(gen->gi_code);
Victor Stinner40ee3012014-06-16 15:59:28 +020023 Py_VISIT(gen->gi_name);
24 Py_VISIT(gen->gi_qualname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000025 return 0;
Martin v. Löwise440e472004-06-01 15:22:42 +000026}
27
Antoine Pitrou58720d62013-08-05 23:26:40 +020028void
29_PyGen_Finalize(PyObject *self)
Antoine Pitrou796564c2013-07-30 19:59:21 +020030{
31 PyGenObject *gen = (PyGenObject *)self;
Benjamin Petersonb88db872016-09-07 08:46:59 -070032 PyObject *res = NULL;
Antoine Pitrou796564c2013-07-30 19:59:21 +020033 PyObject *error_type, *error_value, *error_traceback;
34
35 if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL)
36 /* Generator isn't paused, so no need to close */
37 return;
38
Yury Selivanoveb636452016-09-08 22:01:51 -070039 if (PyAsyncGen_CheckExact(self)) {
40 PyAsyncGenObject *agen = (PyAsyncGenObject*)self;
41 PyObject *finalizer = agen->ag_finalizer;
42 if (finalizer && !agen->ag_closed) {
43 /* Save the current exception, if any. */
44 PyErr_Fetch(&error_type, &error_value, &error_traceback);
45
46 res = PyObject_CallFunctionObjArgs(finalizer, self, NULL);
47
48 if (res == NULL) {
49 PyErr_WriteUnraisable(self);
50 } else {
51 Py_DECREF(res);
52 }
53 /* Restore the saved exception. */
54 PyErr_Restore(error_type, error_value, error_traceback);
55 return;
56 }
57 }
58
Antoine Pitrou796564c2013-07-30 19:59:21 +020059 /* Save the current exception, if any. */
60 PyErr_Fetch(&error_type, &error_value, &error_traceback);
61
Benjamin Peterson2f40ed42016-09-05 10:14:54 -070062 /* If `gen` is a coroutine, and if it was never awaited on,
63 issue a RuntimeWarning. */
Benjamin Petersonb88db872016-09-07 08:46:59 -070064 if (gen->gi_code != NULL &&
65 ((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE &&
66 gen->gi_frame->f_lasti == -1) {
67 if (!error_value) {
68 PyErr_WarnFormat(PyExc_RuntimeWarning, 1,
69 "coroutine '%.50S' was never awaited",
70 gen->gi_qualname);
71 }
Benjamin Peterson2f40ed42016-09-05 10:14:54 -070072 }
73 else {
74 res = gen_close(gen, NULL);
75 }
Antoine Pitrou796564c2013-07-30 19:59:21 +020076
Benjamin Petersonb88db872016-09-07 08:46:59 -070077 if (res == NULL) {
78 if (PyErr_Occurred())
79 PyErr_WriteUnraisable(self);
80 }
81 else {
Antoine Pitrou796564c2013-07-30 19:59:21 +020082 Py_DECREF(res);
Benjamin Petersonb88db872016-09-07 08:46:59 -070083 }
Antoine Pitrou796564c2013-07-30 19:59:21 +020084
85 /* Restore the saved exception. */
86 PyErr_Restore(error_type, error_value, error_traceback);
87}
88
89static void
Martin v. Löwise440e472004-06-01 15:22:42 +000090gen_dealloc(PyGenObject *gen)
91{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000092 PyObject *self = (PyObject *) gen;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000093
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000094 _PyObject_GC_UNTRACK(gen);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000095
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000096 if (gen->gi_weakreflist != NULL)
97 PyObject_ClearWeakRefs(self);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000098
Antoine Pitrou93963562013-05-14 20:37:52 +020099 _PyObject_GC_TRACK(self);
100
Antoine Pitrou796564c2013-07-30 19:59:21 +0200101 if (PyObject_CallFinalizerFromDealloc(self))
102 return; /* resurrected. :( */
Antoine Pitrou93963562013-05-14 20:37:52 +0200103
104 _PyObject_GC_UNTRACK(self);
Yury Selivanoveb636452016-09-08 22:01:51 -0700105 if (PyAsyncGen_CheckExact(gen)) {
106 /* We have to handle this case for asynchronous generators
107 right here, because this code has to be between UNTRACK
108 and GC_Del. */
109 Py_CLEAR(((PyAsyncGenObject*)gen)->ag_finalizer);
110 }
Benjamin Petersonbdddb112016-09-05 10:39:57 -0700111 if (gen->gi_frame != NULL) {
112 gen->gi_frame->f_gen = NULL;
113 Py_CLEAR(gen->gi_frame);
114 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000115 Py_CLEAR(gen->gi_code);
Victor Stinner40ee3012014-06-16 15:59:28 +0200116 Py_CLEAR(gen->gi_name);
117 Py_CLEAR(gen->gi_qualname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000118 PyObject_GC_Del(gen);
Martin v. Löwise440e472004-06-01 15:22:42 +0000119}
120
Yury Selivanoveb636452016-09-08 22:01:51 -0700121static void
122gen_chain_runtime_error(const char *msg)
123{
124 PyObject *exc, *val, *val2, *tb;
125
126 /* TODO: This about rewriting using _PyErr_ChainExceptions. */
127
128 PyErr_Fetch(&exc, &val, &tb);
129 PyErr_NormalizeException(&exc, &val, &tb);
130 if (tb != NULL) {
131 PyException_SetTraceback(val, tb);
132 }
133
134 Py_DECREF(exc);
135 Py_XDECREF(tb);
136
137 PyErr_SetString(PyExc_RuntimeError, msg);
138 PyErr_Fetch(&exc, &val2, &tb);
139 PyErr_NormalizeException(&exc, &val2, &tb);
140
141 Py_INCREF(val);
142 PyException_SetCause(val2, val);
143 PyException_SetContext(val2, val);
144
145 PyErr_Restore(exc, val2, tb);
146}
147
Martin v. Löwise440e472004-06-01 15:22:42 +0000148static PyObject *
Yury Selivanov77c96812016-02-13 17:59:05 -0500149gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
Martin v. Löwise440e472004-06-01 15:22:42 +0000150{
Antoine Pitrou93963562013-05-14 20:37:52 +0200151 PyThreadState *tstate = PyThreadState_GET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000152 PyFrameObject *f = gen->gi_frame;
Antoine Pitrou93963562013-05-14 20:37:52 +0200153 PyObject *result;
Martin v. Löwise440e472004-06-01 15:22:42 +0000154
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500155 if (gen->gi_running) {
Yury Selivanov5376ba92015-06-22 12:19:30 -0400156 char *msg = "generator already executing";
Yury Selivanoveb636452016-09-08 22:01:51 -0700157 if (PyCoro_CheckExact(gen)) {
Yury Selivanov5376ba92015-06-22 12:19:30 -0400158 msg = "coroutine already executing";
Yury Selivanoveb636452016-09-08 22:01:51 -0700159 }
160 else if (PyAsyncGen_CheckExact(gen)) {
161 msg = "async generator already executing";
162 }
Yury Selivanov5376ba92015-06-22 12:19:30 -0400163 PyErr_SetString(PyExc_ValueError, msg);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500164 return NULL;
165 }
Antoine Pitrou93963562013-05-14 20:37:52 +0200166 if (f == NULL || f->f_stacktop == NULL) {
Yury Selivanov77c96812016-02-13 17:59:05 -0500167 if (PyCoro_CheckExact(gen) && !closing) {
168 /* `gen` is an exhausted coroutine: raise an error,
169 except when called from gen_close(), which should
170 always be a silent method. */
171 PyErr_SetString(
172 PyExc_RuntimeError,
173 "cannot reuse already awaited coroutine");
Yury Selivanoveb636452016-09-08 22:01:51 -0700174 }
175 else if (arg && !exc) {
Yury Selivanov77c96812016-02-13 17:59:05 -0500176 /* `gen` is an exhausted generator:
177 only set exception if called from send(). */
Yury Selivanoveb636452016-09-08 22:01:51 -0700178 if (PyAsyncGen_CheckExact(gen)) {
179 PyErr_SetNone(PyExc_StopAsyncIteration);
180 }
181 else {
182 PyErr_SetNone(PyExc_StopIteration);
183 }
Yury Selivanov77c96812016-02-13 17:59:05 -0500184 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000185 return NULL;
186 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000187
Antoine Pitrou93963562013-05-14 20:37:52 +0200188 if (f->f_lasti == -1) {
189 if (arg && arg != Py_None) {
Yury Selivanov5376ba92015-06-22 12:19:30 -0400190 char *msg = "can't send non-None value to a "
191 "just-started generator";
Yury Selivanoveb636452016-09-08 22:01:51 -0700192 if (PyCoro_CheckExact(gen)) {
193 msg = NON_INIT_CORO_MSG;
194 }
195 else if (PyAsyncGen_CheckExact(gen)) {
Yury Selivanov5376ba92015-06-22 12:19:30 -0400196 msg = "can't send non-None value to a "
Yury Selivanoveb636452016-09-08 22:01:51 -0700197 "just-started async generator";
198 }
Yury Selivanov5376ba92015-06-22 12:19:30 -0400199 PyErr_SetString(PyExc_TypeError, msg);
Antoine Pitrou93963562013-05-14 20:37:52 +0200200 return NULL;
201 }
202 } else {
203 /* Push arg onto the frame's value stack */
204 result = arg ? arg : Py_None;
205 Py_INCREF(result);
206 *(f->f_stacktop++) = result;
207 }
208
209 /* Generators always return to their most recent caller, not
210 * necessarily their creator. */
211 Py_XINCREF(tstate->frame);
212 assert(f->f_back == NULL);
213 f->f_back = tstate->frame;
214
215 gen->gi_running = 1;
216 result = PyEval_EvalFrameEx(f, exc);
217 gen->gi_running = 0;
218
219 /* Don't keep the reference to f_back any longer than necessary. It
220 * may keep a chain of frames alive or it could create a reference
221 * cycle. */
222 assert(f->f_back == tstate->frame);
223 Py_CLEAR(f->f_back);
224
225 /* If the generator just returned (as opposed to yielding), signal
226 * that the generator is exhausted. */
227 if (result && f->f_stacktop == NULL) {
228 if (result == Py_None) {
229 /* Delay exception instantiation if we can */
Yury Selivanoveb636452016-09-08 22:01:51 -0700230 if (PyAsyncGen_CheckExact(gen)) {
231 PyErr_SetNone(PyExc_StopAsyncIteration);
232 }
233 else {
234 PyErr_SetNone(PyExc_StopIteration);
235 }
236 }
237 else {
Antoine Pitrou93963562013-05-14 20:37:52 +0200238 PyObject *e = PyObject_CallFunctionObjArgs(
239 PyExc_StopIteration, result, NULL);
Yury Selivanoveb636452016-09-08 22:01:51 -0700240
241 /* Async generators cannot return anything but None */
242 assert(!PyAsyncGen_CheckExact(gen));
243
Antoine Pitrou93963562013-05-14 20:37:52 +0200244 if (e != NULL) {
245 PyErr_SetObject(PyExc_StopIteration, e);
246 Py_DECREF(e);
247 }
248 }
249 Py_CLEAR(result);
250 }
Yury Selivanov68333392015-05-22 11:16:47 -0400251 else if (!result && PyErr_ExceptionMatches(PyExc_StopIteration)) {
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400252 /* Check for __future__ generator_stop and conditionally turn
253 * a leaking StopIteration into RuntimeError (with its cause
254 * set appropriately). */
Yury Selivanoveb636452016-09-08 22:01:51 -0700255
256 const int check_stop_iter_error_flags = CO_FUTURE_GENERATOR_STOP |
257 CO_COROUTINE |
258 CO_ITERABLE_COROUTINE |
259 CO_ASYNC_GENERATOR;
260
261 if (gen->gi_code != NULL &&
262 ((PyCodeObject *)gen->gi_code)->co_flags &
263 check_stop_iter_error_flags)
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400264 {
Yury Selivanoveb636452016-09-08 22:01:51 -0700265 /* `gen` is either:
266 * a generator with CO_FUTURE_GENERATOR_STOP flag;
267 * a coroutine;
268 * a generator with CO_ITERABLE_COROUTINE flag
269 (decorated with types.coroutine decorator);
270 * an async generator.
271 */
272 const char *msg = "generator raised StopIteration";
273 if (PyCoro_CheckExact(gen)) {
Yury Selivanov5376ba92015-06-22 12:19:30 -0400274 msg = "coroutine raised StopIteration";
Yury Selivanoveb636452016-09-08 22:01:51 -0700275 }
276 else if PyAsyncGen_CheckExact(gen) {
277 msg = "async generator raised StopIteration";
278 }
279 /* Raise a RuntimeError */
280 gen_chain_runtime_error(msg);
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400281 }
Yury Selivanov68333392015-05-22 11:16:47 -0400282 else {
Yury Selivanoveb636452016-09-08 22:01:51 -0700283 /* `gen` is an ordinary generator without
284 CO_FUTURE_GENERATOR_STOP flag.
285 */
286
Yury Selivanov68333392015-05-22 11:16:47 -0400287 PyObject *exc, *val, *tb;
288
289 /* Pop the exception before issuing a warning. */
290 PyErr_Fetch(&exc, &val, &tb);
291
Martin Panter7e3a91a2016-02-10 04:40:48 +0000292 if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
Yury Selivanov68333392015-05-22 11:16:47 -0400293 "generator '%.50S' raised StopIteration",
294 gen->gi_qualname)) {
295 /* Warning was converted to an error. */
296 Py_XDECREF(exc);
297 Py_XDECREF(val);
298 Py_XDECREF(tb);
299 }
300 else {
301 PyErr_Restore(exc, val, tb);
302 }
303 }
Yury Selivanov8170e8c2015-05-09 11:44:30 -0400304 }
Yury Selivanoveb636452016-09-08 22:01:51 -0700305 else if (PyAsyncGen_CheckExact(gen) && !result &&
306 PyErr_ExceptionMatches(PyExc_StopAsyncIteration))
307 {
308 /* code in `gen` raised a StopAsyncIteration error:
309 raise a RuntimeError.
310 */
311 const char *msg = "async generator raised StopAsyncIteration";
312 gen_chain_runtime_error(msg);
313 }
Antoine Pitrou93963562013-05-14 20:37:52 +0200314
315 if (!result || f->f_stacktop == NULL) {
316 /* generator can't be rerun, so release the frame */
317 /* first clean reference cycle through stored exception traceback */
318 PyObject *t, *v, *tb;
319 t = f->f_exc_type;
320 v = f->f_exc_value;
321 tb = f->f_exc_traceback;
322 f->f_exc_type = NULL;
323 f->f_exc_value = NULL;
324 f->f_exc_traceback = NULL;
325 Py_XDECREF(t);
326 Py_XDECREF(v);
327 Py_XDECREF(tb);
Antoine Pitrou58720d62013-08-05 23:26:40 +0200328 gen->gi_frame->f_gen = NULL;
Antoine Pitrou93963562013-05-14 20:37:52 +0200329 gen->gi_frame = NULL;
330 Py_DECREF(f);
331 }
332
333 return result;
Martin v. Löwise440e472004-06-01 15:22:42 +0000334}
335
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000336PyDoc_STRVAR(send_doc,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000337"send(arg) -> send 'arg' into generator,\n\
338return next yielded value or raise StopIteration.");
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000339
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500340PyObject *
341_PyGen_Send(PyGenObject *gen, PyObject *arg)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000342{
Yury Selivanov77c96812016-02-13 17:59:05 -0500343 return gen_send_ex(gen, arg, 0, 0);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000344}
345
346PyDoc_STRVAR(close_doc,
Benjamin Petersonab3da292012-05-03 18:44:09 -0400347"close() -> raise GeneratorExit inside generator.");
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000348
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000349/*
350 * This helper function is used by gen_close and gen_throw to
351 * close a subiterator being delegated to by yield-from.
352 */
353
Antoine Pitrou93963562013-05-14 20:37:52 +0200354static int
355gen_close_iter(PyObject *yf)
356{
357 PyObject *retval = NULL;
358 _Py_IDENTIFIER(close);
359
Yury Selivanoveb636452016-09-08 22:01:51 -0700360 if (PyGen_CheckExact(yf) || PyCoro_CheckExact(yf)) {
Antoine Pitrou93963562013-05-14 20:37:52 +0200361 retval = gen_close((PyGenObject *)yf, NULL);
362 if (retval == NULL)
363 return -1;
Yury Selivanoveb636452016-09-08 22:01:51 -0700364 }
365 else {
Antoine Pitrou93963562013-05-14 20:37:52 +0200366 PyObject *meth = _PyObject_GetAttrId(yf, &PyId_close);
367 if (meth == NULL) {
368 if (!PyErr_ExceptionMatches(PyExc_AttributeError))
369 PyErr_WriteUnraisable(yf);
370 PyErr_Clear();
Yury Selivanoveb636452016-09-08 22:01:51 -0700371 }
372 else {
Victor Stinner3466bde2016-09-05 18:16:01 -0700373 retval = _PyObject_CallNoArg(meth);
Antoine Pitrou93963562013-05-14 20:37:52 +0200374 Py_DECREF(meth);
375 if (retval == NULL)
376 return -1;
377 }
378 }
379 Py_XDECREF(retval);
380 return 0;
381}
382
Yury Selivanovc724bae2016-03-02 11:30:46 -0500383PyObject *
384_PyGen_yf(PyGenObject *gen)
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500385{
Antoine Pitrou93963562013-05-14 20:37:52 +0200386 PyObject *yf = NULL;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500387 PyFrameObject *f = gen->gi_frame;
Antoine Pitrou93963562013-05-14 20:37:52 +0200388
389 if (f && f->f_stacktop) {
390 PyObject *bytecode = f->f_code->co_code;
391 unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode);
392
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300393 if (code[f->f_lasti + 2] != YIELD_FROM)
Antoine Pitrou93963562013-05-14 20:37:52 +0200394 return NULL;
395 yf = f->f_stacktop[-1];
396 Py_INCREF(yf);
397 }
398
399 return yf;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500400}
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000401
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000402static PyObject *
403gen_close(PyGenObject *gen, PyObject *args)
404{
Antoine Pitrou93963562013-05-14 20:37:52 +0200405 PyObject *retval;
Yury Selivanovc724bae2016-03-02 11:30:46 -0500406 PyObject *yf = _PyGen_yf(gen);
Antoine Pitrou93963562013-05-14 20:37:52 +0200407 int err = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000408
Antoine Pitrou93963562013-05-14 20:37:52 +0200409 if (yf) {
410 gen->gi_running = 1;
411 err = gen_close_iter(yf);
412 gen->gi_running = 0;
413 Py_DECREF(yf);
414 }
415 if (err == 0)
416 PyErr_SetNone(PyExc_GeneratorExit);
Yury Selivanov77c96812016-02-13 17:59:05 -0500417 retval = gen_send_ex(gen, Py_None, 1, 1);
Antoine Pitrou93963562013-05-14 20:37:52 +0200418 if (retval) {
Yury Selivanov5376ba92015-06-22 12:19:30 -0400419 char *msg = "generator ignored GeneratorExit";
Yury Selivanoveb636452016-09-08 22:01:51 -0700420 if (PyCoro_CheckExact(gen)) {
Yury Selivanov5376ba92015-06-22 12:19:30 -0400421 msg = "coroutine ignored GeneratorExit";
Yury Selivanoveb636452016-09-08 22:01:51 -0700422 } else if (PyAsyncGen_CheckExact(gen)) {
423 msg = ASYNC_GEN_IGNORED_EXIT_MSG;
424 }
Antoine Pitrou93963562013-05-14 20:37:52 +0200425 Py_DECREF(retval);
Yury Selivanov5376ba92015-06-22 12:19:30 -0400426 PyErr_SetString(PyExc_RuntimeError, msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000427 return NULL;
428 }
Antoine Pitrou93963562013-05-14 20:37:52 +0200429 if (PyErr_ExceptionMatches(PyExc_StopIteration)
430 || PyErr_ExceptionMatches(PyExc_GeneratorExit)) {
431 PyErr_Clear(); /* ignore these errors */
432 Py_INCREF(Py_None);
433 return Py_None;
434 }
435 return NULL;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000436}
437
Antoine Pitrou93963562013-05-14 20:37:52 +0200438
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000439PyDoc_STRVAR(throw_doc,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000440"throw(typ[,val[,tb]]) -> raise exception in generator,\n\
441return next yielded value or raise StopIteration.");
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000442
443static PyObject *
Yury Selivanoveb636452016-09-08 22:01:51 -0700444_gen_throw(PyGenObject *gen, int close_on_genexit,
445 PyObject *typ, PyObject *val, PyObject *tb)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000446{
Yury Selivanovc724bae2016-03-02 11:30:46 -0500447 PyObject *yf = _PyGen_yf(gen);
Nick Coghlan5b0dac12012-06-17 15:45:11 +1000448 _Py_IDENTIFIER(throw);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000449
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000450 if (yf) {
451 PyObject *ret;
452 int err;
Yury Selivanoveb636452016-09-08 22:01:51 -0700453 if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit) &&
454 close_on_genexit
455 ) {
456 /* Asynchronous generators *should not* be closed right away.
457 We have to allow some awaits to work it through, hence the
458 `close_on_genexit` parameter here.
459 */
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500460 gen->gi_running = 1;
Antoine Pitrou93963562013-05-14 20:37:52 +0200461 err = gen_close_iter(yf);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500462 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000463 Py_DECREF(yf);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000464 if (err < 0)
Yury Selivanov77c96812016-02-13 17:59:05 -0500465 return gen_send_ex(gen, Py_None, 1, 0);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000466 goto throw_here;
467 }
Yury Selivanoveb636452016-09-08 22:01:51 -0700468 if (PyGen_CheckExact(yf) || PyCoro_CheckExact(yf)) {
469 /* `yf` is a generator or a coroutine. */
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500470 gen->gi_running = 1;
Yury Selivanoveb636452016-09-08 22:01:51 -0700471 /* Close the generator that we are currently iterating with
472 'yield from' or awaiting on with 'await'. */
473 ret = _gen_throw((PyGenObject *)yf, close_on_genexit,
474 typ, val, tb);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500475 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000476 } else {
Yury Selivanoveb636452016-09-08 22:01:51 -0700477 /* `yf` is an iterator or a coroutine-like object. */
Nick Coghlan5b0dac12012-06-17 15:45:11 +1000478 PyObject *meth = _PyObject_GetAttrId(yf, &PyId_throw);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000479 if (meth == NULL) {
480 if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
481 Py_DECREF(yf);
482 return NULL;
483 }
484 PyErr_Clear();
485 Py_DECREF(yf);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000486 goto throw_here;
487 }
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500488 gen->gi_running = 1;
Yury Selivanoveb636452016-09-08 22:01:51 -0700489 ret = PyObject_CallFunctionObjArgs(meth, typ, val, tb, NULL);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500490 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000491 Py_DECREF(meth);
492 }
493 Py_DECREF(yf);
494 if (!ret) {
495 PyObject *val;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500496 /* Pop subiterator from stack */
497 ret = *(--gen->gi_frame->f_stacktop);
498 assert(ret == yf);
499 Py_DECREF(ret);
500 /* Termination repetition of YIELD_FROM */
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300501 gen->gi_frame->f_lasti += 2;
Nick Coghlanc40bc092012-06-17 15:15:49 +1000502 if (_PyGen_FetchStopIterationValue(&val) == 0) {
Yury Selivanov77c96812016-02-13 17:59:05 -0500503 ret = gen_send_ex(gen, val, 0, 0);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000504 Py_DECREF(val);
505 } else {
Yury Selivanov77c96812016-02-13 17:59:05 -0500506 ret = gen_send_ex(gen, Py_None, 1, 0);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000507 }
508 }
509 return ret;
510 }
511
512throw_here:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000513 /* First, check the traceback argument, replacing None with
514 NULL. */
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400515 if (tb == Py_None) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000516 tb = NULL;
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400517 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000518 else if (tb != NULL && !PyTraceBack_Check(tb)) {
519 PyErr_SetString(PyExc_TypeError,
520 "throw() third argument must be a traceback object");
521 return NULL;
522 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 Py_INCREF(typ);
525 Py_XINCREF(val);
526 Py_XINCREF(tb);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000527
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400528 if (PyExceptionClass_Check(typ))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000529 PyErr_NormalizeException(&typ, &val, &tb);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000530
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000531 else if (PyExceptionInstance_Check(typ)) {
532 /* Raising an instance. The value should be a dummy. */
533 if (val && val != Py_None) {
534 PyErr_SetString(PyExc_TypeError,
535 "instance exception may not have a separate value");
536 goto failed_throw;
537 }
538 else {
539 /* Normalize to raise <class>, <instance> */
540 Py_XDECREF(val);
541 val = typ;
542 typ = PyExceptionInstance_Class(typ);
543 Py_INCREF(typ);
Antoine Pitrou551ba202011-10-18 16:40:50 +0200544
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400545 if (tb == NULL)
Antoine Pitrou551ba202011-10-18 16:40:50 +0200546 /* Returns NULL if there's no traceback */
547 tb = PyException_GetTraceback(val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000548 }
549 }
550 else {
551 /* Not something you can raise. throw() fails. */
552 PyErr_Format(PyExc_TypeError,
553 "exceptions must be classes or instances "
554 "deriving from BaseException, not %s",
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000555 Py_TYPE(typ)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000556 goto failed_throw;
557 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000558
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000559 PyErr_Restore(typ, val, tb);
Yury Selivanov77c96812016-02-13 17:59:05 -0500560 return gen_send_ex(gen, Py_None, 1, 0);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000561
562failed_throw:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000563 /* Didn't use our arguments, so restore their original refcounts */
564 Py_DECREF(typ);
565 Py_XDECREF(val);
566 Py_XDECREF(tb);
567 return NULL;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000568}
569
570
571static PyObject *
Yury Selivanoveb636452016-09-08 22:01:51 -0700572gen_throw(PyGenObject *gen, PyObject *args)
573{
574 PyObject *typ;
575 PyObject *tb = NULL;
576 PyObject *val = NULL;
577
578 if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb)) {
579 return NULL;
580 }
581
582 return _gen_throw(gen, 1, typ, val, tb);
583}
584
585
586static PyObject *
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000587gen_iternext(PyGenObject *gen)
588{
Yury Selivanov77c96812016-02-13 17:59:05 -0500589 return gen_send_ex(gen, NULL, 0, 0);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000590}
591
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000592/*
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000593 * If StopIteration exception is set, fetches its 'value'
594 * attribute if any, otherwise sets pvalue to None.
595 *
596 * Returns 0 if no exception or StopIteration is set.
597 * If any other exception is set, returns -1 and leaves
598 * pvalue unchanged.
599 */
600
601int
Nick Coghlanc40bc092012-06-17 15:15:49 +1000602_PyGen_FetchStopIterationValue(PyObject **pvalue) {
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000603 PyObject *et, *ev, *tb;
604 PyObject *value = NULL;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500605
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000606 if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
607 PyErr_Fetch(&et, &ev, &tb);
Antoine Pitrou7403e912015-04-26 18:46:40 +0200608 if (ev) {
609 /* exception will usually be normalised already */
Serhiy Storchaka08d230a2015-05-22 11:02:49 +0300610 if (PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
Antoine Pitrou7403e912015-04-26 18:46:40 +0200611 value = ((PyStopIterationObject *)ev)->value;
612 Py_INCREF(value);
613 Py_DECREF(ev);
614 } else if (et == PyExc_StopIteration) {
615 /* avoid normalisation and take ev as value */
616 value = ev;
617 } else {
618 /* normalisation required */
619 PyErr_NormalizeException(&et, &ev, &tb);
Serhiy Storchaka08d230a2015-05-22 11:02:49 +0300620 if (!PyObject_TypeCheck(ev, (PyTypeObject *)PyExc_StopIteration)) {
Antoine Pitrou7403e912015-04-26 18:46:40 +0200621 PyErr_Restore(et, ev, tb);
622 return -1;
623 }
624 value = ((PyStopIterationObject *)ev)->value;
625 Py_INCREF(value);
626 Py_DECREF(ev);
627 }
628 }
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000629 Py_XDECREF(et);
630 Py_XDECREF(tb);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000631 } else if (PyErr_Occurred()) {
632 return -1;
633 }
634 if (value == NULL) {
635 value = Py_None;
Amaury Forgeot d'Arce557da82012-01-13 21:06:12 +0100636 Py_INCREF(value);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000637 }
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000638 *pvalue = value;
639 return 0;
640}
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000641
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000642static PyObject *
643gen_repr(PyGenObject *gen)
644{
Yury Selivanov5376ba92015-06-22 12:19:30 -0400645 return PyUnicode_FromFormat("<generator object %S at %p>",
646 gen->gi_qualname, gen);
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000647}
648
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000649static PyObject *
Victor Stinner40ee3012014-06-16 15:59:28 +0200650gen_get_name(PyGenObject *op)
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000651{
Victor Stinner40ee3012014-06-16 15:59:28 +0200652 Py_INCREF(op->gi_name);
653 return op->gi_name;
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000654}
655
Victor Stinner40ee3012014-06-16 15:59:28 +0200656static int
657gen_set_name(PyGenObject *op, PyObject *value)
658{
Victor Stinner40ee3012014-06-16 15:59:28 +0200659 /* Not legal to del gen.gi_name or to set it to anything
660 * other than a string object. */
661 if (value == NULL || !PyUnicode_Check(value)) {
662 PyErr_SetString(PyExc_TypeError,
663 "__name__ must be set to a string object");
664 return -1;
665 }
Victor Stinner40ee3012014-06-16 15:59:28 +0200666 Py_INCREF(value);
Serhiy Storchakaec397562016-04-06 09:50:03 +0300667 Py_XSETREF(op->gi_name, value);
Victor Stinner40ee3012014-06-16 15:59:28 +0200668 return 0;
669}
670
671static PyObject *
672gen_get_qualname(PyGenObject *op)
673{
674 Py_INCREF(op->gi_qualname);
675 return op->gi_qualname;
676}
677
678static int
679gen_set_qualname(PyGenObject *op, PyObject *value)
680{
Victor Stinner40ee3012014-06-16 15:59:28 +0200681 /* Not legal to del gen.__qualname__ or to set it to anything
682 * other than a string object. */
683 if (value == NULL || !PyUnicode_Check(value)) {
684 PyErr_SetString(PyExc_TypeError,
685 "__qualname__ must be set to a string object");
686 return -1;
687 }
Victor Stinner40ee3012014-06-16 15:59:28 +0200688 Py_INCREF(value);
Serhiy Storchakaec397562016-04-06 09:50:03 +0300689 Py_XSETREF(op->gi_qualname, value);
Victor Stinner40ee3012014-06-16 15:59:28 +0200690 return 0;
691}
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000692
Yury Selivanove13f8f32015-07-03 00:23:30 -0400693static PyObject *
694gen_getyieldfrom(PyGenObject *gen)
695{
Yury Selivanovc724bae2016-03-02 11:30:46 -0500696 PyObject *yf = _PyGen_yf(gen);
Yury Selivanove13f8f32015-07-03 00:23:30 -0400697 if (yf == NULL)
698 Py_RETURN_NONE;
699 return yf;
700}
701
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000702static PyGetSetDef gen_getsetlist[] = {
Victor Stinner40ee3012014-06-16 15:59:28 +0200703 {"__name__", (getter)gen_get_name, (setter)gen_set_name,
704 PyDoc_STR("name of the generator")},
705 {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
706 PyDoc_STR("qualified name of the generator")},
Yury Selivanove13f8f32015-07-03 00:23:30 -0400707 {"gi_yieldfrom", (getter)gen_getyieldfrom, NULL,
708 PyDoc_STR("object being iterated by yield from, or None")},
Victor Stinner40ee3012014-06-16 15:59:28 +0200709 {NULL} /* Sentinel */
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000710};
711
Martin v. Löwise440e472004-06-01 15:22:42 +0000712static PyMemberDef gen_memberlist[] = {
Victor Stinner40ee3012014-06-16 15:59:28 +0200713 {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), READONLY},
714 {"gi_running", T_BOOL, offsetof(PyGenObject, gi_running), READONLY},
715 {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), READONLY},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000716 {NULL} /* Sentinel */
Martin v. Löwise440e472004-06-01 15:22:42 +0000717};
718
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000719static PyMethodDef gen_methods[] = {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500720 {"send",(PyCFunction)_PyGen_Send, METH_O, send_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000721 {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc},
722 {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc},
723 {NULL, NULL} /* Sentinel */
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000724};
725
Martin v. Löwise440e472004-06-01 15:22:42 +0000726PyTypeObject PyGen_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000727 PyVarObject_HEAD_INIT(&PyType_Type, 0)
728 "generator", /* tp_name */
729 sizeof(PyGenObject), /* tp_basicsize */
730 0, /* tp_itemsize */
731 /* methods */
732 (destructor)gen_dealloc, /* tp_dealloc */
733 0, /* tp_print */
734 0, /* tp_getattr */
735 0, /* tp_setattr */
Yury Selivanov75445082015-05-11 22:57:16 -0400736 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000737 (reprfunc)gen_repr, /* tp_repr */
738 0, /* tp_as_number */
739 0, /* tp_as_sequence */
740 0, /* tp_as_mapping */
741 0, /* tp_hash */
742 0, /* tp_call */
743 0, /* tp_str */
744 PyObject_GenericGetAttr, /* tp_getattro */
745 0, /* tp_setattro */
746 0, /* tp_as_buffer */
Antoine Pitrou796564c2013-07-30 19:59:21 +0200747 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
748 Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000749 0, /* tp_doc */
750 (traverseproc)gen_traverse, /* tp_traverse */
751 0, /* tp_clear */
752 0, /* tp_richcompare */
753 offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */
Yury Selivanov5376ba92015-06-22 12:19:30 -0400754 PyObject_SelfIter, /* tp_iter */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000755 (iternextfunc)gen_iternext, /* tp_iternext */
756 gen_methods, /* tp_methods */
757 gen_memberlist, /* tp_members */
758 gen_getsetlist, /* tp_getset */
759 0, /* tp_base */
760 0, /* tp_dict */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000761
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000762 0, /* tp_descr_get */
763 0, /* tp_descr_set */
764 0, /* tp_dictoffset */
765 0, /* tp_init */
766 0, /* tp_alloc */
767 0, /* tp_new */
768 0, /* tp_free */
769 0, /* tp_is_gc */
770 0, /* tp_bases */
771 0, /* tp_mro */
772 0, /* tp_cache */
773 0, /* tp_subclasses */
774 0, /* tp_weaklist */
Antoine Pitrou796564c2013-07-30 19:59:21 +0200775 0, /* tp_del */
776 0, /* tp_version_tag */
Antoine Pitrou58720d62013-08-05 23:26:40 +0200777 _PyGen_Finalize, /* tp_finalize */
Martin v. Löwise440e472004-06-01 15:22:42 +0000778};
779
Yury Selivanov5376ba92015-06-22 12:19:30 -0400780static PyObject *
781gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,
782 PyObject *name, PyObject *qualname)
Martin v. Löwise440e472004-06-01 15:22:42 +0000783{
Yury Selivanov5376ba92015-06-22 12:19:30 -0400784 PyGenObject *gen = PyObject_GC_New(PyGenObject, type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000785 if (gen == NULL) {
786 Py_DECREF(f);
787 return NULL;
788 }
789 gen->gi_frame = f;
Antoine Pitrou58720d62013-08-05 23:26:40 +0200790 f->f_gen = (PyObject *) gen;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000791 Py_INCREF(f->f_code);
792 gen->gi_code = (PyObject *)(f->f_code);
793 gen->gi_running = 0;
794 gen->gi_weakreflist = NULL;
Victor Stinner40ee3012014-06-16 15:59:28 +0200795 if (name != NULL)
796 gen->gi_name = name;
797 else
798 gen->gi_name = ((PyCodeObject *)gen->gi_code)->co_name;
799 Py_INCREF(gen->gi_name);
800 if (qualname != NULL)
801 gen->gi_qualname = qualname;
802 else
803 gen->gi_qualname = gen->gi_name;
804 Py_INCREF(gen->gi_qualname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000805 _PyObject_GC_TRACK(gen);
806 return (PyObject *)gen;
Martin v. Löwise440e472004-06-01 15:22:42 +0000807}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000808
Victor Stinner40ee3012014-06-16 15:59:28 +0200809PyObject *
Yury Selivanov5376ba92015-06-22 12:19:30 -0400810PyGen_NewWithQualName(PyFrameObject *f, PyObject *name, PyObject *qualname)
811{
812 return gen_new_with_qualname(&PyGen_Type, f, name, qualname);
813}
814
815PyObject *
Victor Stinner40ee3012014-06-16 15:59:28 +0200816PyGen_New(PyFrameObject *f)
817{
Yury Selivanov5376ba92015-06-22 12:19:30 -0400818 return gen_new_with_qualname(&PyGen_Type, f, NULL, NULL);
Victor Stinner40ee3012014-06-16 15:59:28 +0200819}
820
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000821int
822PyGen_NeedsFinalizing(PyGenObject *gen)
823{
Antoine Pitrou93963562013-05-14 20:37:52 +0200824 int i;
825 PyFrameObject *f = gen->gi_frame;
826
827 if (f == NULL || f->f_stacktop == NULL)
828 return 0; /* no frame or empty blockstack == no finalization */
829
830 /* Any block type besides a loop requires cleanup. */
831 for (i = 0; i < f->f_iblock; i++)
832 if (f->f_blockstack[i].b_type != SETUP_LOOP)
833 return 1;
834
835 /* No blocks except loops, it's safe to skip finalization. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000836 return 0;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000837}
Yury Selivanov75445082015-05-11 22:57:16 -0400838
Yury Selivanov5376ba92015-06-22 12:19:30 -0400839/* Coroutine Object */
840
841typedef struct {
842 PyObject_HEAD
843 PyCoroObject *cw_coroutine;
844} PyCoroWrapper;
845
846static int
847gen_is_coroutine(PyObject *o)
848{
849 if (PyGen_CheckExact(o)) {
850 PyCodeObject *code = (PyCodeObject *)((PyGenObject*)o)->gi_code;
851 if (code->co_flags & CO_ITERABLE_COROUTINE) {
852 return 1;
853 }
854 }
855 return 0;
856}
857
Yury Selivanov75445082015-05-11 22:57:16 -0400858/*
859 * This helper function returns an awaitable for `o`:
860 * - `o` if `o` is a coroutine-object;
861 * - `type(o)->tp_as_async->am_await(o)`
862 *
863 * Raises a TypeError if it's not possible to return
864 * an awaitable and returns NULL.
865 */
866PyObject *
Yury Selivanov5376ba92015-06-22 12:19:30 -0400867_PyCoro_GetAwaitableIter(PyObject *o)
Yury Selivanov75445082015-05-11 22:57:16 -0400868{
Yury Selivanov6ef05902015-05-28 11:21:31 -0400869 unaryfunc getter = NULL;
Yury Selivanov75445082015-05-11 22:57:16 -0400870 PyTypeObject *ot;
871
Yury Selivanov5376ba92015-06-22 12:19:30 -0400872 if (PyCoro_CheckExact(o) || gen_is_coroutine(o)) {
873 /* 'o' is a coroutine. */
Yury Selivanov75445082015-05-11 22:57:16 -0400874 Py_INCREF(o);
875 return o;
876 }
877
878 ot = Py_TYPE(o);
879 if (ot->tp_as_async != NULL) {
880 getter = ot->tp_as_async->am_await;
881 }
882 if (getter != NULL) {
883 PyObject *res = (*getter)(o);
884 if (res != NULL) {
Yury Selivanov5376ba92015-06-22 12:19:30 -0400885 if (PyCoro_CheckExact(res) || gen_is_coroutine(res)) {
886 /* __await__ must return an *iterator*, not
887 a coroutine or another awaitable (see PEP 492) */
888 PyErr_SetString(PyExc_TypeError,
889 "__await__() returned a coroutine");
890 Py_CLEAR(res);
891 } else if (!PyIter_Check(res)) {
Yury Selivanov75445082015-05-11 22:57:16 -0400892 PyErr_Format(PyExc_TypeError,
893 "__await__() returned non-iterator "
894 "of type '%.100s'",
895 Py_TYPE(res)->tp_name);
896 Py_CLEAR(res);
897 }
Yury Selivanov75445082015-05-11 22:57:16 -0400898 }
899 return res;
900 }
901
902 PyErr_Format(PyExc_TypeError,
903 "object %.100s can't be used in 'await' expression",
904 ot->tp_name);
Yury Selivanov75445082015-05-11 22:57:16 -0400905 return NULL;
906}
Yury Selivanov5376ba92015-06-22 12:19:30 -0400907
908static PyObject *
909coro_repr(PyCoroObject *coro)
910{
911 return PyUnicode_FromFormat("<coroutine object %S at %p>",
912 coro->cr_qualname, coro);
913}
914
915static PyObject *
916coro_await(PyCoroObject *coro)
917{
918 PyCoroWrapper *cw = PyObject_GC_New(PyCoroWrapper, &_PyCoroWrapper_Type);
919 if (cw == NULL) {
920 return NULL;
921 }
922 Py_INCREF(coro);
923 cw->cw_coroutine = coro;
924 _PyObject_GC_TRACK(cw);
925 return (PyObject *)cw;
926}
927
Yury Selivanove13f8f32015-07-03 00:23:30 -0400928static PyObject *
929coro_get_cr_await(PyCoroObject *coro)
930{
Yury Selivanovc724bae2016-03-02 11:30:46 -0500931 PyObject *yf = _PyGen_yf((PyGenObject *) coro);
Yury Selivanove13f8f32015-07-03 00:23:30 -0400932 if (yf == NULL)
933 Py_RETURN_NONE;
934 return yf;
935}
936
Yury Selivanov5376ba92015-06-22 12:19:30 -0400937static PyGetSetDef coro_getsetlist[] = {
938 {"__name__", (getter)gen_get_name, (setter)gen_set_name,
939 PyDoc_STR("name of the coroutine")},
940 {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
941 PyDoc_STR("qualified name of the coroutine")},
Yury Selivanove13f8f32015-07-03 00:23:30 -0400942 {"cr_await", (getter)coro_get_cr_await, NULL,
943 PyDoc_STR("object being awaited on, or None")},
Yury Selivanov5376ba92015-06-22 12:19:30 -0400944 {NULL} /* Sentinel */
945};
946
947static PyMemberDef coro_memberlist[] = {
948 {"cr_frame", T_OBJECT, offsetof(PyCoroObject, cr_frame), READONLY},
949 {"cr_running", T_BOOL, offsetof(PyCoroObject, cr_running), READONLY},
950 {"cr_code", T_OBJECT, offsetof(PyCoroObject, cr_code), READONLY},
951 {NULL} /* Sentinel */
952};
953
954PyDoc_STRVAR(coro_send_doc,
955"send(arg) -> send 'arg' into coroutine,\n\
Yury Selivanov66f88282015-06-24 11:04:15 -0400956return next iterated value or raise StopIteration.");
Yury Selivanov5376ba92015-06-22 12:19:30 -0400957
958PyDoc_STRVAR(coro_throw_doc,
959"throw(typ[,val[,tb]]) -> raise exception in coroutine,\n\
Yury Selivanov66f88282015-06-24 11:04:15 -0400960return next iterated value or raise StopIteration.");
Yury Selivanov5376ba92015-06-22 12:19:30 -0400961
962PyDoc_STRVAR(coro_close_doc,
963"close() -> raise GeneratorExit inside coroutine.");
964
965static PyMethodDef coro_methods[] = {
966 {"send",(PyCFunction)_PyGen_Send, METH_O, coro_send_doc},
967 {"throw",(PyCFunction)gen_throw, METH_VARARGS, coro_throw_doc},
968 {"close",(PyCFunction)gen_close, METH_NOARGS, coro_close_doc},
969 {NULL, NULL} /* Sentinel */
970};
971
972static PyAsyncMethods coro_as_async = {
973 (unaryfunc)coro_await, /* am_await */
974 0, /* am_aiter */
975 0 /* am_anext */
976};
977
978PyTypeObject PyCoro_Type = {
979 PyVarObject_HEAD_INIT(&PyType_Type, 0)
980 "coroutine", /* tp_name */
981 sizeof(PyCoroObject), /* tp_basicsize */
982 0, /* tp_itemsize */
983 /* methods */
984 (destructor)gen_dealloc, /* tp_dealloc */
985 0, /* tp_print */
986 0, /* tp_getattr */
987 0, /* tp_setattr */
988 &coro_as_async, /* tp_as_async */
989 (reprfunc)coro_repr, /* tp_repr */
990 0, /* tp_as_number */
991 0, /* tp_as_sequence */
992 0, /* tp_as_mapping */
993 0, /* tp_hash */
994 0, /* tp_call */
995 0, /* tp_str */
996 PyObject_GenericGetAttr, /* tp_getattro */
997 0, /* tp_setattro */
998 0, /* tp_as_buffer */
999 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1000 Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
1001 0, /* tp_doc */
1002 (traverseproc)gen_traverse, /* tp_traverse */
1003 0, /* tp_clear */
1004 0, /* tp_richcompare */
1005 offsetof(PyCoroObject, cr_weakreflist), /* tp_weaklistoffset */
1006 0, /* tp_iter */
1007 0, /* tp_iternext */
1008 coro_methods, /* tp_methods */
1009 coro_memberlist, /* tp_members */
1010 coro_getsetlist, /* tp_getset */
1011 0, /* tp_base */
1012 0, /* tp_dict */
1013 0, /* tp_descr_get */
1014 0, /* tp_descr_set */
1015 0, /* tp_dictoffset */
1016 0, /* tp_init */
1017 0, /* tp_alloc */
1018 0, /* tp_new */
1019 0, /* tp_free */
1020 0, /* tp_is_gc */
1021 0, /* tp_bases */
1022 0, /* tp_mro */
1023 0, /* tp_cache */
1024 0, /* tp_subclasses */
1025 0, /* tp_weaklist */
1026 0, /* tp_del */
1027 0, /* tp_version_tag */
1028 _PyGen_Finalize, /* tp_finalize */
1029};
1030
1031static void
1032coro_wrapper_dealloc(PyCoroWrapper *cw)
1033{
1034 _PyObject_GC_UNTRACK((PyObject *)cw);
1035 Py_CLEAR(cw->cw_coroutine);
1036 PyObject_GC_Del(cw);
1037}
1038
1039static PyObject *
1040coro_wrapper_iternext(PyCoroWrapper *cw)
1041{
Yury Selivanov77c96812016-02-13 17:59:05 -05001042 return gen_send_ex((PyGenObject *)cw->cw_coroutine, NULL, 0, 0);
Yury Selivanov5376ba92015-06-22 12:19:30 -04001043}
1044
1045static PyObject *
1046coro_wrapper_send(PyCoroWrapper *cw, PyObject *arg)
1047{
Yury Selivanov77c96812016-02-13 17:59:05 -05001048 return gen_send_ex((PyGenObject *)cw->cw_coroutine, arg, 0, 0);
Yury Selivanov5376ba92015-06-22 12:19:30 -04001049}
1050
1051static PyObject *
1052coro_wrapper_throw(PyCoroWrapper *cw, PyObject *args)
1053{
1054 return gen_throw((PyGenObject *)cw->cw_coroutine, args);
1055}
1056
1057static PyObject *
1058coro_wrapper_close(PyCoroWrapper *cw, PyObject *args)
1059{
1060 return gen_close((PyGenObject *)cw->cw_coroutine, args);
1061}
1062
1063static int
1064coro_wrapper_traverse(PyCoroWrapper *cw, visitproc visit, void *arg)
1065{
1066 Py_VISIT((PyObject *)cw->cw_coroutine);
1067 return 0;
1068}
1069
1070static PyMethodDef coro_wrapper_methods[] = {
Yury Selivanov66f88282015-06-24 11:04:15 -04001071 {"send",(PyCFunction)coro_wrapper_send, METH_O, coro_send_doc},
1072 {"throw",(PyCFunction)coro_wrapper_throw, METH_VARARGS, coro_throw_doc},
1073 {"close",(PyCFunction)coro_wrapper_close, METH_NOARGS, coro_close_doc},
Yury Selivanov5376ba92015-06-22 12:19:30 -04001074 {NULL, NULL} /* Sentinel */
1075};
1076
1077PyTypeObject _PyCoroWrapper_Type = {
1078 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1079 "coroutine_wrapper",
1080 sizeof(PyCoroWrapper), /* tp_basicsize */
1081 0, /* tp_itemsize */
1082 (destructor)coro_wrapper_dealloc, /* destructor tp_dealloc */
1083 0, /* tp_print */
1084 0, /* tp_getattr */
1085 0, /* tp_setattr */
1086 0, /* tp_as_async */
1087 0, /* tp_repr */
1088 0, /* tp_as_number */
1089 0, /* tp_as_sequence */
1090 0, /* tp_as_mapping */
1091 0, /* tp_hash */
1092 0, /* tp_call */
1093 0, /* tp_str */
1094 PyObject_GenericGetAttr, /* tp_getattro */
1095 0, /* tp_setattro */
1096 0, /* tp_as_buffer */
1097 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1098 "A wrapper object implementing __await__ for coroutines.",
1099 (traverseproc)coro_wrapper_traverse, /* tp_traverse */
1100 0, /* tp_clear */
1101 0, /* tp_richcompare */
1102 0, /* tp_weaklistoffset */
1103 PyObject_SelfIter, /* tp_iter */
1104 (iternextfunc)coro_wrapper_iternext, /* tp_iternext */
1105 coro_wrapper_methods, /* tp_methods */
1106 0, /* tp_members */
1107 0, /* tp_getset */
1108 0, /* tp_base */
1109 0, /* tp_dict */
1110 0, /* tp_descr_get */
1111 0, /* tp_descr_set */
1112 0, /* tp_dictoffset */
1113 0, /* tp_init */
1114 0, /* tp_alloc */
1115 0, /* tp_new */
1116 PyObject_Del, /* tp_free */
1117};
1118
1119PyObject *
1120PyCoro_New(PyFrameObject *f, PyObject *name, PyObject *qualname)
1121{
1122 return gen_new_with_qualname(&PyCoro_Type, f, name, qualname);
1123}
Yury Selivanova6f6edb2016-06-09 15:08:31 -04001124
1125
1126/* __aiter__ wrapper; see http://bugs.python.org/issue27243 for details. */
1127
1128typedef struct {
1129 PyObject_HEAD
Yury Selivanoveb636452016-09-08 22:01:51 -07001130 PyObject *ags_aiter;
Yury Selivanova6f6edb2016-06-09 15:08:31 -04001131} PyAIterWrapper;
1132
1133
1134static PyObject *
1135aiter_wrapper_iternext(PyAIterWrapper *aw)
1136{
Yury Selivanoveb636452016-09-08 22:01:51 -07001137 PyErr_SetObject(PyExc_StopIteration, aw->ags_aiter);
Yury Selivanova6f6edb2016-06-09 15:08:31 -04001138 return NULL;
1139}
1140
1141static int
1142aiter_wrapper_traverse(PyAIterWrapper *aw, visitproc visit, void *arg)
1143{
Yury Selivanoveb636452016-09-08 22:01:51 -07001144 Py_VISIT((PyObject *)aw->ags_aiter);
Yury Selivanova6f6edb2016-06-09 15:08:31 -04001145 return 0;
1146}
1147
1148static void
1149aiter_wrapper_dealloc(PyAIterWrapper *aw)
1150{
1151 _PyObject_GC_UNTRACK((PyObject *)aw);
Yury Selivanoveb636452016-09-08 22:01:51 -07001152 Py_CLEAR(aw->ags_aiter);
Yury Selivanova6f6edb2016-06-09 15:08:31 -04001153 PyObject_GC_Del(aw);
1154}
1155
1156static PyAsyncMethods aiter_wrapper_as_async = {
1157 PyObject_SelfIter, /* am_await */
1158 0, /* am_aiter */
1159 0 /* am_anext */
1160};
1161
1162PyTypeObject _PyAIterWrapper_Type = {
1163 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1164 "aiter_wrapper",
1165 sizeof(PyAIterWrapper), /* tp_basicsize */
1166 0, /* tp_itemsize */
1167 (destructor)aiter_wrapper_dealloc, /* destructor tp_dealloc */
1168 0, /* tp_print */
1169 0, /* tp_getattr */
1170 0, /* tp_setattr */
1171 &aiter_wrapper_as_async, /* tp_as_async */
1172 0, /* tp_repr */
1173 0, /* tp_as_number */
1174 0, /* tp_as_sequence */
1175 0, /* tp_as_mapping */
1176 0, /* tp_hash */
1177 0, /* tp_call */
1178 0, /* tp_str */
1179 PyObject_GenericGetAttr, /* tp_getattro */
1180 0, /* tp_setattro */
1181 0, /* tp_as_buffer */
1182 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1183 "A wrapper object for __aiter__ bakwards compatibility.",
1184 (traverseproc)aiter_wrapper_traverse, /* tp_traverse */
1185 0, /* tp_clear */
1186 0, /* tp_richcompare */
1187 0, /* tp_weaklistoffset */
1188 PyObject_SelfIter, /* tp_iter */
1189 (iternextfunc)aiter_wrapper_iternext, /* tp_iternext */
1190 0, /* tp_methods */
1191 0, /* tp_members */
1192 0, /* tp_getset */
1193 0, /* tp_base */
1194 0, /* tp_dict */
1195 0, /* tp_descr_get */
1196 0, /* tp_descr_set */
1197 0, /* tp_dictoffset */
1198 0, /* tp_init */
1199 0, /* tp_alloc */
1200 0, /* tp_new */
1201 PyObject_Del, /* tp_free */
1202};
1203
1204
1205PyObject *
1206_PyAIterWrapper_New(PyObject *aiter)
1207{
1208 PyAIterWrapper *aw = PyObject_GC_New(PyAIterWrapper,
1209 &_PyAIterWrapper_Type);
1210 if (aw == NULL) {
1211 return NULL;
1212 }
1213 Py_INCREF(aiter);
Yury Selivanoveb636452016-09-08 22:01:51 -07001214 aw->ags_aiter = aiter;
Yury Selivanova6f6edb2016-06-09 15:08:31 -04001215 _PyObject_GC_TRACK(aw);
1216 return (PyObject *)aw;
1217}
Yury Selivanoveb636452016-09-08 22:01:51 -07001218
1219
1220/* ========= Asynchronous Generators ========= */
1221
1222
1223typedef enum {
1224 AWAITABLE_STATE_INIT, /* new awaitable, has not yet been iterated */
1225 AWAITABLE_STATE_ITER, /* being iterated */
1226 AWAITABLE_STATE_CLOSED, /* closed */
1227} AwaitableState;
1228
1229
1230typedef struct {
1231 PyObject_HEAD
1232 PyAsyncGenObject *ags_gen;
1233
1234 /* Can be NULL, when in the __anext__() mode
1235 (equivalent of "asend(None)") */
1236 PyObject *ags_sendval;
1237
1238 AwaitableState ags_state;
1239} PyAsyncGenASend;
1240
1241
1242typedef struct {
1243 PyObject_HEAD
1244 PyAsyncGenObject *agt_gen;
1245
1246 /* Can be NULL, when in the "aclose()" mode
1247 (equivalent of "athrow(GeneratorExit)") */
1248 PyObject *agt_args;
1249
1250 AwaitableState agt_state;
1251} PyAsyncGenAThrow;
1252
1253
1254typedef struct {
1255 PyObject_HEAD
1256 PyObject *agw_val;
1257} _PyAsyncGenWrappedValue;
1258
1259
1260#ifndef _PyAsyncGen_MAXFREELIST
1261#define _PyAsyncGen_MAXFREELIST 80
1262#endif
1263
1264/* Freelists boost performance 6-10%; they also reduce memory
1265 fragmentation, as _PyAsyncGenWrappedValue and PyAsyncGenASend
1266 are short-living objects that are instantiated for every
1267 __anext__ call.
1268*/
1269
1270static _PyAsyncGenWrappedValue *ag_value_freelist[_PyAsyncGen_MAXFREELIST];
1271static int ag_value_freelist_free = 0;
1272
1273static PyAsyncGenASend *ag_asend_freelist[_PyAsyncGen_MAXFREELIST];
1274static int ag_asend_freelist_free = 0;
1275
1276#define _PyAsyncGenWrappedValue_CheckExact(o) \
1277 (Py_TYPE(o) == &_PyAsyncGenWrappedValue_Type)
1278
1279#define PyAsyncGenASend_CheckExact(o) \
1280 (Py_TYPE(o) == &_PyAsyncGenASend_Type)
1281
1282
1283static int
1284async_gen_traverse(PyAsyncGenObject *gen, visitproc visit, void *arg)
1285{
1286 Py_VISIT(gen->ag_finalizer);
1287 return gen_traverse((PyGenObject*)gen, visit, arg);
1288}
1289
1290
1291static PyObject *
1292async_gen_repr(PyAsyncGenObject *o)
1293{
1294 return PyUnicode_FromFormat("<async_generator object %S at %p>",
1295 o->ag_qualname, o);
1296}
1297
1298
1299static int
1300async_gen_init_hooks(PyAsyncGenObject *o)
1301{
1302 PyThreadState *tstate;
1303 PyObject *finalizer;
1304 PyObject *firstiter;
1305
1306 if (o->ag_hooks_inited) {
1307 return 0;
1308 }
1309
1310 o->ag_hooks_inited = 1;
1311
1312 tstate = PyThreadState_GET();
1313
1314 finalizer = tstate->async_gen_finalizer;
1315 if (finalizer) {
1316 Py_INCREF(finalizer);
1317 o->ag_finalizer = finalizer;
1318 }
1319
1320 firstiter = tstate->async_gen_firstiter;
1321 if (firstiter) {
1322 PyObject *res;
1323
1324 Py_INCREF(firstiter);
1325 res = PyObject_CallFunction(firstiter, "O", o);
1326 Py_DECREF(firstiter);
1327 if (res == NULL) {
1328 return 1;
1329 }
1330 Py_DECREF(res);
1331 }
1332
1333 return 0;
1334}
1335
1336
1337static PyObject *
1338async_gen_anext(PyAsyncGenObject *o)
1339{
1340 if (async_gen_init_hooks(o)) {
1341 return NULL;
1342 }
1343 return async_gen_asend_new(o, NULL);
1344}
1345
1346
1347static PyObject *
1348async_gen_asend(PyAsyncGenObject *o, PyObject *arg)
1349{
1350 if (async_gen_init_hooks(o)) {
1351 return NULL;
1352 }
1353 return async_gen_asend_new(o, arg);
1354}
1355
1356
1357static PyObject *
1358async_gen_aclose(PyAsyncGenObject *o, PyObject *arg)
1359{
1360 if (async_gen_init_hooks(o)) {
1361 return NULL;
1362 }
1363 return async_gen_athrow_new(o, NULL);
1364}
1365
1366static PyObject *
1367async_gen_athrow(PyAsyncGenObject *o, PyObject *args)
1368{
1369 if (async_gen_init_hooks(o)) {
1370 return NULL;
1371 }
1372 return async_gen_athrow_new(o, args);
1373}
1374
1375
1376static PyGetSetDef async_gen_getsetlist[] = {
1377 {"__name__", (getter)gen_get_name, (setter)gen_set_name,
1378 PyDoc_STR("name of the async generator")},
1379 {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
1380 PyDoc_STR("qualified name of the async generator")},
1381 {"ag_await", (getter)coro_get_cr_await, NULL,
1382 PyDoc_STR("object being awaited on, or None")},
1383 {NULL} /* Sentinel */
1384};
1385
1386static PyMemberDef async_gen_memberlist[] = {
1387 {"ag_frame", T_OBJECT, offsetof(PyAsyncGenObject, ag_frame), READONLY},
1388 {"ag_running", T_BOOL, offsetof(PyAsyncGenObject, ag_running), READONLY},
1389 {"ag_code", T_OBJECT, offsetof(PyAsyncGenObject, ag_code), READONLY},
1390 {NULL} /* Sentinel */
1391};
1392
1393PyDoc_STRVAR(async_aclose_doc,
1394"aclose() -> raise GeneratorExit inside generator.");
1395
1396PyDoc_STRVAR(async_asend_doc,
1397"asend(v) -> send 'v' in generator.");
1398
1399PyDoc_STRVAR(async_athrow_doc,
1400"athrow(typ[,val[,tb]]) -> raise exception in generator.");
1401
1402static PyMethodDef async_gen_methods[] = {
1403 {"asend", (PyCFunction)async_gen_asend, METH_O, async_asend_doc},
1404 {"athrow",(PyCFunction)async_gen_athrow, METH_VARARGS, async_athrow_doc},
1405 {"aclose", (PyCFunction)async_gen_aclose, METH_NOARGS, async_aclose_doc},
1406 {NULL, NULL} /* Sentinel */
1407};
1408
1409
1410static PyAsyncMethods async_gen_as_async = {
1411 0, /* am_await */
1412 PyObject_SelfIter, /* am_aiter */
1413 (unaryfunc)async_gen_anext /* am_anext */
1414};
1415
1416
1417PyTypeObject PyAsyncGen_Type = {
1418 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1419 "async_generator", /* tp_name */
1420 sizeof(PyAsyncGenObject), /* tp_basicsize */
1421 0, /* tp_itemsize */
1422 /* methods */
1423 (destructor)gen_dealloc, /* tp_dealloc */
1424 0, /* tp_print */
1425 0, /* tp_getattr */
1426 0, /* tp_setattr */
1427 &async_gen_as_async, /* tp_as_async */
1428 (reprfunc)async_gen_repr, /* tp_repr */
1429 0, /* tp_as_number */
1430 0, /* tp_as_sequence */
1431 0, /* tp_as_mapping */
1432 0, /* tp_hash */
1433 0, /* tp_call */
1434 0, /* tp_str */
1435 PyObject_GenericGetAttr, /* tp_getattro */
1436 0, /* tp_setattro */
1437 0, /* tp_as_buffer */
1438 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1439 Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
1440 0, /* tp_doc */
1441 (traverseproc)async_gen_traverse, /* tp_traverse */
1442 0, /* tp_clear */
1443 0, /* tp_richcompare */
1444 offsetof(PyAsyncGenObject, ag_weakreflist), /* tp_weaklistoffset */
1445 0, /* tp_iter */
1446 0, /* tp_iternext */
1447 async_gen_methods, /* tp_methods */
1448 async_gen_memberlist, /* tp_members */
1449 async_gen_getsetlist, /* tp_getset */
1450 0, /* tp_base */
1451 0, /* tp_dict */
1452 0, /* tp_descr_get */
1453 0, /* tp_descr_set */
1454 0, /* tp_dictoffset */
1455 0, /* tp_init */
1456 0, /* tp_alloc */
1457 0, /* tp_new */
1458 0, /* tp_free */
1459 0, /* tp_is_gc */
1460 0, /* tp_bases */
1461 0, /* tp_mro */
1462 0, /* tp_cache */
1463 0, /* tp_subclasses */
1464 0, /* tp_weaklist */
1465 0, /* tp_del */
1466 0, /* tp_version_tag */
1467 _PyGen_Finalize, /* tp_finalize */
1468};
1469
1470
1471PyObject *
1472PyAsyncGen_New(PyFrameObject *f, PyObject *name, PyObject *qualname)
1473{
1474 PyAsyncGenObject *o;
1475 o = (PyAsyncGenObject *)gen_new_with_qualname(
1476 &PyAsyncGen_Type, f, name, qualname);
1477 if (o == NULL) {
1478 return NULL;
1479 }
1480 o->ag_finalizer = NULL;
1481 o->ag_closed = 0;
1482 o->ag_hooks_inited = 0;
1483 return (PyObject*)o;
1484}
1485
1486
1487int
1488PyAsyncGen_ClearFreeLists(void)
1489{
1490 int ret = ag_value_freelist_free + ag_asend_freelist_free;
1491
1492 while (ag_value_freelist_free) {
1493 _PyAsyncGenWrappedValue *o;
1494 o = ag_value_freelist[--ag_value_freelist_free];
1495 assert(_PyAsyncGenWrappedValue_CheckExact(o));
1496 PyObject_Del(o);
1497 }
1498
1499 while (ag_asend_freelist_free) {
1500 PyAsyncGenASend *o;
1501 o = ag_asend_freelist[--ag_asend_freelist_free];
1502 assert(Py_TYPE(o) == &_PyAsyncGenASend_Type);
1503 PyObject_Del(o);
1504 }
1505
1506 return ret;
1507}
1508
1509void
1510PyAsyncGen_Fini(void)
1511{
1512 PyAsyncGen_ClearFreeLists();
1513}
1514
1515
1516static PyObject *
1517async_gen_unwrap_value(PyAsyncGenObject *gen, PyObject *result)
1518{
1519 if (result == NULL) {
1520 if (!PyErr_Occurred()) {
1521 PyErr_SetNone(PyExc_StopAsyncIteration);
1522 }
1523
1524 if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration)
1525 || PyErr_ExceptionMatches(PyExc_GeneratorExit)
1526 ) {
1527 gen->ag_closed = 1;
1528 }
1529
1530 return NULL;
1531 }
1532
1533 if (_PyAsyncGenWrappedValue_CheckExact(result)) {
1534 /* async yield */
1535 PyObject *e = PyObject_CallFunctionObjArgs(
1536 PyExc_StopIteration,
1537 ((_PyAsyncGenWrappedValue*)result)->agw_val,
1538 NULL);
1539 Py_DECREF(result);
1540 if (e == NULL) {
1541 return NULL;
1542 }
1543 PyErr_SetObject(PyExc_StopIteration, e);
1544 Py_DECREF(e);
1545 return NULL;
1546 }
1547
1548 return result;
1549}
1550
1551
1552/* ---------- Async Generator ASend Awaitable ------------ */
1553
1554
1555static void
1556async_gen_asend_dealloc(PyAsyncGenASend *o)
1557{
1558 Py_CLEAR(o->ags_gen);
1559 Py_CLEAR(o->ags_sendval);
1560 if (ag_asend_freelist_free < _PyAsyncGen_MAXFREELIST) {
1561 assert(PyAsyncGenASend_CheckExact(o));
1562 ag_asend_freelist[ag_asend_freelist_free++] = o;
1563 } else {
1564 PyObject_Del(o);
1565 }
1566}
1567
1568
1569static PyObject *
1570async_gen_asend_send(PyAsyncGenASend *o, PyObject *arg)
1571{
1572 PyObject *result;
1573
1574 if (o->ags_state == AWAITABLE_STATE_CLOSED) {
1575 PyErr_SetNone(PyExc_StopIteration);
1576 return NULL;
1577 }
1578
1579 if (o->ags_state == AWAITABLE_STATE_INIT) {
1580 if (arg == NULL || arg == Py_None) {
1581 arg = o->ags_sendval;
1582 }
1583 o->ags_state = AWAITABLE_STATE_ITER;
1584 }
1585
1586 result = gen_send_ex((PyGenObject*)o->ags_gen, arg, 0, 0);
1587 result = async_gen_unwrap_value(o->ags_gen, result);
1588
1589 if (result == NULL) {
1590 o->ags_state = AWAITABLE_STATE_CLOSED;
1591 }
1592
1593 return result;
1594}
1595
1596
1597static PyObject *
1598async_gen_asend_iternext(PyAsyncGenASend *o)
1599{
1600 return async_gen_asend_send(o, NULL);
1601}
1602
1603
1604static PyObject *
1605async_gen_asend_throw(PyAsyncGenASend *o, PyObject *args)
1606{
1607 PyObject *result;
1608
1609 if (o->ags_state == AWAITABLE_STATE_CLOSED) {
1610 PyErr_SetNone(PyExc_StopIteration);
1611 return NULL;
1612 }
1613
1614 result = gen_throw((PyGenObject*)o->ags_gen, args);
1615 result = async_gen_unwrap_value(o->ags_gen, result);
1616
1617 if (result == NULL) {
1618 o->ags_state = AWAITABLE_STATE_CLOSED;
1619 }
1620
1621 return result;
1622}
1623
1624
1625static PyObject *
1626async_gen_asend_close(PyAsyncGenASend *o, PyObject *args)
1627{
1628 o->ags_state = AWAITABLE_STATE_CLOSED;
1629 Py_RETURN_NONE;
1630}
1631
1632
1633static PyMethodDef async_gen_asend_methods[] = {
1634 {"send", (PyCFunction)async_gen_asend_send, METH_O, send_doc},
1635 {"throw", (PyCFunction)async_gen_asend_throw, METH_VARARGS, throw_doc},
1636 {"close", (PyCFunction)async_gen_asend_close, METH_NOARGS, close_doc},
1637 {NULL, NULL} /* Sentinel */
1638};
1639
1640
1641static PyAsyncMethods async_gen_asend_as_async = {
1642 PyObject_SelfIter, /* am_await */
1643 0, /* am_aiter */
1644 0 /* am_anext */
1645};
1646
1647
1648PyTypeObject _PyAsyncGenASend_Type = {
1649 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1650 "async_generator_asend", /* tp_name */
1651 sizeof(PyAsyncGenASend), /* tp_basicsize */
1652 0, /* tp_itemsize */
1653 /* methods */
1654 (destructor)async_gen_asend_dealloc, /* tp_dealloc */
1655 0, /* tp_print */
1656 0, /* tp_getattr */
1657 0, /* tp_setattr */
1658 &async_gen_asend_as_async, /* tp_as_async */
1659 0, /* tp_repr */
1660 0, /* tp_as_number */
1661 0, /* tp_as_sequence */
1662 0, /* tp_as_mapping */
1663 0, /* tp_hash */
1664 0, /* tp_call */
1665 0, /* tp_str */
1666 PyObject_GenericGetAttr, /* tp_getattro */
1667 0, /* tp_setattro */
1668 0, /* tp_as_buffer */
1669 Py_TPFLAGS_DEFAULT, /* tp_flags */
1670 0, /* tp_doc */
1671 0, /* tp_traverse */
1672 0, /* tp_clear */
1673 0, /* tp_richcompare */
1674 0, /* tp_weaklistoffset */
1675 PyObject_SelfIter, /* tp_iter */
1676 (iternextfunc)async_gen_asend_iternext, /* tp_iternext */
1677 async_gen_asend_methods, /* tp_methods */
1678 0, /* tp_members */
1679 0, /* tp_getset */
1680 0, /* tp_base */
1681 0, /* tp_dict */
1682 0, /* tp_descr_get */
1683 0, /* tp_descr_set */
1684 0, /* tp_dictoffset */
1685 0, /* tp_init */
1686 0, /* tp_alloc */
1687 0, /* tp_new */
1688};
1689
1690
1691static PyObject *
1692async_gen_asend_new(PyAsyncGenObject *gen, PyObject *sendval)
1693{
1694 PyAsyncGenASend *o;
1695 if (ag_asend_freelist_free) {
1696 ag_asend_freelist_free--;
1697 o = ag_asend_freelist[ag_asend_freelist_free];
1698 _Py_NewReference((PyObject *)o);
1699 } else {
1700 o = PyObject_New(PyAsyncGenASend, &_PyAsyncGenASend_Type);
1701 if (o == NULL) {
1702 return NULL;
1703 }
1704 }
1705
1706 Py_INCREF(gen);
1707 o->ags_gen = gen;
1708
1709 Py_XINCREF(sendval);
1710 o->ags_sendval = sendval;
1711
1712 o->ags_state = AWAITABLE_STATE_INIT;
1713 return (PyObject*)o;
1714}
1715
1716
1717/* ---------- Async Generator Value Wrapper ------------ */
1718
1719
1720static void
1721async_gen_wrapped_val_dealloc(_PyAsyncGenWrappedValue *o)
1722{
1723 Py_CLEAR(o->agw_val);
1724 if (ag_value_freelist_free < _PyAsyncGen_MAXFREELIST) {
1725 assert(_PyAsyncGenWrappedValue_CheckExact(o));
1726 ag_value_freelist[ag_value_freelist_free++] = o;
1727 } else {
1728 PyObject_Del(o);
1729 }
1730}
1731
1732
1733PyTypeObject _PyAsyncGenWrappedValue_Type = {
1734 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1735 "async_generator_wrapped_value", /* tp_name */
1736 sizeof(_PyAsyncGenWrappedValue), /* tp_basicsize */
1737 0, /* tp_itemsize */
1738 /* methods */
1739 (destructor)async_gen_wrapped_val_dealloc, /* tp_dealloc */
1740 0, /* tp_print */
1741 0, /* tp_getattr */
1742 0, /* tp_setattr */
1743 0, /* tp_as_async */
1744 0, /* tp_repr */
1745 0, /* tp_as_number */
1746 0, /* tp_as_sequence */
1747 0, /* tp_as_mapping */
1748 0, /* tp_hash */
1749 0, /* tp_call */
1750 0, /* tp_str */
1751 PyObject_GenericGetAttr, /* tp_getattro */
1752 0, /* tp_setattro */
1753 0, /* tp_as_buffer */
1754 Py_TPFLAGS_DEFAULT, /* tp_flags */
1755 0, /* tp_doc */
1756 0, /* tp_traverse */
1757 0, /* tp_clear */
1758 0, /* tp_richcompare */
1759 0, /* tp_weaklistoffset */
1760 0, /* tp_iter */
1761 0, /* tp_iternext */
1762 0, /* tp_methods */
1763 0, /* tp_members */
1764 0, /* tp_getset */
1765 0, /* tp_base */
1766 0, /* tp_dict */
1767 0, /* tp_descr_get */
1768 0, /* tp_descr_set */
1769 0, /* tp_dictoffset */
1770 0, /* tp_init */
1771 0, /* tp_alloc */
1772 0, /* tp_new */
1773};
1774
1775
1776PyObject *
1777_PyAsyncGenValueWrapperNew(PyObject *val)
1778{
1779 _PyAsyncGenWrappedValue *o;
1780 assert(val);
1781
1782 if (ag_value_freelist_free) {
1783 ag_value_freelist_free--;
1784 o = ag_value_freelist[ag_value_freelist_free];
1785 assert(_PyAsyncGenWrappedValue_CheckExact(o));
1786 _Py_NewReference((PyObject*)o);
1787 } else {
1788 o = PyObject_New(_PyAsyncGenWrappedValue, &_PyAsyncGenWrappedValue_Type);
1789 if (o == NULL) {
1790 return NULL;
1791 }
1792 }
1793 o->agw_val = val;
1794 Py_INCREF(val);
1795 return (PyObject*)o;
1796}
1797
1798
1799/* ---------- Async Generator AThrow awaitable ------------ */
1800
1801
1802static void
1803async_gen_athrow_dealloc(PyAsyncGenAThrow *o)
1804{
1805 Py_CLEAR(o->agt_gen);
1806 Py_CLEAR(o->agt_args);
1807 PyObject_Del(o);
1808}
1809
1810
1811static PyObject *
1812async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg)
1813{
1814 PyGenObject *gen = (PyGenObject*)o->agt_gen;
1815 PyFrameObject *f = gen->gi_frame;
1816 PyObject *retval;
1817
1818 if (f == NULL || f->f_stacktop == NULL ||
1819 o->agt_state == AWAITABLE_STATE_CLOSED) {
1820 PyErr_SetNone(PyExc_StopIteration);
1821 return NULL;
1822 }
1823
1824 if (o->agt_state == AWAITABLE_STATE_INIT) {
1825 if (o->agt_gen->ag_closed) {
1826 PyErr_SetNone(PyExc_StopIteration);
1827 return NULL;
1828 }
1829
1830 if (arg != Py_None) {
1831 PyErr_SetString(PyExc_RuntimeError, NON_INIT_CORO_MSG);
1832 return NULL;
1833 }
1834
1835 o->agt_state = AWAITABLE_STATE_ITER;
1836
1837 if (o->agt_args == NULL) {
1838 /* aclose() mode */
1839 o->agt_gen->ag_closed = 1;
1840
1841 retval = _gen_throw((PyGenObject *)gen,
1842 0, /* Do not close generator when
1843 PyExc_GeneratorExit is passed */
1844 PyExc_GeneratorExit, NULL, NULL);
1845
1846 if (retval && _PyAsyncGenWrappedValue_CheckExact(retval)) {
1847 Py_DECREF(retval);
1848 goto yield_close;
1849 }
1850 } else {
1851 PyObject *typ;
1852 PyObject *tb = NULL;
1853 PyObject *val = NULL;
1854
1855 if (!PyArg_UnpackTuple(o->agt_args, "athrow", 1, 3,
1856 &typ, &val, &tb)) {
1857 return NULL;
1858 }
1859
1860 retval = _gen_throw((PyGenObject *)gen,
1861 0, /* Do not close generator when
1862 PyExc_GeneratorExit is passed */
1863 typ, val, tb);
1864 retval = async_gen_unwrap_value(o->agt_gen, retval);
1865 }
1866 if (retval == NULL) {
1867 goto check_error;
1868 }
1869 return retval;
1870 }
1871
1872 assert(o->agt_state == AWAITABLE_STATE_ITER);
1873
1874 retval = gen_send_ex((PyGenObject *)gen, arg, 0, 0);
1875 if (o->agt_args) {
1876 return async_gen_unwrap_value(o->agt_gen, retval);
1877 } else {
1878 /* aclose() mode */
1879 if (retval) {
1880 if (_PyAsyncGenWrappedValue_CheckExact(retval)) {
1881 Py_DECREF(retval);
1882 goto yield_close;
1883 }
1884 else {
1885 return retval;
1886 }
1887 }
1888 else {
1889 goto check_error;
1890 }
1891 }
1892
1893yield_close:
1894 PyErr_SetString(
1895 PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG);
1896 return NULL;
1897
1898check_error:
1899 if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration)
1900 || PyErr_ExceptionMatches(PyExc_GeneratorExit)
1901 ) {
1902 o->agt_state = AWAITABLE_STATE_CLOSED;
1903 PyErr_Clear(); /* ignore these errors */
1904 PyErr_SetNone(PyExc_StopIteration);
1905 }
1906 return NULL;
1907}
1908
1909
1910static PyObject *
1911async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *args)
1912{
1913 PyObject *retval;
1914
1915 if (o->agt_state == AWAITABLE_STATE_INIT) {
1916 PyErr_SetString(PyExc_RuntimeError, NON_INIT_CORO_MSG);
1917 return NULL;
1918 }
1919
1920 if (o->agt_state == AWAITABLE_STATE_CLOSED) {
1921 PyErr_SetNone(PyExc_StopIteration);
1922 return NULL;
1923 }
1924
1925 retval = gen_throw((PyGenObject*)o->agt_gen, args);
1926 if (o->agt_args) {
1927 return async_gen_unwrap_value(o->agt_gen, retval);
1928 } else {
1929 /* aclose() mode */
1930 if (retval && _PyAsyncGenWrappedValue_CheckExact(retval)) {
1931 Py_DECREF(retval);
1932 PyErr_SetString(PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG);
1933 return NULL;
1934 }
1935 return retval;
1936 }
1937}
1938
1939
1940static PyObject *
1941async_gen_athrow_iternext(PyAsyncGenAThrow *o)
1942{
1943 return async_gen_athrow_send(o, Py_None);
1944}
1945
1946
1947static PyObject *
1948async_gen_athrow_close(PyAsyncGenAThrow *o, PyObject *args)
1949{
1950 o->agt_state = AWAITABLE_STATE_CLOSED;
1951 Py_RETURN_NONE;
1952}
1953
1954
1955static PyMethodDef async_gen_athrow_methods[] = {
1956 {"send", (PyCFunction)async_gen_athrow_send, METH_O, send_doc},
1957 {"throw", (PyCFunction)async_gen_athrow_throw, METH_VARARGS, throw_doc},
1958 {"close", (PyCFunction)async_gen_athrow_close, METH_NOARGS, close_doc},
1959 {NULL, NULL} /* Sentinel */
1960};
1961
1962
1963static PyAsyncMethods async_gen_athrow_as_async = {
1964 PyObject_SelfIter, /* am_await */
1965 0, /* am_aiter */
1966 0 /* am_anext */
1967};
1968
1969
1970PyTypeObject _PyAsyncGenAThrow_Type = {
1971 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1972 "async_generator_athrow", /* tp_name */
1973 sizeof(PyAsyncGenAThrow), /* tp_basicsize */
1974 0, /* tp_itemsize */
1975 /* methods */
1976 (destructor)async_gen_athrow_dealloc, /* tp_dealloc */
1977 0, /* tp_print */
1978 0, /* tp_getattr */
1979 0, /* tp_setattr */
1980 &async_gen_athrow_as_async, /* tp_as_async */
1981 0, /* tp_repr */
1982 0, /* tp_as_number */
1983 0, /* tp_as_sequence */
1984 0, /* tp_as_mapping */
1985 0, /* tp_hash */
1986 0, /* tp_call */
1987 0, /* tp_str */
1988 PyObject_GenericGetAttr, /* tp_getattro */
1989 0, /* tp_setattro */
1990 0, /* tp_as_buffer */
1991 Py_TPFLAGS_DEFAULT, /* tp_flags */
1992 0, /* tp_doc */
1993 0, /* tp_traverse */
1994 0, /* tp_clear */
1995 0, /* tp_richcompare */
1996 0, /* tp_weaklistoffset */
1997 PyObject_SelfIter, /* tp_iter */
1998 (iternextfunc)async_gen_athrow_iternext, /* tp_iternext */
1999 async_gen_athrow_methods, /* tp_methods */
2000 0, /* tp_members */
2001 0, /* tp_getset */
2002 0, /* tp_base */
2003 0, /* tp_dict */
2004 0, /* tp_descr_get */
2005 0, /* tp_descr_set */
2006 0, /* tp_dictoffset */
2007 0, /* tp_init */
2008 0, /* tp_alloc */
2009 0, /* tp_new */
2010};
2011
2012
2013static PyObject *
2014async_gen_athrow_new(PyAsyncGenObject *gen, PyObject *args)
2015{
2016 PyAsyncGenAThrow *o;
2017 o = PyObject_New(PyAsyncGenAThrow, &_PyAsyncGenAThrow_Type);
2018 if (o == NULL) {
2019 return NULL;
2020 }
2021 o->agt_gen = gen;
2022 o->agt_args = args;
2023 o->agt_state = AWAITABLE_STATE_INIT;
2024 Py_INCREF(gen);
2025 Py_XINCREF(args);
2026 return (PyObject*)o;
2027}