Coverage Report

Created: 2026-01-09 06:26

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