diff options
author | Yury Selivanov <yury@magic.io> | 2016-06-09 19:13:16 (GMT) |
---|---|---|
committer | Yury Selivanov <yury@magic.io> | 2016-06-09 19:13:16 (GMT) |
commit | 711d25db4802bd7341b48316d169e648285aac70 (patch) | |
tree | 46628b747f3f7bd1ccdc5e9fe7186e28978fa348 /Python | |
parent | 5dee6551e2b98792bc6336206f763623483e7883 (diff) | |
parent | a6f6edbda8648698289a8ee7abef6a35c924151b (diff) | |
download | cpython-711d25db4802bd7341b48316d169e648285aac70.zip cpython-711d25db4802bd7341b48316d169e648285aac70.tar.gz cpython-711d25db4802bd7341b48316d169e648285aac70.tar.bz2 |
Merge 3.5 (issue #27243)
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 40 |
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(); } |