@@ -137,7 +137,7 @@ gen_dealloc(PyGenObject *gen)
137137}
138138
139139static PyObject *
140- gen_send_ex (PyGenObject * gen , PyObject * arg , int exc , int closing )
140+ gen_send_ex (PyGenObject * gen , PyObject * arg , int exc , int closing , int * is_return_value )
141141{
142142 PyThreadState * tstate = _PyThreadState_GET ();
143143 PyFrameObject * f = gen -> gi_frame ;
@@ -170,6 +170,10 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
170170 PyErr_SetNone (PyExc_StopAsyncIteration );
171171 }
172172 else {
173+ if (is_return_value != NULL ) {
174+ * is_return_value = 1 ;
175+ Py_RETURN_NONE ;
176+ }
173177 PyErr_SetNone (PyExc_StopIteration );
174178 }
175179 }
@@ -230,18 +234,33 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
230234 /* Delay exception instantiation if we can */
231235 if (PyAsyncGen_CheckExact (gen )) {
232236 PyErr_SetNone (PyExc_StopAsyncIteration );
237+ Py_CLEAR (result );
233238 }
234239 else if (arg ) {
235- /* Set exception if not called by gen_iternext() */
236- PyErr_SetNone (PyExc_StopIteration );
240+ if (is_return_value != NULL ) {
241+ * is_return_value = 1 ;
242+ }
243+ else {
244+ /* Set exception if not called by gen_iternext() */
245+ PyErr_SetNone (PyExc_StopIteration );
246+ Py_CLEAR (result );
247+ }
248+ }
249+ else {
250+ Py_CLEAR (result );
237251 }
238252 }
239253 else {
240254 /* Async generators cannot return anything but None */
241255 assert (!PyAsyncGen_CheckExact (gen ));
242- _PyGen_SetStopIterationValue (result );
256+ if (is_return_value != NULL ) {
257+ * is_return_value = 1 ;
258+ }
259+ else {
260+ _PyGen_SetStopIterationValue (result );
261+ Py_CLEAR (result );
262+ }
243263 }
244- Py_CLEAR (result );
245264 }
246265 else if (!result && PyErr_ExceptionMatches (PyExc_StopIteration )) {
247266 const char * msg = "generator raised StopIteration" ;
@@ -264,7 +283,7 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
264283 _PyErr_FormatFromCause (PyExc_RuntimeError , "%s" , msg );
265284 }
266285
267- if (!result || _PyFrameHasCompleted (f )) {
286+ if (( is_return_value && * is_return_value ) || !result || _PyFrameHasCompleted (f )) {
268287 /* generator can't be rerun, so release the frame */
269288 /* first clean reference cycle through stored exception traceback */
270289 _PyErr_ClearExcState (& gen -> gi_exc_state );
@@ -283,7 +302,19 @@ return next yielded value or raise StopIteration.");
283302PyObject *
284303_PyGen_Send (PyGenObject * gen , PyObject * arg )
285304{
286- return gen_send_ex (gen , arg , 0 , 0 );
305+ return gen_send_ex (gen , arg , 0 , 0 , NULL );
306+ }
307+
308+ PySendResult
309+ PyGen_Send (PyGenObject * gen , PyObject * arg , PyObject * * result )
310+ {
311+ assert (result != NULL );
312+
313+ int is_return_value = 0 ;
314+ if ((* result = gen_send_ex (gen , arg , 0 , 0 , & is_return_value )) == NULL ) {
315+ return PYGEN_ERROR ;
316+ }
317+ return is_return_value ? PYGEN_RETURN : PYGEN_NEXT ;
287318}
288319
289320PyDoc_STRVAR (close_doc ,
@@ -365,7 +396,7 @@ gen_close(PyGenObject *gen, PyObject *args)
365396 }
366397 if (err == 0 )
367398 PyErr_SetNone (PyExc_GeneratorExit );
368- retval = gen_send_ex (gen , Py_None , 1 , 1 );
399+ retval = gen_send_ex (gen , Py_None , 1 , 1 , NULL );
369400 if (retval ) {
370401 const char * msg = "generator ignored GeneratorExit" ;
371402 if (PyCoro_CheckExact (gen )) {
@@ -413,7 +444,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
413444 gen -> gi_frame -> f_state = state ;
414445 Py_DECREF (yf );
415446 if (err < 0 )
416- return gen_send_ex (gen , Py_None , 1 , 0 );
447+ return gen_send_ex (gen , Py_None , 1 , 0 , NULL );
417448 goto throw_here ;
418449 }
419450 if (PyGen_CheckExact (yf ) || PyCoro_CheckExact (yf )) {
@@ -465,10 +496,10 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
465496 assert (gen -> gi_frame -> f_lasti >= 0 );
466497 gen -> gi_frame -> f_lasti += sizeof (_Py_CODEUNIT );
467498 if (_PyGen_FetchStopIterationValue (& val ) == 0 ) {
468- ret = gen_send_ex (gen , val , 0 , 0 );
499+ ret = gen_send_ex (gen , val , 0 , 0 , NULL );
469500 Py_DECREF (val );
470501 } else {
471- ret = gen_send_ex (gen , Py_None , 1 , 0 );
502+ ret = gen_send_ex (gen , Py_None , 1 , 0 , NULL );
472503 }
473504 }
474505 return ret ;
@@ -522,7 +553,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
522553 }
523554
524555 PyErr_Restore (typ , val , tb );
525- return gen_send_ex (gen , Py_None , 1 , 0 );
556+ return gen_send_ex (gen , Py_None , 1 , 0 , NULL );
526557
527558failed_throw :
528559 /* Didn't use our arguments, so restore their original refcounts */
@@ -551,7 +582,7 @@ gen_throw(PyGenObject *gen, PyObject *args)
551582static PyObject *
552583gen_iternext (PyGenObject * gen )
553584{
554- return gen_send_ex (gen , NULL , 0 , 0 );
585+ return gen_send_ex (gen , NULL , 0 , 0 , NULL );
555586}
556587
557588/*
@@ -1051,13 +1082,13 @@ coro_wrapper_dealloc(PyCoroWrapper *cw)
10511082static PyObject *
10521083coro_wrapper_iternext (PyCoroWrapper * cw )
10531084{
1054- return gen_send_ex ((PyGenObject * )cw -> cw_coroutine , NULL , 0 , 0 );
1085+ return gen_send_ex ((PyGenObject * )cw -> cw_coroutine , NULL , 0 , 0 , NULL );
10551086}
10561087
10571088static PyObject *
10581089coro_wrapper_send (PyCoroWrapper * cw , PyObject * arg )
10591090{
1060- return gen_send_ex ((PyGenObject * )cw -> cw_coroutine , arg , 0 , 0 );
1091+ return gen_send_ex ((PyGenObject * )cw -> cw_coroutine , arg , 0 , 0 , NULL );
10611092}
10621093
10631094static PyObject *
@@ -1570,7 +1601,7 @@ async_gen_asend_send(PyAsyncGenASend *o, PyObject *arg)
15701601 }
15711602
15721603 o -> ags_gen -> ag_running_async = 1 ;
1573- result = gen_send_ex ((PyGenObject * )o -> ags_gen , arg , 0 , 0 );
1604+ result = gen_send_ex ((PyGenObject * )o -> ags_gen , arg , 0 , 0 , NULL );
15741605 result = async_gen_unwrap_value (o -> ags_gen , result );
15751606
15761607 if (result == NULL ) {
@@ -1926,7 +1957,7 @@ async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg)
19261957
19271958 assert (o -> agt_state == AWAITABLE_STATE_ITER );
19281959
1929- retval = gen_send_ex ((PyGenObject * )gen , arg , 0 , 0 );
1960+ retval = gen_send_ex ((PyGenObject * )gen , arg , 0 , 0 , NULL );
19301961 if (o -> agt_args ) {
19311962 return async_gen_unwrap_value (o -> agt_gen , retval );
19321963 } else {
0 commit comments