Coverage Report

Created: 2025-07-11 06:59

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