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