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