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