@@ -1965,8 +1965,10 @@ PyAsyncGen_New(PyFrameObject *f, PyObject *name, PyObject *qualname)
19651965 return (PyObject * )ag ;
19661966}
19671967
1968- static PyObject *
1969- async_gen_unwrap_value (PyAsyncGenObject * gen , PyObject * result )
1968+ // Report an async yield as PYGEN_RETURN with the yielded value.
1969+ static PySendResult
1970+ async_gen_unwrap_send (PyAsyncGenObject * gen , PyObject * result ,
1971+ PyObject * * presult )
19701972{
19711973 if (result == NULL ) {
19721974 if (!PyErr_Occurred ()) {
@@ -1979,17 +1981,31 @@ async_gen_unwrap_value(PyAsyncGenObject *gen, PyObject *result)
19791981 FT_ATOMIC_STORE_INT8_RELAXED (gen -> ag_closed , 1 );
19801982 }
19811983
1982- return NULL ;
1984+ * presult = NULL ;
1985+ return PYGEN_ERROR ;
19831986 }
19841987
19851988 if (_PyAsyncGenWrappedValue_CheckExact (result )) {
19861989 /* async yield */
1987- _PyGen_SetStopIterationValue (((_PyAsyncGenWrappedValue * )result )-> agw_val );
1990+ * presult = Py_NewRef (((_PyAsyncGenWrappedValue * )result )-> agw_val );
19881991 Py_DECREF (result );
1989- return NULL ;
1992+ return PYGEN_RETURN ;
19901993 }
19911994
1992- return result ;
1995+ * presult = result ;
1996+ return PYGEN_NEXT ;
1997+ }
1998+
1999+ static PyObject *
2000+ async_gen_unwrap_value (PyAsyncGenObject * gen , PyObject * result )
2001+ {
2002+ PyObject * value ;
2003+ if (async_gen_unwrap_send (gen , result , & value ) == PYGEN_RETURN ) {
2004+ _PyGen_SetStopIterationValue (value );
2005+ Py_DECREF (value );
2006+ return NULL ;
2007+ }
2008+ return value ;
19932009}
19942010
19952011
@@ -2002,7 +2018,10 @@ async_gen_asend_dealloc(PyObject *self)
20022018 assert (PyAsyncGenASend_CheckExact (self ));
20032019 PyAsyncGenASend * ags = _PyAsyncGenASend_CAST (self );
20042020
2005- if (PyObject_CallFinalizerFromDealloc (self )) {
2021+ // The finalizer only warns about an asend() that was never awaited.
2022+ if (ags -> ags_state == AWAITABLE_STATE_INIT
2023+ && PyObject_CallFinalizerFromDealloc (self ))
2024+ {
20062025 return ;
20072026 }
20082027
@@ -2025,18 +2044,19 @@ async_gen_asend_traverse(PyObject *self, visitproc visit, void *arg)
20252044}
20262045
20272046
2028- static PyObject *
2029- async_gen_asend_send (PyObject * self , PyObject * arg )
2047+ PySendResult
2048+ _PyAsyncGenASend_Send (PyObject * self , PyObject * arg , PyObject * * presult )
20302049{
20312050 PyAsyncGenASend * o = _PyAsyncGenASend_CAST (self );
20322051
2052+ * presult = NULL ;
20332053 int8_t state = FT_ATOMIC_LOAD_INT8_RELAXED (o -> ags_state );
20342054 do {
20352055 if (state == AWAITABLE_STATE_CLOSED ) {
20362056 PyErr_SetString (
20372057 PyExc_RuntimeError ,
20382058 "cannot reuse already awaited __anext__()/asend()" );
2039- return NULL ;
2059+ return PYGEN_ERROR ;
20402060 }
20412061 if (state == AWAITABLE_STATE_ITER ) {
20422062 goto do_send ;
@@ -2053,37 +2073,37 @@ async_gen_asend_send(PyObject *self, PyObject *arg)
20532073 PyErr_SetString (
20542074 PyExc_RuntimeError ,
20552075 "anext(): asynchronous generator is already running" );
2056- return NULL ;
2076+ return PYGEN_ERROR ;
20572077 }
20582078
20592079 if (arg == NULL || arg == Py_None ) {
20602080 arg = o -> ags_sendval ;
20612081 }
20622082
20632083 PyObject * result ;
2084+ PySendResult res ;
20642085do_send :
20652086 result = gen_send ((PyObject * )o -> ags_gen , arg );
2066- result = async_gen_unwrap_value (o -> ags_gen , result );
2087+ res = async_gen_unwrap_send (o -> ags_gen , result , presult );
20672088
2068- if (result == NULL ) {
2089+ if (res != PYGEN_NEXT ) {
20692090 FT_ATOMIC_STORE_INT8_RELAXED (o -> ags_state , AWAITABLE_STATE_CLOSED );
20702091 FT_ATOMIC_STORE_INT8_RELEASE (o -> ags_gen -> ag_running_async , 0 );
20712092 }
20722093
2073- return result ;
2094+ return res ;
20742095}
20752096
2076- PySendResult
2077- _PyAsyncGenASend_Send (PyObject * iter , PyObject * arg , PyObject * * result )
2097+ static PyObject *
2098+ async_gen_asend_send (PyObject * self , PyObject * arg )
20782099{
2079- * result = async_gen_asend_send (iter , arg );
2080- if (* result != NULL ) {
2081- return PYGEN_NEXT ;
2082- }
2083- if (_PyGen_FetchStopIterationValue (result ) == 0 ) {
2084- return PYGEN_RETURN ;
2100+ PyObject * result ;
2101+ if (_PyAsyncGenASend_Send (self , arg , & result ) == PYGEN_RETURN ) {
2102+ _PyGen_SetStopIterationValue (result );
2103+ Py_DECREF (result );
2104+ return NULL ;
20852105 }
2086- return PYGEN_ERROR ;
2106+ return result ;
20872107}
20882108
20892109
@@ -2168,6 +2188,7 @@ static void
21682188async_gen_asend_finalize (PyObject * self )
21692189{
21702190 PyAsyncGenASend * ags = _PyAsyncGenASend_CAST (self );
2191+ // async_gen_asend_dealloc() calls this only in the INIT state.
21712192 if (ags -> ags_state == AWAITABLE_STATE_INIT ) {
21722193 _PyErr_WarnUnawaitedAgenMethod (ags -> ags_gen , & _Py_ID (asend ));
21732194 }
0 commit comments