1/* Generator object implementation */
2
3#include "Python.h"
4#include "pycore_ceval.h" // _PyEval_EvalFrame()
5#include "pycore_object.h"
6#include "pycore_pyerrors.h" // _PyErr_ClearExcState()
7#include "pycore_pystate.h" // _PyThreadState_GET()
8#include "frameobject.h"
9#include "structmember.h" // PyMemberDef
10#include "opcode.h"
11
12static PyObject *gen_close(PyGenObject *, PyObject *);
13static PyObject *async_gen_asend_new(PyAsyncGenObject *, PyObject *);
14static PyObject *async_gen_athrow_new(PyAsyncGenObject *, PyObject *);
15
16static const char *NON_INIT_CORO_MSG = "can't send non-None value to a "
17 "just-started coroutine";
18
19static const char *ASYNC_GEN_IGNORED_EXIT_MSG =
20 "async generator ignored GeneratorExit";
21
22static inline int
23exc_state_traverse(_PyErr_StackItem *exc_state, visitproc visit, void *arg)
24{
25 Py_VISIT(exc_state->exc_type);
26 Py_VISIT(exc_state->exc_value);
27 Py_VISIT(exc_state->exc_traceback);
28 return 0;
29}
30
31static int
32gen_traverse(PyGenObject *gen, visitproc visit, void *arg)
33{
34 Py_VISIT((PyObject *)gen->gi_frame);
35 Py_VISIT(gen->gi_code);
36 Py_VISIT(gen->gi_name);
37 Py_VISIT(gen->gi_qualname);
38 /* No need to visit cr_origin, because it's just tuples/str/int, so can't
39 participate in a reference cycle. */
40 return exc_state_traverse(&gen->gi_exc_state, visit, arg);
41}
42
43void
44_PyGen_Finalize(PyObject *self)
45{
46 PyGenObject *gen = (PyGenObject *)self;
47 PyObject *res = NULL;
48 PyObject *error_type, *error_value, *error_traceback;
49
50 if (gen->gi_frame == NULL || _PyFrameHasCompleted(gen->gi_frame)) {
51 /* Generator isn't paused, so no need to close */
52 return;
53 }
54
55 if (PyAsyncGen_CheckExact(self)) {
56 PyAsyncGenObject *agen = (PyAsyncGenObject*)self;
57 PyObject *finalizer = agen->ag_finalizer;
58 if (finalizer && !agen->ag_closed) {
59 /* Save the current exception, if any. */
60 PyErr_Fetch(&error_type, &error_value, &error_traceback);
61
62 res = PyObject_CallOneArg(finalizer, self);
63
64 if (res == NULL) {
65 PyErr_WriteUnraisable(self);
66 } else {
67 Py_DECREF(res);
68 }
69 /* Restore the saved exception. */
70 PyErr_Restore(error_type, error_value, error_traceback);
71 return;
72 }
73 }
74
75 /* Save the current exception, if any. */
76 PyErr_Fetch(&error_type, &error_value, &error_traceback);
77
78 /* If `gen` is a coroutine, and if it was never awaited on,
79 issue a RuntimeWarning. */
80 if (gen->gi_code != NULL &&
81 ((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE &&
82 gen->gi_frame->f_lasti == -1)
83 {
84 _PyErr_WarnUnawaitedCoroutine((PyObject *)gen);
85 }
86 else {
87 res = gen_close(gen, NULL);
88 }
89
90 if (res == NULL) {
91 if (PyErr_Occurred()) {
92 PyErr_WriteUnraisable(self);
93 }
94 }
95 else {
96 Py_DECREF(res);
97 }
98
99 /* Restore the saved exception. */
100 PyErr_Restore(error_type, error_value, error_traceback);
101}
102
103static void
104gen_dealloc(PyGenObject *gen)
105{
106 PyObject *self = (PyObject *) gen;
107
108 _PyObject_GC_UNTRACK(gen);
109
110 if (gen->gi_weakreflist != NULL)
111 PyObject_ClearWeakRefs(self);
112
113 _PyObject_GC_TRACK(self);
114
115 if (PyObject_CallFinalizerFromDealloc(self))
116 return; /* resurrected. :( */
117
118 _PyObject_GC_UNTRACK(self);
119 if (PyAsyncGen_CheckExact(gen)) {
120 /* We have to handle this case for asynchronous generators
121 right here, because this code has to be between UNTRACK
122 and GC_Del. */
123 Py_CLEAR(((PyAsyncGenObject*)gen)->ag_finalizer);
124 }
125 if (gen->gi_frame != NULL) {
126 gen->gi_frame->f_gen = NULL;
127 Py_CLEAR(gen->gi_frame);
128 }
129 if (((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE) {
130 Py_CLEAR(((PyCoroObject *)gen)->cr_origin);
131 }
132 Py_CLEAR(gen->gi_code);
133 Py_CLEAR(gen->gi_name);
134 Py_CLEAR(gen->gi_qualname);
135 _PyErr_ClearExcState(&gen->gi_exc_state);
136 PyObject_GC_Del(gen);
137}
138
139static PySendResult
140gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
141 int exc, int closing)
142{
143 PyThreadState *tstate = _PyThreadState_GET();
144 PyFrameObject *f = gen->gi_frame;
145 PyObject *result;
146
147 *presult = NULL;
148 if (f != NULL && f->f_lasti < 0 && arg && arg != Py_None) {
149 const char *msg = "can't send non-None value to a "
150 "just-started generator";
151 if (PyCoro_CheckExact(gen)) {
152 msg = NON_INIT_CORO_MSG;
153 }
154 else if (PyAsyncGen_CheckExact(gen)) {
155 msg = "can't send non-None value to a "
156 "just-started async generator";
157 }
158 PyErr_SetString(PyExc_TypeError, msg);
159 return PYGEN_ERROR;
160 }
161 if (f != NULL && _PyFrame_IsExecuting(f)) {
162 const char *msg = "generator already executing";
163 if (PyCoro_CheckExact(gen)) {
164 msg = "coroutine already executing";
165 }
166 else if (PyAsyncGen_CheckExact(gen)) {
167 msg = "async generator already executing";
168 }
169 PyErr_SetString(PyExc_ValueError, msg);
170 return PYGEN_ERROR;
171 }
172 if (f == NULL || _PyFrameHasCompleted(f)) {
173 if (PyCoro_CheckExact(gen) && !closing) {
174 /* `gen` is an exhausted coroutine: raise an error,
175 except when called from gen_close(), which should
176 always be a silent method. */
177 PyErr_SetString(
178 PyExc_RuntimeError,
179 "cannot reuse already awaited coroutine");
180 }
181 else if (arg && !exc) {
182 /* `gen` is an exhausted generator:
183 only return value if called from send(). */
184 *presult = Py_None;
185 Py_INCREF(*presult);
186 return PYGEN_RETURN;
187 }
188 return PYGEN_ERROR;
189 }
190
191 assert(_PyFrame_IsRunnable(f));
192 assert(f->f_lasti >= 0 || ((unsigned char *)PyBytes_AS_STRING(f->f_code->co_code))[0] == GEN_START);
193 /* Push arg onto the frame's value stack */
194 result = arg ? arg : Py_None;
195 Py_INCREF(result);
196 gen->gi_frame->f_valuestack[gen->gi_frame->f_stackdepth] = result;
197 gen->gi_frame->f_stackdepth++;
198
199 /* Generators always return to their most recent caller, not
200 * necessarily their creator. */
201 Py_XINCREF(tstate->frame);
202 assert(f->f_back == NULL);
203 f->f_back = tstate->frame;
204
205 gen->gi_exc_state.previous_item = tstate->exc_info;
206 tstate->exc_info = &gen->gi_exc_state;
207
208 if (exc) {
209 assert(_PyErr_Occurred(tstate));
210 _PyErr_ChainStackItem(NULL);
211 }
212
213 result = _PyEval_EvalFrame(tstate, f, exc);
214 tstate->exc_info = gen->gi_exc_state.previous_item;
215 gen->gi_exc_state.previous_item = NULL;
216
217 /* Don't keep the reference to f_back any longer than necessary. It
218 * may keep a chain of frames alive or it could create a reference
219 * cycle. */
220 assert(f->f_back == tstate->frame);
221 Py_CLEAR(f->f_back);
222
223 /* If the generator just returned (as opposed to yielding), signal
224 * that the generator is exhausted. */
225 if (result) {
226 if (!_PyFrameHasCompleted(f)) {
227 *presult = result;
228 return PYGEN_NEXT;
229 }
230 assert(result == Py_None || !PyAsyncGen_CheckExact(gen));
231 if (result == Py_None && !PyAsyncGen_CheckExact(gen) && !arg) {
232 /* Return NULL if called by gen_iternext() */
233 Py_CLEAR(result);
234 }
235 }
236 else {
237 if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
238 const char *msg = "generator raised StopIteration";
239 if (PyCoro_CheckExact(gen)) {
240 msg = "coroutine raised StopIteration";
241 }
242 else if (PyAsyncGen_CheckExact(gen)) {
243 msg = "async generator raised StopIteration";
244 }
245 _PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg);
246 }
247 else if (PyAsyncGen_CheckExact(gen) &&
248 PyErr_ExceptionMatches(PyExc_StopAsyncIteration))
249 {
250 /* code in `gen` raised a StopAsyncIteration error:
251 raise a RuntimeError.
252 */
253 const char *msg = "async generator raised StopAsyncIteration";
254 _PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg);
255 }
256 }
257
258 /* generator can't be rerun, so release the frame */
259 /* first clean reference cycle through stored exception traceback */
260 _PyErr_ClearExcState(&gen->gi_exc_state);
261 gen->gi_frame->f_gen = NULL;
262 gen->gi_frame = NULL;
263 Py_DECREF(f);
264
265 *presult = result;
266 return result ? PYGEN_RETURN : PYGEN_ERROR;
267}
268
269static PySendResult
270PyGen_am_send(PyGenObject *gen, PyObject *arg, PyObject **result)
271{
272 return gen_send_ex2(gen, arg, result, 0, 0);
273}
274
275static PyObject *
276gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
277{
278 PyObject *result;
279 if (gen_send_ex2(gen, arg, &result, exc, closing) == PYGEN_RETURN) {
280 if (PyAsyncGen_CheckExact(gen)) {
281 assert(result == Py_None);
282 PyErr_SetNone(PyExc_StopAsyncIteration);
283 }
284 else if (result == Py_None) {
285 PyErr_SetNone(PyExc_StopIteration);
286 }
287 else {
288 _PyGen_SetStopIterationValue(result);
289 }
290 Py_CLEAR(result);
291 }
292 return result;
293}
294
295PyDoc_STRVAR(send_doc,
296"send(arg) -> send 'arg' into generator,\n\
297return next yielded value or raise StopIteration.");
298
299static PyObject *
300gen_send(PyGenObject *gen, PyObject *arg)
301{
302 return gen_send_ex(gen, arg, 0, 0);
303}
304
305PyDoc_STRVAR(close_doc,
306"close() -> raise GeneratorExit inside generator.");
307
308/*
309 * This helper function is used by gen_close and gen_throw to
310 * close a subiterator being delegated to by yield-from.
311 */
312
313static int
314gen_close_iter(PyObject *yf)
315{
316 PyObject *retval = NULL;
317 _Py_IDENTIFIER(close);
318
319 if (PyGen_CheckExact(yf) || PyCoro_CheckExact(yf)) {
320 retval = gen_close((PyGenObject *)yf, NULL);
321 if (retval == NULL)
322 return -1;
323 }
324 else {
325 PyObject *meth;
326 if (_PyObject_LookupAttrId(yf, &PyId_close, &meth) < 0) {
327 PyErr_WriteUnraisable(yf);
328 }
329 if (meth) {
330 retval = _PyObject_CallNoArg(meth);
331 Py_DECREF(meth);
332 if (retval == NULL)
333 return -1;
334 }
335 }
336 Py_XDECREF(retval);
337 return 0;
338}
339
340PyObject *
341_PyGen_yf(PyGenObject *gen)
342{
343 PyObject *yf = NULL;
344 PyFrameObject *f = gen->gi_frame;
345
346 if (f) {
347 PyObject *bytecode = f->f_code->co_code;
348 unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode);
349
350 if (f->f_lasti < 0) {
351 /* Return immediately if the frame didn't start yet. YIELD_FROM
352 always come after LOAD_CONST: a code object should not start
353 with YIELD_FROM */
354 assert(code[0] != YIELD_FROM);
355 return NULL;
356 }
357
358 if (code[(f->f_lasti+1)*sizeof(_Py_CODEUNIT)] != YIELD_FROM)
359 return NULL;
360 assert(f->f_stackdepth > 0);
361 yf = f->f_valuestack[f->f_stackdepth-1];
362 Py_INCREF(yf);
363 }
364
365 return yf;
366}
367
368static PyObject *
369gen_close(PyGenObject *gen, PyObject *args)
370{
371 PyObject *retval;
372 PyObject *yf = _PyGen_yf(gen);
373 int err = 0;
374
375 if (yf) {
376 PyFrameState state = gen->gi_frame->f_state;
377 gen->gi_frame->f_state = FRAME_EXECUTING;
378 err = gen_close_iter(yf);
379 gen->gi_frame->f_state = state;
380 Py_DECREF(yf);
381 }
382 if (err == 0)
383 PyErr_SetNone(PyExc_GeneratorExit);
384 retval = gen_send_ex(gen, Py_None, 1, 1);
385 if (retval) {
386 const char *msg = "generator ignored GeneratorExit";
387 if (PyCoro_CheckExact(gen)) {
388 msg = "coroutine ignored GeneratorExit";
389 } else if (PyAsyncGen_CheckExact(gen)) {
390 msg = ASYNC_GEN_IGNORED_EXIT_MSG;
391 }
392 Py_DECREF(retval);
393 PyErr_SetString(PyExc_RuntimeError, msg);
394 return NULL;
395 }
396 if (PyErr_ExceptionMatches(PyExc_StopIteration)
397 || PyErr_ExceptionMatches(PyExc_GeneratorExit)) {
398 PyErr_Clear(); /* ignore these errors */
399 Py_RETURN_NONE;
400 }
401 return NULL;
402}
403
404
405PyDoc_STRVAR(throw_doc,
406"throw(value)\n\
407throw(type[,value[,tb]])\n\
408\n\
409Raise exception in generator, return next yielded value or raise\n\
410StopIteration.");
411
412static PyObject *
413_gen_throw(PyGenObject *gen, int close_on_genexit,
414 PyObject *typ, PyObject *val, PyObject *tb)
415{
416 PyObject *yf = _PyGen_yf(gen);
417 _Py_IDENTIFIER(throw);
418
419 if (yf) {
420 PyObject *ret;
421 int err;
422 if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit) &&
423 close_on_genexit
424 ) {
425 /* Asynchronous generators *should not* be closed right away.
426 We have to allow some awaits to work it through, hence the
427 `close_on_genexit` parameter here.
428 */
429 PyFrameState state = gen->gi_frame->f_state;
430 gen->gi_frame->f_state = FRAME_EXECUTING;
431 err = gen_close_iter(yf);
432 gen->gi_frame->f_state = state;
433 Py_DECREF(yf);
434 if (err < 0)
435 return gen_send_ex(gen, Py_None, 1, 0);
436 goto throw_here;
437 }
438 if (PyGen_CheckExact(yf) || PyCoro_CheckExact(yf)) {
439 /* `yf` is a generator or a coroutine. */
440 PyThreadState *tstate = _PyThreadState_GET();
441 PyFrameObject *f = tstate->frame;
442
443 /* Since we are fast-tracking things by skipping the eval loop,
444 we need to update the current frame so the stack trace
445 will be reported correctly to the user. */
446 /* XXX We should probably be updating the current frame
447 somewhere in ceval.c. */
448 tstate->frame = gen->gi_frame;
449 /* Close the generator that we are currently iterating with
450 'yield from' or awaiting on with 'await'. */
451 PyFrameState state = gen->gi_frame->f_state;
452 gen->gi_frame->f_state = FRAME_EXECUTING;
453 ret = _gen_throw((PyGenObject *)yf, close_on_genexit,
454 typ, val, tb);
455 gen->gi_frame->f_state = state;
456 tstate->frame = f;
457 } else {
458 /* `yf` is an iterator or a coroutine-like object. */
459 PyObject *meth;
460 if (_PyObject_LookupAttrId(yf, &PyId_throw, &meth) < 0) {
461 Py_DECREF(yf);
462 return NULL;
463 }
464 if (meth == NULL) {
465 Py_DECREF(yf);
466 goto throw_here;
467 }
468 PyFrameState state = gen->gi_frame->f_state;
469 gen->gi_frame->f_state = FRAME_EXECUTING;
470 ret = PyObject_CallFunctionObjArgs(meth, typ, val, tb, NULL);
471 gen->gi_frame->f_state = state;
472 Py_DECREF(meth);
473 }
474 Py_DECREF(yf);
475 if (!ret) {
476 PyObject *val;
477 /* Pop subiterator from stack */
478 assert(gen->gi_frame->f_stackdepth > 0);
479 gen->gi_frame->f_stackdepth--;
480 ret = gen->gi_frame->f_valuestack[gen->gi_frame->f_stackdepth];
481 assert(ret == yf);
482 Py_DECREF(ret);
483 /* Termination repetition of YIELD_FROM */
484 assert(gen->gi_frame->f_lasti >= 0);
485 gen->gi_frame->f_lasti += 1;
486 if (_PyGen_FetchStopIterationValue(&val) == 0) {
487 ret = gen_send(gen, val);
488 Py_DECREF(val);
489 } else {
490 ret = gen_send_ex(gen, Py_None, 1, 0);
491 }
492 }
493 return ret;
494 }
495
496throw_here:
497 /* First, check the traceback argument, replacing None with
498 NULL. */
499 if (tb == Py_None) {
500 tb = NULL;
501 }
502 else if (tb != NULL && !PyTraceBack_Check(tb)) {
503 PyErr_SetString(PyExc_TypeError,
504 "throw() third argument must be a traceback object");
505 return NULL;
506 }
507
508 Py_INCREF(typ);
509 Py_XINCREF(val);
510 Py_XINCREF(tb);
511
512 if (PyExceptionClass_Check(typ))
513 PyErr_NormalizeException(&typ, &val, &tb);
514
515 else if (PyExceptionInstance_Check(typ)) {
516 /* Raising an instance. The value should be a dummy. */
517 if (val && val != Py_None) {
518 PyErr_SetString(PyExc_TypeError,
519 "instance exception may not have a separate value");
520 goto failed_throw;
521 }
522 else {
523 /* Normalize to raise <class>, <instance> */
524 Py_XDECREF(val);
525 val = typ;
526 typ = PyExceptionInstance_Class(typ);
527 Py_INCREF(typ);
528
529 if (tb == NULL)
530 /* Returns NULL if there's no traceback */
531 tb = PyException_GetTraceback(val);
532 }
533 }
534 else {
535 /* Not something you can raise. throw() fails. */
536 PyErr_Format(PyExc_TypeError,
537 "exceptions must be classes or instances "
538 "deriving from BaseException, not %s",
539 Py_TYPE(typ)->tp_name);
540 goto failed_throw;
541 }
542
543 PyErr_Restore(typ, val, tb);
544 return gen_send_ex(gen, Py_None, 1, 0);
545
546failed_throw:
547 /* Didn't use our arguments, so restore their original refcounts */
548 Py_DECREF(typ);
549 Py_XDECREF(val);
550 Py_XDECREF(tb);
551 return NULL;
552}
553
554
555static PyObject *
556gen_throw(PyGenObject *gen, PyObject *args)
557{
558 PyObject *typ;
559 PyObject *tb = NULL;
560 PyObject *val = NULL;
561
562 if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb)) {
563 return NULL;
564 }
565
566 return _gen_throw(gen, 1, typ, val, tb);
567}
568
569
570static PyObject *
571gen_iternext(PyGenObject *gen)
572{
573 PyObject *result;
574 assert(PyGen_CheckExact(gen) || PyCoro_CheckExact(gen));
575 if (gen_send_ex2(gen, NULL, &result, 0, 0) == PYGEN_RETURN) {
576 if (result != Py_None) {
577 _PyGen_SetStopIterationValue(result);
578 }
579 Py_CLEAR(result);
580 }
581 return result;
582}
583
584/*
585 * Set StopIteration with specified value. Value can be arbitrary object
586 * or NULL.
587 *
588 * Returns 0 if StopIteration is set and -1 if any other exception is set.
589 */
590int
591_PyGen_SetStopIterationValue(PyObject *value)
592{
593 PyObject *e;
594
595 if (value == NULL ||
596 (!PyTuple_Check(value) && !PyExceptionInstance_Check(value)))
597 {
598 /* Delay exception instantiation if we can */
599 PyErr_SetObject(PyExc_StopIteration, value);
600 return 0;
601 }
602 /* Construct an exception instance manually with
603 * PyObject_CallOneArg and pass it to PyErr_SetObject.
604 *
605 * We do this to handle a situation when "value" is a tuple, in which
606 * case PyErr_SetObject would set the value of StopIteration to
607 * the first element of the tuple.
608 *
609 * (See PyErr_SetObject/_PyErr_CreateException code for details.)
610 */
611 e = PyObject_CallOneArg(PyExc_StopIteration, value);
612 if (e == NULL) {
613 return -1;
614 }
615 PyErr_SetObject(PyExc_StopIteration, e);
616 Py_DECREF(e);
617 return 0;
618}
619
620/*
621 * If StopIteration exception is set, fetches its 'value'
622 * attribute if any, otherwise sets pvalue to None.
623 *
624 * Returns 0 if no exception or StopIteration is set.
625 * If any other exception is set, returns -1 and leaves
626 * pvalue unchanged.
627 */
628
629int
630_PyGen_FetchStopIterationValue(PyObject **pvalue)
631{
632 PyObject *et, *ev, *tb;
633 PyObject *value = NULL;
634
635 if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
636 PyErr_Fetch(&et, &ev, &tb);
637 if (ev) {
638 /* exception will usually be normalised already */
639 if (PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
640 value = ((PyStopIterationObject *)ev)->value;
641 Py_INCREF(value);
642 Py_DECREF(ev);
643 } else if (et == PyExc_StopIteration && !PyTuple_Check(ev)) {
644 /* Avoid normalisation and take ev as value.
645 *
646 * Normalization is required if the value is a tuple, in
647 * that case the value of StopIteration would be set to
648 * the first element of the tuple.
649 *
650 * (See _PyErr_CreateException code for details.)
651 */
652 value = ev;
653 } else {
654 /* normalisation required */
655 PyErr_NormalizeException(&et, &ev, &tb);
656 if (!PyObject_TypeCheck(ev, (PyTypeObject *)PyExc_StopIteration)) {
657 PyErr_Restore(et, ev, tb);
658 return -1;
659 }
660 value = ((PyStopIterationObject *)ev)->value;
661 Py_INCREF(value);
662 Py_DECREF(ev);
663 }
664 }
665 Py_XDECREF(et);
666 Py_XDECREF(tb);
667 } else if (PyErr_Occurred()) {
668 return -1;
669 }
670 if (value == NULL) {
671 value = Py_None;
672 Py_INCREF(value);
673 }
674 *pvalue = value;
675 return 0;
676}
677
678static PyObject *
679gen_repr(PyGenObject *gen)
680{
681 return PyUnicode_FromFormat("<generator object %S at %p>",
682 gen->gi_qualname, gen);
683}
684
685static PyObject *
686gen_get_name(PyGenObject *op, void *Py_UNUSED(ignored))
687{
688 Py_INCREF(op->gi_name);
689 return op->gi_name;
690}
691
692static int
693gen_set_name(PyGenObject *op, PyObject *value, void *Py_UNUSED(ignored))
694{
695 /* Not legal to del gen.gi_name or to set it to anything
696 * other than a string object. */
697 if (value == NULL || !PyUnicode_Check(value)) {
698 PyErr_SetString(PyExc_TypeError,
699 "__name__ must be set to a string object");
700 return -1;
701 }
702 Py_INCREF(value);
703 Py_XSETREF(op->gi_name, value);
704 return 0;
705}
706
707static PyObject *
708gen_get_qualname(PyGenObject *op, void *Py_UNUSED(ignored))
709{
710 Py_INCREF(op->gi_qualname);
711 return op->gi_qualname;
712}
713
714static int
715gen_set_qualname(PyGenObject *op, PyObject *value, void *Py_UNUSED(ignored))
716{
717 /* Not legal to del gen.__qualname__ or to set it to anything
718 * other than a string object. */
719 if (value == NULL || !PyUnicode_Check(value)) {
720 PyErr_SetString(PyExc_TypeError,
721 "__qualname__ must be set to a string object");
722 return -1;
723 }
724 Py_INCREF(value);
725 Py_XSETREF(op->gi_qualname, value);
726 return 0;
727}
728
729static PyObject *
730gen_getyieldfrom(PyGenObject *gen, void *Py_UNUSED(ignored))
731{
732 PyObject *yf = _PyGen_yf(gen);
733 if (yf == NULL)
734 Py_RETURN_NONE;
735 return yf;
736}
737
738
739static PyObject *
740gen_getrunning(PyGenObject *gen, void *Py_UNUSED(ignored))
741{
742 if (gen->gi_frame == NULL) {
743 Py_RETURN_FALSE;
744 }
745 return PyBool_FromLong(_PyFrame_IsExecuting(gen->gi_frame));
746}
747
748static PyGetSetDef gen_getsetlist[] = {
749 {"__name__", (getter)gen_get_name, (setter)gen_set_name,
750 PyDoc_STR("name of the generator")},
751 {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
752 PyDoc_STR("qualified name of the generator")},
753 {"gi_yieldfrom", (getter)gen_getyieldfrom, NULL,
754 PyDoc_STR("object being iterated by yield from, or None")},
755 {"gi_running", (getter)gen_getrunning, NULL, NULL},
756 {NULL} /* Sentinel */
757};
758
759static PyMemberDef gen_memberlist[] = {
760 {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), READONLY|PY_AUDIT_READ},
761 {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), READONLY|PY_AUDIT_READ},
762 {NULL} /* Sentinel */
763};
764
765static PyMethodDef gen_methods[] = {
766 {"send",(PyCFunction)gen_send, METH_O, send_doc},
767 {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc},
768 {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc},
769 {NULL, NULL} /* Sentinel */
770};
771
772static PyAsyncMethods gen_as_async = {
773 0, /* am_await */
774 0, /* am_aiter */
775 0, /* am_anext */
776 (sendfunc)PyGen_am_send, /* am_send */
777};
778
779
780PyTypeObject PyGen_Type = {
781 PyVarObject_HEAD_INIT(&PyType_Type, 0)
782 "generator", /* tp_name */
783 sizeof(PyGenObject), /* tp_basicsize */
784 0, /* tp_itemsize */
785 /* methods */
786 (destructor)gen_dealloc, /* tp_dealloc */
787 0, /* tp_vectorcall_offset */
788 0, /* tp_getattr */
789 0, /* tp_setattr */
790 &gen_as_async, /* tp_as_async */
791 (reprfunc)gen_repr, /* tp_repr */
792 0, /* tp_as_number */
793 0, /* tp_as_sequence */
794 0, /* tp_as_mapping */
795 0, /* tp_hash */
796 0, /* tp_call */
797 0, /* tp_str */
798 PyObject_GenericGetAttr, /* tp_getattro */
799 0, /* tp_setattro */
800 0, /* tp_as_buffer */
801 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
802 0, /* tp_doc */
803 (traverseproc)gen_traverse, /* tp_traverse */
804 0, /* tp_clear */
805 0, /* tp_richcompare */
806 offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */
807 PyObject_SelfIter, /* tp_iter */
808 (iternextfunc)gen_iternext, /* tp_iternext */
809 gen_methods, /* tp_methods */
810 gen_memberlist, /* tp_members */
811 gen_getsetlist, /* tp_getset */
812 0, /* tp_base */
813 0, /* tp_dict */
814
815 0, /* tp_descr_get */
816 0, /* tp_descr_set */
817 0, /* tp_dictoffset */
818 0, /* tp_init */
819 0, /* tp_alloc */
820 0, /* tp_new */
821 0, /* tp_free */
822 0, /* tp_is_gc */
823 0, /* tp_bases */
824 0, /* tp_mro */
825 0, /* tp_cache */
826 0, /* tp_subclasses */
827 0, /* tp_weaklist */
828 0, /* tp_del */
829 0, /* tp_version_tag */
830 _PyGen_Finalize, /* tp_finalize */
831};
832
833static PyObject *
834gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,
835 PyObject *name, PyObject *qualname)
836{
837 PyGenObject *gen = PyObject_GC_New(PyGenObject, type);
838 if (gen == NULL) {
839 Py_DECREF(f);
840 return NULL;
841 }
842 gen->gi_frame = f;
843 f->f_gen = (PyObject *) gen;
844 Py_INCREF(f->f_code);
845 gen->gi_code = (PyObject *)(f->f_code);
846 gen->gi_weakreflist = NULL;
847 gen->gi_exc_state.exc_type = NULL;
848 gen->gi_exc_state.exc_value = NULL;
849 gen->gi_exc_state.exc_traceback = NULL;
850 gen->gi_exc_state.previous_item = NULL;
851 if (name != NULL)
852 gen->gi_name = name;
853 else
854 gen->gi_name = ((PyCodeObject *)gen->gi_code)->co_name;
855 Py_INCREF(gen->gi_name);
856 if (qualname != NULL)
857 gen->gi_qualname = qualname;
858 else
859 gen->gi_qualname = gen->gi_name;
860 Py_INCREF(gen->gi_qualname);
861 _PyObject_GC_TRACK(gen);
862 return (PyObject *)gen;
863}
864
865PyObject *
866PyGen_NewWithQualName(PyFrameObject *f, PyObject *name, PyObject *qualname)
867{
868 return gen_new_with_qualname(&PyGen_Type, f, name, qualname);
869}
870
871PyObject *
872PyGen_New(PyFrameObject *f)
873{
874 return gen_new_with_qualname(&PyGen_Type, f, NULL, NULL);
875}
876
877/* Coroutine Object */
878
879typedef struct {
880 PyObject_HEAD
881 PyCoroObject *cw_coroutine;
882} PyCoroWrapper;
883
884static int
885gen_is_coroutine(PyObject *o)
886{
887 if (PyGen_CheckExact(o)) {
888 PyCodeObject *code = (PyCodeObject *)((PyGenObject*)o)->gi_code;
889 if (code->co_flags & CO_ITERABLE_COROUTINE) {
890 return 1;
891 }
892 }
893 return 0;
894}
895
896/*
897 * This helper function returns an awaitable for `o`:
898 * - `o` if `o` is a coroutine-object;
899 * - `type(o)->tp_as_async->am_await(o)`
900 *
901 * Raises a TypeError if it's not possible to return
902 * an awaitable and returns NULL.
903 */
904PyObject *
905_PyCoro_GetAwaitableIter(PyObject *o)
906{
907 unaryfunc getter = NULL;
908 PyTypeObject *ot;
909
910 if (PyCoro_CheckExact(o) || gen_is_coroutine(o)) {
911 /* 'o' is a coroutine. */
912 Py_INCREF(o);
913 return o;
914 }
915
916 ot = Py_TYPE(o);
917 if (ot->tp_as_async != NULL) {
918 getter = ot->tp_as_async->am_await;
919 }
920 if (getter != NULL) {
921 PyObject *res = (*getter)(o);
922 if (res != NULL) {
923 if (PyCoro_CheckExact(res) || gen_is_coroutine(res)) {
924 /* __await__ must return an *iterator*, not
925 a coroutine or another awaitable (see PEP 492) */
926 PyErr_SetString(PyExc_TypeError,
927 "__await__() returned a coroutine");
928 Py_CLEAR(res);
929 } else if (!PyIter_Check(res)) {
930 PyErr_Format(PyExc_TypeError,
931 "__await__() returned non-iterator "
932 "of type '%.100s'",
933 Py_TYPE(res)->tp_name);
934 Py_CLEAR(res);
935 }
936 }
937 return res;
938 }
939
940 PyErr_Format(PyExc_TypeError,
941 "object %.100s can't be used in 'await' expression",
942 ot->tp_name);
943 return NULL;
944}
945
946static PyObject *
947coro_repr(PyCoroObject *coro)
948{
949 return PyUnicode_FromFormat("<coroutine object %S at %p>",
950 coro->cr_qualname, coro);
951}
952
953static PyObject *
954coro_await(PyCoroObject *coro)
955{
956 PyCoroWrapper *cw = PyObject_GC_New(PyCoroWrapper, &_PyCoroWrapper_Type);
957 if (cw == NULL) {
958 return NULL;
959 }
960 Py_INCREF(coro);
961 cw->cw_coroutine = coro;
962 _PyObject_GC_TRACK(cw);
963 return (PyObject *)cw;
964}
965
966static PyObject *
967coro_get_cr_await(PyCoroObject *coro, void *Py_UNUSED(ignored))
968{
969 PyObject *yf = _PyGen_yf((PyGenObject *) coro);
970 if (yf == NULL)
971 Py_RETURN_NONE;
972 return yf;
973}
974
975static PyObject *
976cr_getrunning(PyCoroObject *coro, void *Py_UNUSED(ignored))
977{
978 if (coro->cr_frame == NULL) {
979 Py_RETURN_FALSE;
980 }
981 return PyBool_FromLong(_PyFrame_IsExecuting(coro->cr_frame));
982}
983
984static PyGetSetDef coro_getsetlist[] = {
985 {"__name__", (getter)gen_get_name, (setter)gen_set_name,
986 PyDoc_STR("name of the coroutine")},
987 {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
988 PyDoc_STR("qualified name of the coroutine")},
989 {"cr_await", (getter)coro_get_cr_await, NULL,
990 PyDoc_STR("object being awaited on, or None")},
991 {"cr_running", (getter)cr_getrunning, NULL, NULL},
992 {NULL} /* Sentinel */
993};
994
995static PyMemberDef coro_memberlist[] = {
996 {"cr_frame", T_OBJECT, offsetof(PyCoroObject, cr_frame), READONLY|PY_AUDIT_READ},
997 {"cr_code", T_OBJECT, offsetof(PyCoroObject, cr_code), READONLY|PY_AUDIT_READ},
998 {"cr_origin", T_OBJECT, offsetof(PyCoroObject, cr_origin), READONLY},
999 {NULL} /* Sentinel */
1000};
1001
1002PyDoc_STRVAR(coro_send_doc,
1003"send(arg) -> send 'arg' into coroutine,\n\
1004return next iterated value or raise StopIteration.");
1005
1006PyDoc_STRVAR(coro_throw_doc,
1007"throw(value)\n\
1008throw(type[,value[,traceback]])\n\
1009\n\
1010Raise exception in coroutine, return next iterated value or raise\n\
1011StopIteration.");
1012
1013PyDoc_STRVAR(coro_close_doc,
1014"close() -> raise GeneratorExit inside coroutine.");
1015
1016static PyMethodDef coro_methods[] = {
1017 {"send",(PyCFunction)gen_send, METH_O, coro_send_doc},
1018 {"throw",(PyCFunction)gen_throw, METH_VARARGS, coro_throw_doc},
1019 {"close",(PyCFunction)gen_close, METH_NOARGS, coro_close_doc},
1020 {NULL, NULL} /* Sentinel */
1021};
1022
1023static PyAsyncMethods coro_as_async = {
1024 (unaryfunc)coro_await, /* am_await */
1025 0, /* am_aiter */
1026 0, /* am_anext */
1027 (sendfunc)PyGen_am_send, /* am_send */
1028};
1029
1030PyTypeObject PyCoro_Type = {
1031 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1032 "coroutine", /* tp_name */
1033 sizeof(PyCoroObject), /* tp_basicsize */
1034 0, /* tp_itemsize */
1035 /* methods */
1036 (destructor)gen_dealloc, /* tp_dealloc */
1037 0, /* tp_vectorcall_offset */
1038 0, /* tp_getattr */
1039 0, /* tp_setattr */
1040 &coro_as_async, /* tp_as_async */
1041 (reprfunc)coro_repr, /* tp_repr */
1042 0, /* tp_as_number */
1043 0, /* tp_as_sequence */
1044 0, /* tp_as_mapping */
1045 0, /* tp_hash */
1046 0, /* tp_call */
1047 0, /* tp_str */
1048 PyObject_GenericGetAttr, /* tp_getattro */
1049 0, /* tp_setattro */
1050 0, /* tp_as_buffer */
1051 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1052 0, /* tp_doc */
1053 (traverseproc)gen_traverse, /* tp_traverse */
1054 0, /* tp_clear */
1055 0, /* tp_richcompare */
1056 offsetof(PyCoroObject, cr_weakreflist), /* tp_weaklistoffset */
1057 0, /* tp_iter */
1058 0, /* tp_iternext */
1059 coro_methods, /* tp_methods */
1060 coro_memberlist, /* tp_members */
1061 coro_getsetlist, /* tp_getset */
1062 0, /* tp_base */
1063 0, /* tp_dict */
1064 0, /* tp_descr_get */
1065 0, /* tp_descr_set */
1066 0, /* tp_dictoffset */
1067 0, /* tp_init */
1068 0, /* tp_alloc */
1069 0, /* tp_new */
1070 0, /* tp_free */
1071 0, /* tp_is_gc */
1072 0, /* tp_bases */
1073 0, /* tp_mro */
1074 0, /* tp_cache */
1075 0, /* tp_subclasses */
1076 0, /* tp_weaklist */
1077 0, /* tp_del */
1078 0, /* tp_version_tag */
1079 _PyGen_Finalize, /* tp_finalize */
1080};
1081
1082static void
1083coro_wrapper_dealloc(PyCoroWrapper *cw)
1084{
1085 _PyObject_GC_UNTRACK((PyObject *)cw);
1086 Py_CLEAR(cw->cw_coroutine);
1087 PyObject_GC_Del(cw);
1088}
1089
1090static PyObject *
1091coro_wrapper_iternext(PyCoroWrapper *cw)
1092{
1093 return gen_iternext((PyGenObject *)cw->cw_coroutine);
1094}
1095
1096static PyObject *
1097coro_wrapper_send(PyCoroWrapper *cw, PyObject *arg)
1098{
1099 return gen_send((PyGenObject *)cw->cw_coroutine, arg);
1100}
1101
1102static PyObject *
1103coro_wrapper_throw(PyCoroWrapper *cw, PyObject *args)
1104{
1105 return gen_throw((PyGenObject *)cw->cw_coroutine, args);
1106}
1107
1108static PyObject *
1109coro_wrapper_close(PyCoroWrapper *cw, PyObject *args)
1110{
1111 return gen_close((PyGenObject *)cw->cw_coroutine, args);
1112}
1113
1114static int
1115coro_wrapper_traverse(PyCoroWrapper *cw, visitproc visit, void *arg)
1116{
1117 Py_VISIT((PyObject *)cw->cw_coroutine);
1118 return 0;
1119}
1120
1121static PyMethodDef coro_wrapper_methods[] = {
1122 {"send",(PyCFunction)coro_wrapper_send, METH_O, coro_send_doc},
1123 {"throw",(PyCFunction)coro_wrapper_throw, METH_VARARGS, coro_throw_doc},
1124 {"close",(PyCFunction)coro_wrapper_close, METH_NOARGS, coro_close_doc},
1125 {NULL, NULL} /* Sentinel */
1126};
1127
1128PyTypeObject _PyCoroWrapper_Type = {
1129 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1130 "coroutine_wrapper",
1131 sizeof(PyCoroWrapper), /* tp_basicsize */
1132 0, /* tp_itemsize */
1133 (destructor)coro_wrapper_dealloc, /* destructor tp_dealloc */
1134 0, /* tp_vectorcall_offset */
1135 0, /* tp_getattr */
1136 0, /* tp_setattr */
1137 0, /* tp_as_async */
1138 0, /* tp_repr */
1139 0, /* tp_as_number */
1140 0, /* tp_as_sequence */
1141 0, /* tp_as_mapping */
1142 0, /* tp_hash */
1143 0, /* tp_call */
1144 0, /* tp_str */
1145 PyObject_GenericGetAttr, /* tp_getattro */
1146 0, /* tp_setattro */
1147 0, /* tp_as_buffer */
1148 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1149 "A wrapper object implementing __await__ for coroutines.",
1150 (traverseproc)coro_wrapper_traverse, /* tp_traverse */
1151 0, /* tp_clear */
1152 0, /* tp_richcompare */
1153 0, /* tp_weaklistoffset */
1154 PyObject_SelfIter, /* tp_iter */
1155 (iternextfunc)coro_wrapper_iternext, /* tp_iternext */
1156 coro_wrapper_methods, /* tp_methods */
1157 0, /* tp_members */
1158 0, /* tp_getset */
1159 0, /* tp_base */
1160 0, /* tp_dict */
1161 0, /* tp_descr_get */
1162 0, /* tp_descr_set */
1163 0, /* tp_dictoffset */
1164 0, /* tp_init */
1165 0, /* tp_alloc */
1166 0, /* tp_new */
1167 0, /* tp_free */
1168};
1169
1170static PyObject *
1171compute_cr_origin(int origin_depth)
1172{
1173 PyFrameObject *frame = PyEval_GetFrame();
1174 /* First count how many frames we have */
1175 int frame_count = 0;
1176 for (; frame && frame_count < origin_depth; ++frame_count) {
1177 frame = frame->f_back;
1178 }
1179
1180 /* Now collect them */
1181 PyObject *cr_origin = PyTuple_New(frame_count);
1182 if (cr_origin == NULL) {
1183 return NULL;
1184 }
1185 frame = PyEval_GetFrame();
1186 for (int i = 0; i < frame_count; ++i) {
1187 PyCodeObject *code = frame->f_code;
1188 PyObject *frameinfo = Py_BuildValue("OiO",
1189 code->co_filename,
1190 PyFrame_GetLineNumber(frame),
1191 code->co_name);
1192 if (!frameinfo) {
1193 Py_DECREF(cr_origin);
1194 return NULL;
1195 }
1196 PyTuple_SET_ITEM(cr_origin, i, frameinfo);
1197 frame = frame->f_back;
1198 }
1199
1200 return cr_origin;
1201}
1202
1203PyObject *
1204PyCoro_New(PyFrameObject *f, PyObject *name, PyObject *qualname)
1205{
1206 PyObject *coro = gen_new_with_qualname(&PyCoro_Type, f, name, qualname);
1207 if (!coro) {
1208 return NULL;
1209 }
1210
1211 PyThreadState *tstate = _PyThreadState_GET();
1212 int origin_depth = tstate->coroutine_origin_tracking_depth;
1213
1214 if (origin_depth == 0) {
1215 ((PyCoroObject *)coro)->cr_origin = NULL;
1216 } else {
1217 PyObject *cr_origin = compute_cr_origin(origin_depth);
1218 ((PyCoroObject *)coro)->cr_origin = cr_origin;
1219 if (!cr_origin) {
1220 Py_DECREF(coro);
1221 return NULL;
1222 }
1223 }
1224
1225 return coro;
1226}
1227
1228
1229/* ========= Asynchronous Generators ========= */
1230
1231
1232typedef enum {
1233 AWAITABLE_STATE_INIT, /* new awaitable, has not yet been iterated */
1234 AWAITABLE_STATE_ITER, /* being iterated */
1235 AWAITABLE_STATE_CLOSED, /* closed */
1236} AwaitableState;
1237
1238
1239typedef struct PyAsyncGenASend {
1240 PyObject_HEAD
1241 PyAsyncGenObject *ags_gen;
1242
1243 /* Can be NULL, when in the __anext__() mode
1244 (equivalent of "asend(None)") */
1245 PyObject *ags_sendval;
1246
1247 AwaitableState ags_state;
1248} PyAsyncGenASend;
1249
1250
1251typedef struct PyAsyncGenAThrow {
1252 PyObject_HEAD
1253 PyAsyncGenObject *agt_gen;
1254
1255 /* Can be NULL, when in the "aclose()" mode
1256 (equivalent of "athrow(GeneratorExit)") */
1257 PyObject *agt_args;
1258
1259 AwaitableState agt_state;
1260} PyAsyncGenAThrow;
1261
1262
1263typedef struct _PyAsyncGenWrappedValue {
1264 PyObject_HEAD
1265 PyObject *agw_val;
1266} _PyAsyncGenWrappedValue;
1267
1268
1269#define _PyAsyncGenWrappedValue_CheckExact(o) \
1270 Py_IS_TYPE(o, &_PyAsyncGenWrappedValue_Type)
1271
1272#define PyAsyncGenASend_CheckExact(o) \
1273 Py_IS_TYPE(o, &_PyAsyncGenASend_Type)
1274
1275
1276static int
1277async_gen_traverse(PyAsyncGenObject *gen, visitproc visit, void *arg)
1278{
1279 Py_VISIT(gen->ag_finalizer);
1280 return gen_traverse((PyGenObject*)gen, visit, arg);
1281}
1282
1283
1284static PyObject *
1285async_gen_repr(PyAsyncGenObject *o)
1286{
1287 return PyUnicode_FromFormat("<async_generator object %S at %p>",
1288 o->ag_qualname, o);
1289}
1290
1291
1292static int
1293async_gen_init_hooks(PyAsyncGenObject *o)
1294{
1295 PyThreadState *tstate;
1296 PyObject *finalizer;
1297 PyObject *firstiter;
1298
1299 if (o->ag_hooks_inited) {
1300 return 0;
1301 }
1302
1303 o->ag_hooks_inited = 1;
1304
1305 tstate = _PyThreadState_GET();
1306
1307 finalizer = tstate->async_gen_finalizer;
1308 if (finalizer) {
1309 Py_INCREF(finalizer);
1310 o->ag_finalizer = finalizer;
1311 }
1312
1313 firstiter = tstate->async_gen_firstiter;
1314 if (firstiter) {
1315 PyObject *res;
1316
1317 Py_INCREF(firstiter);
1318 res = PyObject_CallOneArg(firstiter, (PyObject *)o);
1319 Py_DECREF(firstiter);
1320 if (res == NULL) {
1321 return 1;
1322 }
1323 Py_DECREF(res);
1324 }
1325
1326 return 0;
1327}
1328
1329
1330static PyObject *
1331async_gen_anext(PyAsyncGenObject *o)
1332{
1333 if (async_gen_init_hooks(o)) {
1334 return NULL;
1335 }
1336 return async_gen_asend_new(o, NULL);
1337}
1338
1339
1340static PyObject *
1341async_gen_asend(PyAsyncGenObject *o, PyObject *arg)
1342{
1343 if (async_gen_init_hooks(o)) {
1344 return NULL;
1345 }
1346 return async_gen_asend_new(o, arg);
1347}
1348
1349
1350static PyObject *
1351async_gen_aclose(PyAsyncGenObject *o, PyObject *arg)
1352{
1353 if (async_gen_init_hooks(o)) {
1354 return NULL;
1355 }
1356 return async_gen_athrow_new(o, NULL);
1357}
1358
1359static PyObject *
1360async_gen_athrow(PyAsyncGenObject *o, PyObject *args)
1361{
1362 if (async_gen_init_hooks(o)) {
1363 return NULL;
1364 }
1365 return async_gen_athrow_new(o, args);
1366}
1367
1368
1369static PyGetSetDef async_gen_getsetlist[] = {
1370 {"__name__", (getter)gen_get_name, (setter)gen_set_name,
1371 PyDoc_STR("name of the async generator")},
1372 {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
1373 PyDoc_STR("qualified name of the async generator")},
1374 {"ag_await", (getter)coro_get_cr_await, NULL,
1375 PyDoc_STR("object being awaited on, or None")},
1376 {NULL} /* Sentinel */
1377};
1378
1379static PyMemberDef async_gen_memberlist[] = {
1380 {"ag_frame", T_OBJECT, offsetof(PyAsyncGenObject, ag_frame), READONLY|PY_AUDIT_READ},
1381 {"ag_running", T_BOOL, offsetof(PyAsyncGenObject, ag_running_async),
1382 READONLY},
1383 {"ag_code", T_OBJECT, offsetof(PyAsyncGenObject, ag_code), READONLY|PY_AUDIT_READ},
1384 {NULL} /* Sentinel */
1385};
1386
1387PyDoc_STRVAR(async_aclose_doc,
1388"aclose() -> raise GeneratorExit inside generator.");
1389
1390PyDoc_STRVAR(async_asend_doc,
1391"asend(v) -> send 'v' in generator.");
1392
1393PyDoc_STRVAR(async_athrow_doc,
1394"athrow(typ[,val[,tb]]) -> raise exception in generator.");
1395
1396static PyMethodDef async_gen_methods[] = {
1397 {"asend", (PyCFunction)async_gen_asend, METH_O, async_asend_doc},
1398 {"athrow",(PyCFunction)async_gen_athrow, METH_VARARGS, async_athrow_doc},
1399 {"aclose", (PyCFunction)async_gen_aclose, METH_NOARGS, async_aclose_doc},
1400 {"__class_getitem__", (PyCFunction)Py_GenericAlias,
1401 METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
1402 {NULL, NULL} /* Sentinel */
1403};
1404
1405
1406static PyAsyncMethods async_gen_as_async = {
1407 0, /* am_await */
1408 PyObject_SelfIter, /* am_aiter */
1409 (unaryfunc)async_gen_anext, /* am_anext */
1410 (sendfunc)PyGen_am_send, /* am_send */
1411};
1412
1413
1414PyTypeObject PyAsyncGen_Type = {
1415 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1416 "async_generator", /* tp_name */
1417 sizeof(PyAsyncGenObject), /* tp_basicsize */
1418 0, /* tp_itemsize */
1419 /* methods */
1420 (destructor)gen_dealloc, /* tp_dealloc */
1421 0, /* tp_vectorcall_offset */
1422 0, /* tp_getattr */
1423 0, /* tp_setattr */
1424 &async_gen_as_async, /* tp_as_async */
1425 (reprfunc)async_gen_repr, /* tp_repr */
1426 0, /* tp_as_number */
1427 0, /* tp_as_sequence */
1428 0, /* tp_as_mapping */
1429 0, /* tp_hash */
1430 0, /* tp_call */
1431 0, /* tp_str */
1432 PyObject_GenericGetAttr, /* tp_getattro */
1433 0, /* tp_setattro */
1434 0, /* tp_as_buffer */
1435 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1436 0, /* tp_doc */
1437 (traverseproc)async_gen_traverse, /* tp_traverse */
1438 0, /* tp_clear */
1439 0, /* tp_richcompare */
1440 offsetof(PyAsyncGenObject, ag_weakreflist), /* tp_weaklistoffset */
1441 0, /* tp_iter */
1442 0, /* tp_iternext */
1443 async_gen_methods, /* tp_methods */
1444 async_gen_memberlist, /* tp_members */
1445 async_gen_getsetlist, /* tp_getset */
1446 0, /* tp_base */
1447 0, /* tp_dict */
1448 0, /* tp_descr_get */
1449 0, /* tp_descr_set */
1450 0, /* tp_dictoffset */
1451 0, /* tp_init */
1452 0, /* tp_alloc */
1453 0, /* tp_new */
1454 0, /* tp_free */
1455 0, /* tp_is_gc */
1456 0, /* tp_bases */
1457 0, /* tp_mro */
1458 0, /* tp_cache */
1459 0, /* tp_subclasses */
1460 0, /* tp_weaklist */
1461 0, /* tp_del */
1462 0, /* tp_version_tag */
1463 _PyGen_Finalize, /* tp_finalize */
1464};
1465
1466
1467static struct _Py_async_gen_state *
1468get_async_gen_state(void)
1469{
1470 PyInterpreterState *interp = _PyInterpreterState_GET();
1471 return &interp->async_gen;
1472}
1473
1474
1475PyObject *
1476PyAsyncGen_New(PyFrameObject *f, PyObject *name, PyObject *qualname)
1477{
1478 PyAsyncGenObject *o;
1479 o = (PyAsyncGenObject *)gen_new_with_qualname(
1480 &PyAsyncGen_Type, f, name, qualname);
1481 if (o == NULL) {
1482 return NULL;
1483 }
1484 o->ag_finalizer = NULL;
1485 o->ag_closed = 0;
1486 o->ag_hooks_inited = 0;
1487 o->ag_running_async = 0;
1488 return (PyObject*)o;
1489}
1490
1491
1492void
1493_PyAsyncGen_ClearFreeLists(PyInterpreterState *interp)
1494{
1495 struct _Py_async_gen_state *state = &interp->async_gen;
1496
1497 while (state->value_numfree) {
1498 _PyAsyncGenWrappedValue *o;
1499 o = state->value_freelist[--state->value_numfree];
1500 assert(_PyAsyncGenWrappedValue_CheckExact(o));
1501 PyObject_GC_Del(o);
1502 }
1503
1504 while (state->asend_numfree) {
1505 PyAsyncGenASend *o;
1506 o = state->asend_freelist[--state->asend_numfree];
1507 assert(Py_IS_TYPE(o, &_PyAsyncGenASend_Type));
1508 PyObject_GC_Del(o);
1509 }
1510}
1511
1512void
1513_PyAsyncGen_Fini(PyInterpreterState *interp)
1514{
1515 _PyAsyncGen_ClearFreeLists(interp);
1516#ifdef Py_DEBUG
1517 struct _Py_async_gen_state *state = &interp->async_gen;
1518 state->value_numfree = -1;
1519 state->asend_numfree = -1;
1520#endif
1521}
1522
1523
1524static PyObject *
1525async_gen_unwrap_value(PyAsyncGenObject *gen, PyObject *result)
1526{
1527 if (result == NULL) {
1528 if (!PyErr_Occurred()) {
1529 PyErr_SetNone(PyExc_StopAsyncIteration);
1530 }
1531
1532 if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration)
1533 || PyErr_ExceptionMatches(PyExc_GeneratorExit)
1534 ) {
1535 gen->ag_closed = 1;
1536 }
1537
1538 gen->ag_running_async = 0;
1539 return NULL;
1540 }
1541
1542 if (_PyAsyncGenWrappedValue_CheckExact(result)) {
1543 /* async yield */
1544 _PyGen_SetStopIterationValue(((_PyAsyncGenWrappedValue*)result)->agw_val);
1545 Py_DECREF(result);
1546 gen->ag_running_async = 0;
1547 return NULL;
1548 }
1549
1550 return result;
1551}
1552
1553
1554/* ---------- Async Generator ASend Awaitable ------------ */
1555
1556
1557static void
1558async_gen_asend_dealloc(PyAsyncGenASend *o)
1559{
1560 _PyObject_GC_UNTRACK((PyObject *)o);
1561 Py_CLEAR(o->ags_gen);
1562 Py_CLEAR(o->ags_sendval);
1563 struct _Py_async_gen_state *state = get_async_gen_state();
1564#ifdef Py_DEBUG
1565 // async_gen_asend_dealloc() must not be called after _PyAsyncGen_Fini()
1566 assert(state->asend_numfree != -1);
1567#endif
1568 if (state->asend_numfree < _PyAsyncGen_MAXFREELIST) {
1569 assert(PyAsyncGenASend_CheckExact(o));
1570 state->asend_freelist[state->asend_numfree++] = o;
1571 }
1572 else {
1573 PyObject_GC_Del(o);
1574 }
1575}
1576
1577static int
1578async_gen_asend_traverse(PyAsyncGenASend *o, visitproc visit, void *arg)
1579{
1580 Py_VISIT(o->ags_gen);
1581 Py_VISIT(o->ags_sendval);
1582 return 0;
1583}
1584
1585
1586static PyObject *
1587async_gen_asend_send(PyAsyncGenASend *o, PyObject *arg)
1588{
1589 PyObject *result;
1590
1591 if (o->ags_state == AWAITABLE_STATE_CLOSED) {
1592 PyErr_SetString(
1593 PyExc_RuntimeError,
1594 "cannot reuse already awaited __anext__()/asend()");
1595 return NULL;
1596 }
1597
1598 if (o->ags_state == AWAITABLE_STATE_INIT) {
1599 if (o->ags_gen->ag_running_async) {
1600 PyErr_SetString(
1601 PyExc_RuntimeError,
1602 "anext(): asynchronous generator is already running");
1603 return NULL;
1604 }
1605
1606 if (arg == NULL || arg == Py_None) {
1607 arg = o->ags_sendval;
1608 }
1609 o->ags_state = AWAITABLE_STATE_ITER;
1610 }
1611
1612 o->ags_gen->ag_running_async = 1;
1613 result = gen_send((PyGenObject*)o->ags_gen, arg);
1614 result = async_gen_unwrap_value(o->ags_gen, result);
1615
1616 if (result == NULL) {
1617 o->ags_state = AWAITABLE_STATE_CLOSED;
1618 }
1619
1620 return result;
1621}
1622
1623
1624static PyObject *
1625async_gen_asend_iternext(PyAsyncGenASend *o)
1626{
1627 return async_gen_asend_send(o, NULL);
1628}
1629
1630
1631static PyObject *
1632async_gen_asend_throw(PyAsyncGenASend *o, PyObject *args)
1633{
1634 PyObject *result;
1635
1636 if (o->ags_state == AWAITABLE_STATE_CLOSED) {
1637 PyErr_SetString(
1638 PyExc_RuntimeError,
1639 "cannot reuse already awaited __anext__()/asend()");
1640 return NULL;
1641 }
1642
1643 result = gen_throw((PyGenObject*)o->ags_gen, args);
1644 result = async_gen_unwrap_value(o->ags_gen, result);
1645
1646 if (result == NULL) {
1647 o->ags_state = AWAITABLE_STATE_CLOSED;
1648 }
1649
1650 return result;
1651}
1652
1653
1654static PyObject *
1655async_gen_asend_close(PyAsyncGenASend *o, PyObject *args)
1656{
1657 o->ags_state = AWAITABLE_STATE_CLOSED;
1658 Py_RETURN_NONE;
1659}
1660
1661
1662static PyMethodDef async_gen_asend_methods[] = {
1663 {"send", (PyCFunction)async_gen_asend_send, METH_O, send_doc},
1664 {"throw", (PyCFunction)async_gen_asend_throw, METH_VARARGS, throw_doc},
1665 {"close", (PyCFunction)async_gen_asend_close, METH_NOARGS, close_doc},
1666 {NULL, NULL} /* Sentinel */
1667};
1668
1669
1670static PyAsyncMethods async_gen_asend_as_async = {
1671 PyObject_SelfIter, /* am_await */
1672 0, /* am_aiter */
1673 0, /* am_anext */
1674 0, /* am_send */
1675};
1676
1677
1678PyTypeObject _PyAsyncGenASend_Type = {
1679 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1680 "async_generator_asend", /* tp_name */
1681 sizeof(PyAsyncGenASend), /* tp_basicsize */
1682 0, /* tp_itemsize */
1683 /* methods */
1684 (destructor)async_gen_asend_dealloc, /* tp_dealloc */
1685 0, /* tp_vectorcall_offset */
1686 0, /* tp_getattr */
1687 0, /* tp_setattr */
1688 &async_gen_asend_as_async, /* tp_as_async */
1689 0, /* tp_repr */
1690 0, /* tp_as_number */
1691 0, /* tp_as_sequence */
1692 0, /* tp_as_mapping */
1693 0, /* tp_hash */
1694 0, /* tp_call */
1695 0, /* tp_str */
1696 PyObject_GenericGetAttr, /* tp_getattro */
1697 0, /* tp_setattro */
1698 0, /* tp_as_buffer */
1699 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1700 0, /* tp_doc */
1701 (traverseproc)async_gen_asend_traverse, /* tp_traverse */
1702 0, /* tp_clear */
1703 0, /* tp_richcompare */
1704 0, /* tp_weaklistoffset */
1705 PyObject_SelfIter, /* tp_iter */
1706 (iternextfunc)async_gen_asend_iternext, /* tp_iternext */
1707 async_gen_asend_methods, /* tp_methods */
1708 0, /* tp_members */
1709 0, /* tp_getset */
1710 0, /* tp_base */
1711 0, /* tp_dict */
1712 0, /* tp_descr_get */
1713 0, /* tp_descr_set */
1714 0, /* tp_dictoffset */
1715 0, /* tp_init */
1716 0, /* tp_alloc */
1717 0, /* tp_new */
1718};
1719
1720
1721static PyObject *
1722async_gen_asend_new(PyAsyncGenObject *gen, PyObject *sendval)
1723{
1724 PyAsyncGenASend *o;
1725 struct _Py_async_gen_state *state = get_async_gen_state();
1726#ifdef Py_DEBUG
1727 // async_gen_asend_new() must not be called after _PyAsyncGen_Fini()
1728 assert(state->asend_numfree != -1);
1729#endif
1730 if (state->asend_numfree) {
1731 state->asend_numfree--;
1732 o = state->asend_freelist[state->asend_numfree];
1733 _Py_NewReference((PyObject *)o);
1734 }
1735 else {
1736 o = PyObject_GC_New(PyAsyncGenASend, &_PyAsyncGenASend_Type);
1737 if (o == NULL) {
1738 return NULL;
1739 }
1740 }
1741
1742 Py_INCREF(gen);
1743 o->ags_gen = gen;
1744
1745 Py_XINCREF(sendval);
1746 o->ags_sendval = sendval;
1747
1748 o->ags_state = AWAITABLE_STATE_INIT;
1749
1750 _PyObject_GC_TRACK((PyObject*)o);
1751 return (PyObject*)o;
1752}
1753
1754
1755/* ---------- Async Generator Value Wrapper ------------ */
1756
1757
1758static void
1759async_gen_wrapped_val_dealloc(_PyAsyncGenWrappedValue *o)
1760{
1761 _PyObject_GC_UNTRACK((PyObject *)o);
1762 Py_CLEAR(o->agw_val);
1763 struct _Py_async_gen_state *state = get_async_gen_state();
1764#ifdef Py_DEBUG
1765 // async_gen_wrapped_val_dealloc() must not be called after _PyAsyncGen_Fini()
1766 assert(state->value_numfree != -1);
1767#endif
1768 if (state->value_numfree < _PyAsyncGen_MAXFREELIST) {
1769 assert(_PyAsyncGenWrappedValue_CheckExact(o));
1770 state->value_freelist[state->value_numfree++] = o;
1771 }
1772 else {
1773 PyObject_GC_Del(o);
1774 }
1775}
1776
1777
1778static int
1779async_gen_wrapped_val_traverse(_PyAsyncGenWrappedValue *o,
1780 visitproc visit, void *arg)
1781{
1782 Py_VISIT(o->agw_val);
1783 return 0;
1784}
1785
1786
1787PyTypeObject _PyAsyncGenWrappedValue_Type = {
1788 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1789 "async_generator_wrapped_value", /* tp_name */
1790 sizeof(_PyAsyncGenWrappedValue), /* tp_basicsize */
1791 0, /* tp_itemsize */
1792 /* methods */
1793 (destructor)async_gen_wrapped_val_dealloc, /* tp_dealloc */
1794 0, /* tp_vectorcall_offset */
1795 0, /* tp_getattr */
1796 0, /* tp_setattr */
1797 0, /* tp_as_async */
1798 0, /* tp_repr */
1799 0, /* tp_as_number */
1800 0, /* tp_as_sequence */
1801 0, /* tp_as_mapping */
1802 0, /* tp_hash */
1803 0, /* tp_call */
1804 0, /* tp_str */
1805 PyObject_GenericGetAttr, /* tp_getattro */
1806 0, /* tp_setattro */
1807 0, /* tp_as_buffer */
1808 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1809 0, /* tp_doc */
1810 (traverseproc)async_gen_wrapped_val_traverse, /* tp_traverse */
1811 0, /* tp_clear */
1812 0, /* tp_richcompare */
1813 0, /* tp_weaklistoffset */
1814 0, /* tp_iter */
1815 0, /* tp_iternext */
1816 0, /* tp_methods */
1817 0, /* tp_members */
1818 0, /* tp_getset */
1819 0, /* tp_base */
1820 0, /* tp_dict */
1821 0, /* tp_descr_get */
1822 0, /* tp_descr_set */
1823 0, /* tp_dictoffset */
1824 0, /* tp_init */
1825 0, /* tp_alloc */
1826 0, /* tp_new */
1827};
1828
1829
1830PyObject *
1831_PyAsyncGenValueWrapperNew(PyObject *val)
1832{
1833 _PyAsyncGenWrappedValue *o;
1834 assert(val);
1835
1836 struct _Py_async_gen_state *state = get_async_gen_state();
1837#ifdef Py_DEBUG
1838 // _PyAsyncGenValueWrapperNew() must not be called after _PyAsyncGen_Fini()
1839 assert(state->value_numfree != -1);
1840#endif
1841 if (state->value_numfree) {
1842 state->value_numfree--;
1843 o = state->value_freelist[state->value_numfree];
1844 assert(_PyAsyncGenWrappedValue_CheckExact(o));
1845 _Py_NewReference((PyObject*)o);
1846 }
1847 else {
1848 o = PyObject_GC_New(_PyAsyncGenWrappedValue,
1849 &_PyAsyncGenWrappedValue_Type);
1850 if (o == NULL) {
1851 return NULL;
1852 }
1853 }
1854 o->agw_val = val;
1855 Py_INCREF(val);
1856 _PyObject_GC_TRACK((PyObject*)o);
1857 return (PyObject*)o;
1858}
1859
1860
1861/* ---------- Async Generator AThrow awaitable ------------ */
1862
1863
1864static void
1865async_gen_athrow_dealloc(PyAsyncGenAThrow *o)
1866{
1867 _PyObject_GC_UNTRACK((PyObject *)o);
1868 Py_CLEAR(o->agt_gen);
1869 Py_CLEAR(o->agt_args);
1870 PyObject_GC_Del(o);
1871}
1872
1873
1874static int
1875async_gen_athrow_traverse(PyAsyncGenAThrow *o, visitproc visit, void *arg)
1876{
1877 Py_VISIT(o->agt_gen);
1878 Py_VISIT(o->agt_args);
1879 return 0;
1880}
1881
1882
1883static PyObject *
1884async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg)
1885{
1886 PyGenObject *gen = (PyGenObject*)o->agt_gen;
1887 PyFrameObject *f = gen->gi_frame;
1888 PyObject *retval;
1889
1890 if (o->agt_state == AWAITABLE_STATE_CLOSED) {
1891 PyErr_SetString(
1892 PyExc_RuntimeError,
1893 "cannot reuse already awaited aclose()/athrow()");
1894 return NULL;
1895 }
1896
1897 if (f == NULL || _PyFrameHasCompleted(f)) {
1898 o->agt_state = AWAITABLE_STATE_CLOSED;
1899 PyErr_SetNone(PyExc_StopIteration);
1900 return NULL;
1901 }
1902
1903 if (o->agt_state == AWAITABLE_STATE_INIT) {
1904 if (o->agt_gen->ag_running_async) {
1905 o->agt_state = AWAITABLE_STATE_CLOSED;
1906 if (o->agt_args == NULL) {
1907 PyErr_SetString(
1908 PyExc_RuntimeError,
1909 "aclose(): asynchronous generator is already running");
1910 }
1911 else {
1912 PyErr_SetString(
1913 PyExc_RuntimeError,
1914 "athrow(): asynchronous generator is already running");
1915 }
1916 return NULL;
1917 }
1918
1919 if (o->agt_gen->ag_closed) {
1920 o->agt_state = AWAITABLE_STATE_CLOSED;
1921 PyErr_SetNone(PyExc_StopAsyncIteration);
1922 return NULL;
1923 }
1924
1925 if (arg != Py_None) {
1926 PyErr_SetString(PyExc_RuntimeError, NON_INIT_CORO_MSG);
1927 return NULL;
1928 }
1929
1930 o->agt_state = AWAITABLE_STATE_ITER;
1931 o->agt_gen->ag_running_async = 1;
1932
1933 if (o->agt_args == NULL) {
1934 /* aclose() mode */
1935 o->agt_gen->ag_closed = 1;
1936
1937 retval = _gen_throw((PyGenObject *)gen,
1938 0, /* Do not close generator when
1939 PyExc_GeneratorExit is passed */
1940 PyExc_GeneratorExit, NULL, NULL);
1941
1942 if (retval && _PyAsyncGenWrappedValue_CheckExact(retval)) {
1943 Py_DECREF(retval);
1944 goto yield_close;
1945 }
1946 } else {
1947 PyObject *typ;
1948 PyObject *tb = NULL;
1949 PyObject *val = NULL;
1950
1951 if (!PyArg_UnpackTuple(o->agt_args, "athrow", 1, 3,
1952 &typ, &val, &tb)) {
1953 return NULL;
1954 }
1955
1956 retval = _gen_throw((PyGenObject *)gen,
1957 0, /* Do not close generator when
1958 PyExc_GeneratorExit is passed */
1959 typ, val, tb);
1960 retval = async_gen_unwrap_value(o->agt_gen, retval);
1961 }
1962 if (retval == NULL) {
1963 goto check_error;
1964 }
1965 return retval;
1966 }
1967
1968 assert(o->agt_state == AWAITABLE_STATE_ITER);
1969
1970 retval = gen_send((PyGenObject *)gen, arg);
1971 if (o->agt_args) {
1972 return async_gen_unwrap_value(o->agt_gen, retval);
1973 } else {
1974 /* aclose() mode */
1975 if (retval) {
1976 if (_PyAsyncGenWrappedValue_CheckExact(retval)) {
1977 Py_DECREF(retval);
1978 goto yield_close;
1979 }
1980 else {
1981 return retval;
1982 }
1983 }
1984 else {
1985 goto check_error;
1986 }
1987 }
1988
1989yield_close:
1990 o->agt_gen->ag_running_async = 0;
1991 o->agt_state = AWAITABLE_STATE_CLOSED;
1992 PyErr_SetString(
1993 PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG);
1994 return NULL;
1995
1996check_error:
1997 o->agt_gen->ag_running_async = 0;
1998 o->agt_state = AWAITABLE_STATE_CLOSED;
1999 if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration) ||
2000 PyErr_ExceptionMatches(PyExc_GeneratorExit))
2001 {
2002 if (o->agt_args == NULL) {
2003 /* when aclose() is called we don't want to propagate
2004 StopAsyncIteration or GeneratorExit; just raise
2005 StopIteration, signalling that this 'aclose()' await
2006 is done.
2007 */
2008 PyErr_Clear();
2009 PyErr_SetNone(PyExc_StopIteration);
2010 }
2011 }
2012 return NULL;
2013}
2014
2015
2016static PyObject *
2017async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *args)
2018{
2019 PyObject *retval;
2020
2021 if (o->agt_state == AWAITABLE_STATE_CLOSED) {
2022 PyErr_SetString(
2023 PyExc_RuntimeError,
2024 "cannot reuse already awaited aclose()/athrow()");
2025 return NULL;
2026 }
2027
2028 retval = gen_throw((PyGenObject*)o->agt_gen, args);
2029 if (o->agt_args) {
2030 return async_gen_unwrap_value(o->agt_gen, retval);
2031 } else {
2032 /* aclose() mode */
2033 if (retval && _PyAsyncGenWrappedValue_CheckExact(retval)) {
2034 o->agt_gen->ag_running_async = 0;
2035 o->agt_state = AWAITABLE_STATE_CLOSED;
2036 Py_DECREF(retval);
2037 PyErr_SetString(PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG);
2038 return NULL;
2039 }
2040 if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration) ||
2041 PyErr_ExceptionMatches(PyExc_GeneratorExit))
2042 {
2043 /* when aclose() is called we don't want to propagate
2044 StopAsyncIteration or GeneratorExit; just raise
2045 StopIteration, signalling that this 'aclose()' await
2046 is done.
2047 */
2048 PyErr_Clear();
2049 PyErr_SetNone(PyExc_StopIteration);
2050 }
2051 return retval;
2052 }
2053}
2054
2055
2056static PyObject *
2057async_gen_athrow_iternext(PyAsyncGenAThrow *o)
2058{
2059 return async_gen_athrow_send(o, Py_None);
2060}
2061
2062
2063static PyObject *
2064async_gen_athrow_close(PyAsyncGenAThrow *o, PyObject *args)
2065{
2066 o->agt_state = AWAITABLE_STATE_CLOSED;
2067 Py_RETURN_NONE;
2068}
2069
2070
2071static PyMethodDef async_gen_athrow_methods[] = {
2072 {"send", (PyCFunction)async_gen_athrow_send, METH_O, send_doc},
2073 {"throw", (PyCFunction)async_gen_athrow_throw, METH_VARARGS, throw_doc},
2074 {"close", (PyCFunction)async_gen_athrow_close, METH_NOARGS, close_doc},
2075 {NULL, NULL} /* Sentinel */
2076};
2077
2078
2079static PyAsyncMethods async_gen_athrow_as_async = {
2080 PyObject_SelfIter, /* am_await */
2081 0, /* am_aiter */
2082 0, /* am_anext */
2083 0, /* am_send */
2084};
2085
2086
2087PyTypeObject _PyAsyncGenAThrow_Type = {
2088 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2089 "async_generator_athrow", /* tp_name */
2090 sizeof(PyAsyncGenAThrow), /* tp_basicsize */
2091 0, /* tp_itemsize */
2092 /* methods */
2093 (destructor)async_gen_athrow_dealloc, /* tp_dealloc */
2094 0, /* tp_vectorcall_offset */
2095 0, /* tp_getattr */
2096 0, /* tp_setattr */
2097 &async_gen_athrow_as_async, /* tp_as_async */
2098 0, /* tp_repr */
2099 0, /* tp_as_number */
2100 0, /* tp_as_sequence */
2101 0, /* tp_as_mapping */
2102 0, /* tp_hash */
2103 0, /* tp_call */
2104 0, /* tp_str */
2105 PyObject_GenericGetAttr, /* tp_getattro */
2106 0, /* tp_setattro */
2107 0, /* tp_as_buffer */
2108 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2109 0, /* tp_doc */
2110 (traverseproc)async_gen_athrow_traverse, /* tp_traverse */
2111 0, /* tp_clear */
2112 0, /* tp_richcompare */
2113 0, /* tp_weaklistoffset */
2114 PyObject_SelfIter, /* tp_iter */
2115 (iternextfunc)async_gen_athrow_iternext, /* tp_iternext */
2116 async_gen_athrow_methods, /* tp_methods */
2117 0, /* tp_members */
2118 0, /* tp_getset */
2119 0, /* tp_base */
2120 0, /* tp_dict */
2121 0, /* tp_descr_get */
2122 0, /* tp_descr_set */
2123 0, /* tp_dictoffset */
2124 0, /* tp_init */
2125 0, /* tp_alloc */
2126 0, /* tp_new */
2127};
2128
2129
2130static PyObject *
2131async_gen_athrow_new(PyAsyncGenObject *gen, PyObject *args)
2132{
2133 PyAsyncGenAThrow *o;
2134 o = PyObject_GC_New(PyAsyncGenAThrow, &_PyAsyncGenAThrow_Type);
2135 if (o == NULL) {
2136 return NULL;
2137 }
2138 o->agt_gen = gen;
2139 o->agt_args = args;
2140 o->agt_state = AWAITABLE_STATE_INIT;
2141 Py_INCREF(gen);
2142 Py_XINCREF(args);
2143 _PyObject_GC_TRACK((PyObject*)o);
2144 return (PyObject*)o;
2145}
2146