]> granicus.if.org Git - python/commitdiff
bpo-28893: Set __cause__ for errors in async iteration protocol (#407)
authorYury Selivanov <yselivanov@gmail.com>
Fri, 3 Mar 2017 03:20:00 +0000 (22:20 -0500)
committerGitHub <noreply@github.com>
Fri, 3 Mar 2017 03:20:00 +0000 (22:20 -0500)
Lib/test/test_coroutines.py
Misc/NEWS
Python/ceval.c

index 78439a2acae2d8b030375a020e9e0b05376f105d..b4c7b5be6e208c79d040f3a5034d217cd2edf1ae 100644 (file)
@@ -1680,6 +1680,44 @@ class CoroutineTest(unittest.TestCase):
                 warnings.simplefilter("error")
                 run_async(foo())
 
+    def test_for_11(self):
+        class F:
+            def __aiter__(self):
+                return self
+            def __anext__(self):
+                return self
+            def __await__(self):
+                1 / 0
+
+        async def main():
+            async for _ in F():
+                pass
+
+        with self.assertRaisesRegex(TypeError,
+                                    'an invalid object from __anext__') as c:
+            main().send(None)
+
+        err = c.exception
+        self.assertIsInstance(err.__cause__, ZeroDivisionError)
+
+    def test_for_12(self):
+        class F:
+            def __aiter__(self):
+                return self
+            def __await__(self):
+                1 / 0
+
+        async def main():
+            async for _ in F():
+                pass
+
+        with self.assertRaisesRegex(TypeError,
+                                    'an invalid object from __aiter__') as c:
+            main().send(None)
+
+        err = c.exception
+        self.assertIsInstance(err.__cause__, ZeroDivisionError)
+
     def test_for_tuple(self):
         class Done(Exception): pass
 
index cc896e1b5955cc3a45d6a147f62c1f27bc4dc4d1..12f57f9eecf50be9e2b9bb61c7a9cd2ec97f072d 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.7.0 alpha 1?
 Core and Builtins
 -----------------
 
+- bpo-28893: Set correct __cause__ for errors about invalid awaitables
+  returned from __aiter__ and __anext__.
+
 - bpo-29683: Fixes to memory allocation in _PyCode_SetExtra.  Patch by
   Brian Coleman.
 
index 4022ba2ac96d34dbeca325cd3f5324f798660ce6..49177d8e0587bc71d7504ae0f16615b007387fd2 100644 (file)
@@ -1855,13 +1855,13 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
 
             awaitable = _PyCoro_GetAwaitableIter(iter);
             if (awaitable == NULL) {
-                SET_TOP(NULL);
-                PyErr_Format(
+                _PyErr_FormatFromCause(
                     PyExc_TypeError,
                     "'async for' received an invalid object "
                     "from __aiter__: %.100s",
                     Py_TYPE(iter)->tp_name);
 
+                SET_TOP(NULL);
                 Py_DECREF(iter);
                 goto error;
             } else {
@@ -1920,7 +1920,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
 
                 awaitable = _PyCoro_GetAwaitableIter(next_iter);
                 if (awaitable == NULL) {
-                    PyErr_Format(
+                    _PyErr_FormatFromCause(
                         PyExc_TypeError,
                         "'async for' received an invalid object "
                         "from __anext__: %.100s",