[Python-checkins] cpython (3.6): Issue #28492: Fix how StopIteration is raised in _asyncio.Future

yury.selivanov python-checkins at python.org
Thu Oct 20 15:55:10 EDT 2016


https://hg.python.org/cpython/rev/cfe2109ce2c0
changeset:   104588:cfe2109ce2c0
branch:      3.6
parent:      104585:c60d41590054
user:        Yury Selivanov <yury at magic.io>
date:        Thu Oct 20 15:54:20 2016 -0400
summary:
  Issue #28492: Fix how StopIteration is raised in _asyncio.Future

files:
  Lib/test/test_asyncio/test_futures.py |  13 +++++++++
  Misc/NEWS                             |   2 +
  Modules/_asynciomodule.c              |  21 +++++++++++++-
  3 files changed, 34 insertions(+), 2 deletions(-)


diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py
--- a/Lib/test/test_asyncio/test_futures.py
+++ b/Lib/test/test_asyncio/test_futures.py
@@ -464,6 +464,19 @@
         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/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -28,6 +28,8 @@
 - Issue #20766: Fix references leaked by pdb in the handling of SIGINT
   handlers.
 
+- Issue #28492: Fix how StopIteration exception is raised in _asyncio.Future.
+
 Build
 -----
 
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -787,9 +787,26 @@
 
     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;

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list