summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorYury Selivanov <yury@magic.io>2016-06-09 19:13:16 (GMT)
committerYury Selivanov <yury@magic.io>2016-06-09 19:13:16 (GMT)
commit711d25db4802bd7341b48316d169e648285aac70 (patch)
tree46628b747f3f7bd1ccdc5e9fe7186e28978fa348 /Python
parent5dee6551e2b98792bc6336206f763623483e7883 (diff)
parenta6f6edbda8648698289a8ee7abef6a35c924151b (diff)
downloadcpython-711d25db4802bd7341b48316d169e648285aac70.zip
cpython-711d25db4802bd7341b48316d169e648285aac70.tar.gz
cpython-711d25db4802bd7341b48316d169e648285aac70.tar.bz2
Merge 3.5 (issue #27243)
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 5f8dbcd..b6ce67c 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1935,8 +1935,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
PyObject *obj = TOP();
PyTypeObject *type = Py_TYPE(obj);
- if (type->tp_as_async != NULL)
+ if (type->tp_as_async != NULL) {
getter = type->tp_as_async->am_aiter;
+ }
if (getter != NULL) {
iter = (*getter)(obj);
@@ -1957,6 +1958,27 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
goto error;
}
+ if (Py_TYPE(iter)->tp_as_async != NULL &&
+ Py_TYPE(iter)->tp_as_async->am_anext != NULL) {
+
+ /* Starting with CPython 3.5.2 __aiter__ should return
+ asynchronous iterators directly (not awaitables that
+ resolve to asynchronous iterators.)
+
+ Therefore, we check if the object that was returned
+ from __aiter__ has an __anext__ method. If it does,
+ we wrap it in an awaitable that resolves to `iter`.
+
+ See http://bugs.python.org/issue27243 for more
+ details.
+ */
+
+ PyObject *wrapper = _PyAIterWrapper_New(iter);
+ Py_DECREF(iter);
+ SET_TOP(wrapper);
+ DISPATCH();
+ }
+
awaitable = _PyCoro_GetAwaitableIter(iter);
if (awaitable == NULL) {
SET_TOP(NULL);
@@ -1968,9 +1990,23 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(iter);
goto error;
- } else
+ } else {
Py_DECREF(iter);
+ if (PyErr_WarnFormat(
+ PyExc_PendingDeprecationWarning, 1,
+ "'%.100s' implements legacy __aiter__ protocol; "
+ "__aiter__ should return an asynchronous "
+ "iterator, not awaitable",
+ type->tp_name))
+ {
+ /* Warning was converted to an error. */
+ Py_DECREF(awaitable);
+ SET_TOP(NULL);
+ goto error;
+ }
+ }
+
SET_TOP(awaitable);
DISPATCH();
}