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