diff options
author | Yury Selivanov <yury@magic.io> | 2016-10-20 15:54:51 -0400 |
---|---|---|
committer | Yury Selivanov <yury@magic.io> | 2016-10-20 15:54:51 -0400 |
commit | 3ceee7b0dad2c262bf6eaadb473b51daa82d9025 (patch) | |
tree | 34b15f7e0d7ccfae55de9323139a5d536768981a | |
parent | ae8ca1c0e2878d1c0ea5b19ca25ca0ac77e1e942 (diff) | |
parent | a4b884f9009e9797e8bb7f8c9e797b4f033dd37e (diff) | |
download | cpython-git-3ceee7b0dad2c262bf6eaadb473b51daa82d9025.tar.gz |
Merge 3.6 (issue #28492)
-rw-r--r-- | Lib/test/test_asyncio/test_futures.py | 13 | ||||
-rw-r--r-- | Modules/_asynciomodule.c | 21 |
2 files changed, 32 insertions, 2 deletions
diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index d20eb687f9..6916b513e8 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -464,6 +464,19 @@ class FutureTests(test_utils.TestCase): futures._set_result_unless_cancelled(fut, 2) self.assertTrue(fut.cancelled()) + def test_future_stop_iteration_args(self): + fut = asyncio.Future(loop=self.loop) + fut.set_result((1, 2)) + fi = fut.__iter__() + result = None + try: + fi.send(None) + except StopIteration as ex: + result = ex.args[0] + else: + self.fail('StopIteration was expected') + self.assertEqual(result, (1, 2)) + class FutureDoneCallbackTests(test_utils.TestCase): diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index d1d9c5425e..d9fe63d320 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -787,9 +787,26 @@ FutureIter_iternext(futureiterobject *it) res = FutureObj_result(fut, NULL); if (res != NULL) { - // normal result - PyErr_SetObject(PyExc_StopIteration, res); + /* The result of the Future is not an exception. + + We cunstruct an exception instance manually with + PyObject_CallFunctionObjArgs and pass it to PyErr_SetObject + (similarly to what genobject.c does). + + This is to handle a situation when "res" is a tuple, in which + case PyErr_SetObject would set the value of StopIteration to + the first element of the tuple. + + (See PyErr_SetObject/_PyErr_CreateException code for details.) + */ + PyObject *e = PyObject_CallFunctionObjArgs( + PyExc_StopIteration, res, NULL); Py_DECREF(res); + if (e == NULL) { + return NULL; + } + PyErr_SetObject(PyExc_StopIteration, e); + Py_DECREF(e); } it->future = NULL; |