summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYury Selivanov <yselivanov@gmail.com>2017-03-03 03:20:00 (GMT)
committerGitHub <noreply@github.com>2017-03-03 03:20:00 (GMT)
commit398ff91ac0b8f4d930cd5d9e3e6a4bf247f810ef (patch)
tree574e40060c9c962fa87627af595ee540dbe33ab1
parent8d26aa930c0123933a1ceb12fceba4f5aef4e95e (diff)
downloadcpython-398ff91ac0b8f4d930cd5d9e3e6a4bf247f810ef.zip
cpython-398ff91ac0b8f4d930cd5d9e3e6a4bf247f810ef.tar.gz
cpython-398ff91ac0b8f4d930cd5d9e3e6a4bf247f810ef.tar.bz2
bpo-28893: Set __cause__ for errors in async iteration protocol (#407)
-rw-r--r--Lib/test/test_coroutines.py38
-rw-r--r--Misc/NEWS3
-rw-r--r--Python/ceval.c6
3 files changed, 44 insertions, 3 deletions
diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py
index 78439a2..b4c7b5b 100644
--- a/Lib/test/test_coroutines.py
+++ b/Lib/test/test_coroutines.py
@@ -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
diff --git a/Misc/NEWS b/Misc/NEWS
index cc896e1..12f57f9 100644
--- 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.
diff --git a/Python/ceval.c b/Python/ceval.c
index 4022ba2..49177d8 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -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",