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