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