-
-
Notifications
You must be signed in to change notification settings - Fork 33.8k
bpo-42085: Introduce dedicated entry in PyAsyncMethods for sending values #22780
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
cdd612e
7fb80fd
d11ba24
4635bf1
6559a1e
0269d6c
5006b27
016f3e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -167,10 +167,23 @@ typedef struct { | |
| objobjargproc mp_ass_subscript; | ||
| } PyMappingMethods; | ||
|
|
||
| #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000 | ||
| typedef enum { | ||
| PYGEN_RETURN = 0, | ||
| PYGEN_ERROR = -1, | ||
| PYGEN_NEXT = 1, | ||
| } PySendResult; | ||
|
|
||
| typedef PySendResult (*sendfunc)(PyObject *iter, PyObject *value, PyObject **result); | ||
| #endif | ||
|
|
||
| typedef struct { | ||
| unaryfunc am_await; | ||
| unaryfunc am_aiter; | ||
| unaryfunc am_anext; | ||
| #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000 | ||
| sendfunc am_send; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should not we add corresponding
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Do we support extensions compiled for higher versions of Python in lower versions of Python? If I compile something for 3.10 I wouldn't expect it to work in 3.9.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO we don't need a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But if you compile something for 3.9 it is expected to work in 3.10 and do not read uninitialized slot.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps there is a bug in the PEP 492 implementation.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahh, I see now, thanks for explaining! Yeah, in this case we do need a flag.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Well, I don't think we need to do anything now that
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We used an existing slot for PEP-492, so the ABI did not change. |
||
| #endif | ||
| } PyAsyncMethods; | ||
|
|
||
| typedef struct { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1484,7 +1484,8 @@ future_cls_getitem(PyObject *cls, PyObject *type) | |
| static PyAsyncMethods FutureType_as_async = { | ||
| (unaryfunc)future_new_iter, /* am_await */ | ||
| 0, /* am_aiter */ | ||
| 0 /* am_anext */ | ||
| 0, /* am_anext */ | ||
| 0, /* am_send */ | ||
| }; | ||
|
|
||
| static PyMethodDef FutureType_methods[] = { | ||
|
|
@@ -1602,37 +1603,55 @@ FutureIter_dealloc(futureiterobject *it) | |
| } | ||
| } | ||
|
|
||
| static PyObject * | ||
| FutureIter_iternext(futureiterobject *it) | ||
| static PySendResult | ||
| FutureIter_am_send(futureiterobject *it, PyObject *arg, PyObject **result) | ||
|
||
| { | ||
| PyObject *res; | ||
| FutureObj *fut = it->future; | ||
|
|
||
| if (fut == NULL) { | ||
| return NULL; | ||
| return PYGEN_ERROR; | ||
serhiy-storchaka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| if (fut->fut_state == STATE_PENDING) { | ||
| if (!fut->fut_blocking) { | ||
| fut->fut_blocking = 1; | ||
| Py_INCREF(fut); | ||
| return (PyObject *)fut; | ||
| *result = (PyObject *)fut; | ||
| return PYGEN_NEXT; | ||
| } | ||
| PyErr_SetString(PyExc_RuntimeError, | ||
| "await wasn't used with future"); | ||
| return NULL; | ||
| return PYGEN_ERROR; | ||
serhiy-storchaka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| it->future = NULL; | ||
| res = _asyncio_Future_result_impl(fut); | ||
| if (res != NULL) { | ||
| /* The result of the Future is not an exception. */ | ||
| (void)_PyGen_SetStopIterationValue(res); | ||
| Py_DECREF(res); | ||
| *result = res; | ||
| return PYGEN_RETURN; | ||
| } | ||
|
|
||
| Py_DECREF(fut); | ||
| return NULL; | ||
| 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; | ||
| case PYGEN_NEXT: | ||
| return result; | ||
| case PYGEN_ERROR: | ||
| return NULL; | ||
| default: | ||
| Py_UNREACHABLE(); | ||
| } | ||
| } | ||
|
|
||
| static PyObject * | ||
|
|
@@ -1721,12 +1740,21 @@ static PyMethodDef FutureIter_methods[] = { | |
| {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 = { | ||
| PyVarObject_HEAD_INIT(NULL, 0) | ||
| "_asyncio.FutureIter", | ||
| .tp_basicsize = sizeof(futureiterobject), | ||
| .tp_itemsize = 0, | ||
| .tp_dealloc = (destructor)FutureIter_dealloc, | ||
| .tp_as_async = &FutureIterType_as_async, | ||
| .tp_getattro = PyObject_GenericGetAttr, | ||
| .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, | ||
| .tp_traverse = (traverseproc)FutureIter_traverse, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -274,7 +274,9 @@ PyIter_Send(PyObject *iter, PyObject *arg, PyObject **result) | |
| _Py_IDENTIFIER(send); | ||
| assert(arg != NULL); | ||
| assert(result != NULL); | ||
|
|
||
| if (Py_TYPE(iter)->tp_as_async != NULL && Py_TYPE(iter)->tp_as_async->am_send != NULL) { | ||
| return Py_TYPE(iter)->tp_as_async->am_send(iter, arg, result); | ||
| } | ||
| if (PyGen_CheckExact(iter) || PyCoro_CheckExact(iter)) { | ||
| return gen_send_ex2((PyGenObject *)iter, arg, result, 0, 0); | ||
| } | ||
|
|
@@ -1031,7 +1033,8 @@ static PyMethodDef coro_methods[] = { | |
| static PyAsyncMethods coro_as_async = { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wait, with this PR regular generators no longer benefit from the faster |
||
| (unaryfunc)coro_await, /* am_await */ | ||
| 0, /* am_aiter */ | ||
| 0 /* am_anext */ | ||
| 0, /* am_anext */ | ||
| 0, /* am_send */ | ||
| }; | ||
|
|
||
| PyTypeObject PyCoro_Type = { | ||
|
|
@@ -1413,7 +1416,8 @@ static PyMethodDef async_gen_methods[] = { | |
| static PyAsyncMethods async_gen_as_async = { | ||
| 0, /* am_await */ | ||
| PyObject_SelfIter, /* am_aiter */ | ||
| (unaryfunc)async_gen_anext /* am_anext */ | ||
| (unaryfunc)async_gen_anext, /* am_anext */ | ||
| 0, /* am_send */ | ||
| }; | ||
|
|
||
|
|
||
|
|
@@ -1676,7 +1680,8 @@ static PyMethodDef async_gen_asend_methods[] = { | |
| static PyAsyncMethods async_gen_asend_as_async = { | ||
| PyObject_SelfIter, /* am_await */ | ||
| 0, /* am_aiter */ | ||
| 0 /* am_anext */ | ||
| 0, /* am_anext */ | ||
| 0, /* am_send */ | ||
| }; | ||
|
|
||
|
|
||
|
|
@@ -2084,7 +2089,8 @@ static PyMethodDef async_gen_athrow_methods[] = { | |
| static PyAsyncMethods async_gen_athrow_as_async = { | ||
| PyObject_SelfIter, /* am_await */ | ||
| 0, /* am_aiter */ | ||
| 0 /* am_anext */ | ||
| 0, /* am_anext */ | ||
| 0, /* am_send */ | ||
| }; | ||
|
|
||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cpython/object.his only imported whenPy_LIMITED_APIis not defined, so this#ifdoes not make sense. Also, moving the declaration ofPySendResulthere removes it from the limited API. It actually break the limited API because importingabstract.hwith the limited API will be error.