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