bpo-42085: Introduce dedicated entry in PyAsyncMethods for sending values (#22780)
This commit is contained in:
parent
e59b2deffd
commit
1e996c3a3b
|
@ -199,6 +199,8 @@ sub-slots
|
||||||
+---------------------------------------------------------+-----------------------------------+--------------+
|
+---------------------------------------------------------+-----------------------------------+--------------+
|
||||||
| :c:member:`~PyAsyncMethods.am_anext` | :c:type:`unaryfunc` | __anext__ |
|
| :c:member:`~PyAsyncMethods.am_anext` | :c:type:`unaryfunc` | __anext__ |
|
||||||
+---------------------------------------------------------+-----------------------------------+--------------+
|
+---------------------------------------------------------+-----------------------------------+--------------+
|
||||||
|
| :c:member:`~PyAsyncMethods.am_send` | :c:type:`sendfunc` | |
|
||||||
|
+---------------------------------------------------------+-----------------------------------+--------------+
|
||||||
| |
|
| |
|
||||||
+---------------------------------------------------------+-----------------------------------+--------------+
|
+---------------------------------------------------------+-----------------------------------+--------------+
|
||||||
| :c:member:`~PyNumberMethods.nb_add` | :c:type:`binaryfunc` | __add__ |
|
| :c:member:`~PyNumberMethods.nb_add` | :c:type:`binaryfunc` | __add__ |
|
||||||
|
@ -2304,6 +2306,7 @@ Async Object Structures
|
||||||
unaryfunc am_await;
|
unaryfunc am_await;
|
||||||
unaryfunc am_aiter;
|
unaryfunc am_aiter;
|
||||||
unaryfunc am_anext;
|
unaryfunc am_anext;
|
||||||
|
sendfunc am_send;
|
||||||
} PyAsyncMethods;
|
} PyAsyncMethods;
|
||||||
|
|
||||||
.. c:member:: unaryfunc PyAsyncMethods.am_await
|
.. c:member:: unaryfunc PyAsyncMethods.am_await
|
||||||
|
@ -2337,6 +2340,15 @@ Async Object Structures
|
||||||
Must return an :term:`awaitable` object. See :meth:`__anext__` for details.
|
Must return an :term:`awaitable` object. See :meth:`__anext__` for details.
|
||||||
This slot may be set to ``NULL``.
|
This slot may be set to ``NULL``.
|
||||||
|
|
||||||
|
.. c:member:: sendfunc PyAsyncMethods.am_send
|
||||||
|
|
||||||
|
The signature of this function is::
|
||||||
|
|
||||||
|
PySendResult am_send(PyObject *self, PyObject *arg, PyObject **result);
|
||||||
|
|
||||||
|
See :c:func:`PyIter_Send` for details.
|
||||||
|
This slot may be set to ``NULL``.
|
||||||
|
|
||||||
|
|
||||||
.. _slot-typedefs:
|
.. _slot-typedefs:
|
||||||
|
|
||||||
|
@ -2432,6 +2444,10 @@ Slot Type typedefs
|
||||||
|
|
||||||
.. c:type:: PyObject *(*binaryfunc)(PyObject *, PyObject *)
|
.. c:type:: PyObject *(*binaryfunc)(PyObject *, PyObject *)
|
||||||
|
|
||||||
|
.. c:type:: PySendResult (*sendfunc)(PyObject *, PyObject *, PyObject **)
|
||||||
|
|
||||||
|
See :c:member:`~PyAsyncMethods.am_send`.
|
||||||
|
|
||||||
.. c:type:: PyObject *(*ternaryfunc)(PyObject *, PyObject *, PyObject *)
|
.. c:type:: PyObject *(*ternaryfunc)(PyObject *, PyObject *, PyObject *)
|
||||||
|
|
||||||
.. c:type:: PyObject *(*ssizeargfunc)(PyObject *, Py_ssize_t)
|
.. c:type:: PyObject *(*ssizeargfunc)(PyObject *, Py_ssize_t)
|
||||||
|
|
|
@ -339,11 +339,6 @@ PyAPI_FUNC(int) PyIter_Check(PyObject *);
|
||||||
PyAPI_FUNC(PyObject *) PyIter_Next(PyObject *);
|
PyAPI_FUNC(PyObject *) PyIter_Next(PyObject *);
|
||||||
|
|
||||||
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000
|
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000
|
||||||
typedef enum {
|
|
||||||
PYGEN_RETURN = 0,
|
|
||||||
PYGEN_ERROR = -1,
|
|
||||||
PYGEN_NEXT = 1,
|
|
||||||
} PySendResult;
|
|
||||||
|
|
||||||
/* Takes generator, coroutine or iterator object and sends the value into it.
|
/* Takes generator, coroutine or iterator object and sends the value into it.
|
||||||
Returns:
|
Returns:
|
||||||
|
|
|
@ -167,10 +167,13 @@ typedef struct {
|
||||||
objobjargproc mp_ass_subscript;
|
objobjargproc mp_ass_subscript;
|
||||||
} PyMappingMethods;
|
} PyMappingMethods;
|
||||||
|
|
||||||
|
typedef PySendResult (*sendfunc)(PyObject *iter, PyObject *value, PyObject **result);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unaryfunc am_await;
|
unaryfunc am_await;
|
||||||
unaryfunc am_aiter;
|
unaryfunc am_aiter;
|
||||||
unaryfunc am_anext;
|
unaryfunc am_anext;
|
||||||
|
sendfunc am_send;
|
||||||
} PyAsyncMethods;
|
} PyAsyncMethods;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -356,6 +356,11 @@ given type object has a specified feature.
|
||||||
/* Type is abstract and cannot be instantiated */
|
/* Type is abstract and cannot be instantiated */
|
||||||
#define Py_TPFLAGS_IS_ABSTRACT (1UL << 20)
|
#define Py_TPFLAGS_IS_ABSTRACT (1UL << 20)
|
||||||
|
|
||||||
|
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000
|
||||||
|
/* Type has am_send entry in tp_as_async slot */
|
||||||
|
#define Py_TPFLAGS_HAVE_AM_SEND (1UL << 21)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* These flags are used to determine if a type is a subclass. */
|
/* These flags are used to determine if a type is a subclass. */
|
||||||
#define Py_TPFLAGS_LONG_SUBCLASS (1UL << 24)
|
#define Py_TPFLAGS_LONG_SUBCLASS (1UL << 24)
|
||||||
#define Py_TPFLAGS_LIST_SUBCLASS (1UL << 25)
|
#define Py_TPFLAGS_LIST_SUBCLASS (1UL << 25)
|
||||||
|
@ -582,6 +587,15 @@ PyAPI_DATA(PyObject) _Py_NotImplementedStruct; /* Don't use this directly */
|
||||||
#define Py_GT 4
|
#define Py_GT 4
|
||||||
#define Py_GE 5
|
#define Py_GE 5
|
||||||
|
|
||||||
|
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000
|
||||||
|
/* Result of calling PyIter_Send */
|
||||||
|
typedef enum {
|
||||||
|
PYGEN_RETURN = 0,
|
||||||
|
PYGEN_ERROR = -1,
|
||||||
|
PYGEN_NEXT = 1,
|
||||||
|
} PySendResult;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macro for implementing rich comparisons
|
* Macro for implementing rich comparisons
|
||||||
*
|
*
|
||||||
|
|
|
@ -88,3 +88,7 @@
|
||||||
/* New in 3.5 */
|
/* New in 3.5 */
|
||||||
#define Py_tp_finalize 80
|
#define Py_tp_finalize 80
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000
|
||||||
|
/* New in 3.10 */
|
||||||
|
#define Py_am_send 81
|
||||||
|
#endif
|
||||||
|
|
|
@ -1407,7 +1407,7 @@ class SizeofTest(unittest.TestCase):
|
||||||
check(int, s)
|
check(int, s)
|
||||||
# class
|
# class
|
||||||
s = vsize(fmt + # PyTypeObject
|
s = vsize(fmt + # PyTypeObject
|
||||||
'3P' # PyAsyncMethods
|
'4P' # PyAsyncMethods
|
||||||
'36P' # PyNumberMethods
|
'36P' # PyNumberMethods
|
||||||
'3P' # PyMappingMethods
|
'3P' # PyMappingMethods
|
||||||
'10P' # PySequenceMethods
|
'10P' # PySequenceMethods
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Add dedicated entry to PyAsyncMethods for sending values
|
|
@ -1479,7 +1479,8 @@ future_cls_getitem(PyObject *cls, PyObject *type)
|
||||||
static PyAsyncMethods FutureType_as_async = {
|
static PyAsyncMethods FutureType_as_async = {
|
||||||
(unaryfunc)future_new_iter, /* am_await */
|
(unaryfunc)future_new_iter, /* am_await */
|
||||||
0, /* am_aiter */
|
0, /* am_aiter */
|
||||||
0 /* am_anext */
|
0, /* am_anext */
|
||||||
|
0, /* am_send */
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyMethodDef FutureType_methods[] = {
|
static PyMethodDef FutureType_methods[] = {
|
||||||
|
@ -1597,37 +1598,60 @@ FutureIter_dealloc(futureiterobject *it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PySendResult
|
||||||
FutureIter_iternext(futureiterobject *it)
|
FutureIter_am_send(futureiterobject *it,
|
||||||
|
PyObject *Py_UNUSED(arg),
|
||||||
|
PyObject **result)
|
||||||
{
|
{
|
||||||
|
/* arg is unused, see the comment on FutureIter_send for clarification */
|
||||||
|
|
||||||
PyObject *res;
|
PyObject *res;
|
||||||
FutureObj *fut = it->future;
|
FutureObj *fut = it->future;
|
||||||
|
|
||||||
|
*result = NULL;
|
||||||
if (fut == NULL) {
|
if (fut == NULL) {
|
||||||
return NULL;
|
return PYGEN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fut->fut_state == STATE_PENDING) {
|
if (fut->fut_state == STATE_PENDING) {
|
||||||
if (!fut->fut_blocking) {
|
if (!fut->fut_blocking) {
|
||||||
fut->fut_blocking = 1;
|
fut->fut_blocking = 1;
|
||||||
Py_INCREF(fut);
|
Py_INCREF(fut);
|
||||||
return (PyObject *)fut;
|
*result = (PyObject *)fut;
|
||||||
|
return PYGEN_NEXT;
|
||||||
}
|
}
|
||||||
PyErr_SetString(PyExc_RuntimeError,
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
"await wasn't used with future");
|
"await wasn't used with future");
|
||||||
return NULL;
|
return PYGEN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
it->future = NULL;
|
it->future = NULL;
|
||||||
res = _asyncio_Future_result_impl(fut);
|
res = _asyncio_Future_result_impl(fut);
|
||||||
if (res != NULL) {
|
if (res != NULL) {
|
||||||
/* The result of the Future is not an exception. */
|
*result = res;
|
||||||
(void)_PyGen_SetStopIterationValue(res);
|
return PYGEN_RETURN;
|
||||||
Py_DECREF(res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_DECREF(fut);
|
Py_DECREF(fut);
|
||||||
|
return PYGEN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
FutureIter_iternext(futureiterobject *it)
|
||||||
|
{
|
||||||
|
PyObject *result;
|
||||||
|
switch (FutureIter_am_send(it, Py_None, &result)) {
|
||||||
|
case PYGEN_RETURN:
|
||||||
|
(void)_PyGen_SetStopIterationValue(result);
|
||||||
|
Py_DECREF(result);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
case PYGEN_NEXT:
|
||||||
|
return result;
|
||||||
|
case PYGEN_ERROR:
|
||||||
|
return NULL;
|
||||||
|
default:
|
||||||
|
Py_UNREACHABLE();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -1716,14 +1740,24 @@ static PyMethodDef FutureIter_methods[] = {
|
||||||
{NULL, NULL} /* Sentinel */
|
{NULL, NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyAsyncMethods FutureIterType_as_async = {
|
||||||
|
0, /* am_await */
|
||||||
|
0, /* am_aiter */
|
||||||
|
0, /* am_anext */
|
||||||
|
(sendfunc)FutureIter_am_send, /* am_send */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static PyTypeObject FutureIterType = {
|
static PyTypeObject FutureIterType = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
"_asyncio.FutureIter",
|
"_asyncio.FutureIter",
|
||||||
.tp_basicsize = sizeof(futureiterobject),
|
.tp_basicsize = sizeof(futureiterobject),
|
||||||
.tp_itemsize = 0,
|
.tp_itemsize = 0,
|
||||||
.tp_dealloc = (destructor)FutureIter_dealloc,
|
.tp_dealloc = (destructor)FutureIter_dealloc,
|
||||||
|
.tp_as_async = &FutureIterType_as_async,
|
||||||
.tp_getattro = PyObject_GenericGetAttr,
|
.tp_getattro = PyObject_GenericGetAttr,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
|
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||||
|
Py_TPFLAGS_HAVE_AM_SEND,
|
||||||
.tp_traverse = (traverseproc)FutureIter_traverse,
|
.tp_traverse = (traverseproc)FutureIter_traverse,
|
||||||
.tp_iter = PyObject_SelfIter,
|
.tp_iter = PyObject_SelfIter,
|
||||||
.tp_iternext = (iternextfunc)FutureIter_iternext,
|
.tp_iternext = (iternextfunc)FutureIter_iternext,
|
||||||
|
|
|
@ -6142,7 +6142,8 @@ awaitObject_await(awaitObject *ao)
|
||||||
static PyAsyncMethods awaitType_as_async = {
|
static PyAsyncMethods awaitType_as_async = {
|
||||||
(unaryfunc)awaitObject_await, /* am_await */
|
(unaryfunc)awaitObject_await, /* am_await */
|
||||||
0, /* am_aiter */
|
0, /* am_aiter */
|
||||||
0 /* am_anext */
|
0, /* am_anext */
|
||||||
|
0, /* am_send */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2669,6 +2669,32 @@ PyIter_Next(PyObject *iter)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PySendResult
|
||||||
|
PyIter_Send(PyObject *iter, PyObject *arg, PyObject **result)
|
||||||
|
{
|
||||||
|
_Py_IDENTIFIER(send);
|
||||||
|
assert(arg != NULL);
|
||||||
|
assert(result != NULL);
|
||||||
|
if (PyType_HasFeature(Py_TYPE(iter), Py_TPFLAGS_HAVE_AM_SEND)) {
|
||||||
|
assert (Py_TYPE(iter)->tp_as_async != NULL);
|
||||||
|
assert (Py_TYPE(iter)->tp_as_async->am_send != NULL);
|
||||||
|
return Py_TYPE(iter)->tp_as_async->am_send(iter, arg, result);
|
||||||
|
}
|
||||||
|
if (arg == Py_None && PyIter_Check(iter)) {
|
||||||
|
*result = Py_TYPE(iter)->tp_iternext(iter);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*result = _PyObject_CallMethodIdOneArg(iter, &PyId_send, arg);
|
||||||
|
}
|
||||||
|
if (*result != NULL) {
|
||||||
|
return PYGEN_NEXT;
|
||||||
|
}
|
||||||
|
if (_PyGen_FetchStopIterationValue(result) == 0) {
|
||||||
|
return PYGEN_RETURN;
|
||||||
|
}
|
||||||
|
return PYGEN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flatten a sequence of bytes() objects into a C array of
|
* Flatten a sequence of bytes() objects into a C array of
|
||||||
* NULL terminated string pointers with a NULL char* terminating the array.
|
* NULL terminated string pointers with a NULL char* terminating the array.
|
||||||
|
|
|
@ -268,30 +268,10 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
|
||||||
return result ? PYGEN_RETURN : PYGEN_ERROR;
|
return result ? PYGEN_RETURN : PYGEN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
PySendResult
|
static PySendResult
|
||||||
PyIter_Send(PyObject *iter, PyObject *arg, PyObject **result)
|
PyGen_am_send(PyGenObject *gen, PyObject *arg, PyObject **result)
|
||||||
{
|
{
|
||||||
_Py_IDENTIFIER(send);
|
return gen_send_ex2(gen, arg, result, 0, 0);
|
||||||
assert(arg != NULL);
|
|
||||||
assert(result != NULL);
|
|
||||||
|
|
||||||
if (PyGen_CheckExact(iter) || PyCoro_CheckExact(iter)) {
|
|
||||||
return gen_send_ex2((PyGenObject *)iter, arg, result, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg == Py_None && PyIter_Check(iter)) {
|
|
||||||
*result = Py_TYPE(iter)->tp_iternext(iter);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*result = _PyObject_CallMethodIdOneArg(iter, &PyId_send, arg);
|
|
||||||
}
|
|
||||||
if (*result != NULL) {
|
|
||||||
return PYGEN_NEXT;
|
|
||||||
}
|
|
||||||
if (_PyGen_FetchStopIterationValue(result) == 0) {
|
|
||||||
return PYGEN_RETURN;
|
|
||||||
}
|
|
||||||
return PYGEN_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -788,6 +768,14 @@ static PyMethodDef gen_methods[] = {
|
||||||
{NULL, NULL} /* Sentinel */
|
{NULL, NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyAsyncMethods gen_as_async = {
|
||||||
|
0, /* am_await */
|
||||||
|
0, /* am_aiter */
|
||||||
|
0, /* am_anext */
|
||||||
|
(sendfunc)PyGen_am_send, /* am_send */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
PyTypeObject PyGen_Type = {
|
PyTypeObject PyGen_Type = {
|
||||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||||
"generator", /* tp_name */
|
"generator", /* tp_name */
|
||||||
|
@ -798,7 +786,7 @@ PyTypeObject PyGen_Type = {
|
||||||
0, /* tp_vectorcall_offset */
|
0, /* tp_vectorcall_offset */
|
||||||
0, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
0, /* tp_setattr */
|
0, /* tp_setattr */
|
||||||
0, /* tp_as_async */
|
&gen_as_async, /* tp_as_async */
|
||||||
(reprfunc)gen_repr, /* tp_repr */
|
(reprfunc)gen_repr, /* tp_repr */
|
||||||
0, /* tp_as_number */
|
0, /* tp_as_number */
|
||||||
0, /* tp_as_sequence */
|
0, /* tp_as_sequence */
|
||||||
|
@ -809,7 +797,8 @@ PyTypeObject PyGen_Type = {
|
||||||
PyObject_GenericGetAttr, /* tp_getattro */
|
PyObject_GenericGetAttr, /* tp_getattro */
|
||||||
0, /* tp_setattro */
|
0, /* tp_setattro */
|
||||||
0, /* tp_as_buffer */
|
0, /* tp_as_buffer */
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||||
|
Py_TPFLAGS_HAVE_AM_SEND, /* tp_flags */
|
||||||
0, /* tp_doc */
|
0, /* tp_doc */
|
||||||
(traverseproc)gen_traverse, /* tp_traverse */
|
(traverseproc)gen_traverse, /* tp_traverse */
|
||||||
0, /* tp_clear */
|
0, /* tp_clear */
|
||||||
|
@ -1031,7 +1020,8 @@ static PyMethodDef coro_methods[] = {
|
||||||
static PyAsyncMethods coro_as_async = {
|
static PyAsyncMethods coro_as_async = {
|
||||||
(unaryfunc)coro_await, /* am_await */
|
(unaryfunc)coro_await, /* am_await */
|
||||||
0, /* am_aiter */
|
0, /* am_aiter */
|
||||||
0 /* am_anext */
|
0, /* am_anext */
|
||||||
|
(sendfunc)PyGen_am_send, /* am_send */
|
||||||
};
|
};
|
||||||
|
|
||||||
PyTypeObject PyCoro_Type = {
|
PyTypeObject PyCoro_Type = {
|
||||||
|
@ -1055,7 +1045,8 @@ PyTypeObject PyCoro_Type = {
|
||||||
PyObject_GenericGetAttr, /* tp_getattro */
|
PyObject_GenericGetAttr, /* tp_getattro */
|
||||||
0, /* tp_setattro */
|
0, /* tp_setattro */
|
||||||
0, /* tp_as_buffer */
|
0, /* tp_as_buffer */
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||||
|
Py_TPFLAGS_HAVE_AM_SEND, /* tp_flags */
|
||||||
0, /* tp_doc */
|
0, /* tp_doc */
|
||||||
(traverseproc)gen_traverse, /* tp_traverse */
|
(traverseproc)gen_traverse, /* tp_traverse */
|
||||||
0, /* tp_clear */
|
0, /* tp_clear */
|
||||||
|
@ -1413,7 +1404,8 @@ static PyMethodDef async_gen_methods[] = {
|
||||||
static PyAsyncMethods async_gen_as_async = {
|
static PyAsyncMethods async_gen_as_async = {
|
||||||
0, /* am_await */
|
0, /* am_await */
|
||||||
PyObject_SelfIter, /* am_aiter */
|
PyObject_SelfIter, /* am_aiter */
|
||||||
(unaryfunc)async_gen_anext /* am_anext */
|
(unaryfunc)async_gen_anext, /* am_anext */
|
||||||
|
(sendfunc)PyGen_am_send, /* am_send */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1438,7 +1430,8 @@ PyTypeObject PyAsyncGen_Type = {
|
||||||
PyObject_GenericGetAttr, /* tp_getattro */
|
PyObject_GenericGetAttr, /* tp_getattro */
|
||||||
0, /* tp_setattro */
|
0, /* tp_setattro */
|
||||||
0, /* tp_as_buffer */
|
0, /* tp_as_buffer */
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||||
|
Py_TPFLAGS_HAVE_AM_SEND, /* tp_flags */
|
||||||
0, /* tp_doc */
|
0, /* tp_doc */
|
||||||
(traverseproc)async_gen_traverse, /* tp_traverse */
|
(traverseproc)async_gen_traverse, /* tp_traverse */
|
||||||
0, /* tp_clear */
|
0, /* tp_clear */
|
||||||
|
@ -1676,7 +1669,8 @@ static PyMethodDef async_gen_asend_methods[] = {
|
||||||
static PyAsyncMethods async_gen_asend_as_async = {
|
static PyAsyncMethods async_gen_asend_as_async = {
|
||||||
PyObject_SelfIter, /* am_await */
|
PyObject_SelfIter, /* am_await */
|
||||||
0, /* am_aiter */
|
0, /* am_aiter */
|
||||||
0 /* am_anext */
|
0, /* am_anext */
|
||||||
|
0, /* am_send */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2084,7 +2078,8 @@ static PyMethodDef async_gen_athrow_methods[] = {
|
||||||
static PyAsyncMethods async_gen_athrow_as_async = {
|
static PyAsyncMethods async_gen_athrow_as_async = {
|
||||||
PyObject_SelfIter, /* am_await */
|
PyObject_SelfIter, /* am_await */
|
||||||
0, /* am_aiter */
|
0, /* am_aiter */
|
||||||
0 /* am_anext */
|
0, /* am_anext */
|
||||||
|
0, /* am_send */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5427,6 +5427,13 @@ PyType_Ready(PyTypeObject *type)
|
||||||
_PyObject_ASSERT((PyObject *)type, type->tp_vectorcall_offset > 0);
|
_PyObject_ASSERT((PyObject *)type, type->tp_vectorcall_offset > 0);
|
||||||
_PyObject_ASSERT((PyObject *)type, type->tp_call != NULL);
|
_PyObject_ASSERT((PyObject *)type, type->tp_call != NULL);
|
||||||
}
|
}
|
||||||
|
/* Consistency check for Py_TPFLAGS_HAVE_AM_SEND - flag requires
|
||||||
|
* type->tp_as_async->am_send to be present.
|
||||||
|
*/
|
||||||
|
if (type->tp_flags & Py_TPFLAGS_HAVE_AM_SEND) {
|
||||||
|
_PyObject_ASSERT((PyObject *)type, type->tp_as_async != NULL);
|
||||||
|
_PyObject_ASSERT((PyObject *)type, type->tp_as_async->am_send != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
type->tp_flags |= Py_TPFLAGS_READYING;
|
type->tp_flags |= Py_TPFLAGS_READYING;
|
||||||
|
|
||||||
|
|
|
@ -79,3 +79,4 @@ offsetof(PyHeapTypeObject, as_async.am_await),
|
||||||
offsetof(PyHeapTypeObject, as_async.am_aiter),
|
offsetof(PyHeapTypeObject, as_async.am_aiter),
|
||||||
offsetof(PyHeapTypeObject, as_async.am_anext),
|
offsetof(PyHeapTypeObject, as_async.am_anext),
|
||||||
offsetof(PyHeapTypeObject, ht_type.tp_finalize),
|
offsetof(PyHeapTypeObject, ht_type.tp_finalize),
|
||||||
|
offsetof(PyHeapTypeObject, as_async.am_send),
|
||||||
|
|
Loading…
Reference in New Issue