-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
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; | ||
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 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.
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. 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 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. 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. 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. 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 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) | ||
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. Is 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. yes, there is a comment in
|
||
{ | ||
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 = { | ||
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.h
is only imported whenPy_LIMITED_API
is not defined, so this#if
does not make sense. Also, moving the declaration ofPySendResult
here removes it from the limited API. It actually break the limited API because importingabstract.h
with the limited API will be error.