Skip to content

Commit 398ff91

Browse files
authored
bpo-28893: Set __cause__ for errors in async iteration protocol (python#407)
1 parent 8d26aa9 commit 398ff91

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

Lib/test/test_coroutines.py

+38
Original file line numberDiff line numberDiff line change
@@ -1680,6 +1680,44 @@ async def foo():
16801680
warnings.simplefilter("error")
16811681
run_async(foo())
16821682

1683+
def test_for_11(self):
1684+
class F:
1685+
def __aiter__(self):
1686+
return self
1687+
def __anext__(self):
1688+
return self
1689+
def __await__(self):
1690+
1 / 0
1691+
1692+
async def main():
1693+
async for _ in F():
1694+
pass
1695+
1696+
with self.assertRaisesRegex(TypeError,
1697+
'an invalid object from __anext__') as c:
1698+
main().send(None)
1699+
1700+
err = c.exception
1701+
self.assertIsInstance(err.__cause__, ZeroDivisionError)
1702+
1703+
def test_for_12(self):
1704+
class F:
1705+
def __aiter__(self):
1706+
return self
1707+
def __await__(self):
1708+
1 / 0
1709+
1710+
async def main():
1711+
async for _ in F():
1712+
pass
1713+
1714+
with self.assertRaisesRegex(TypeError,
1715+
'an invalid object from __aiter__') as c:
1716+
main().send(None)
1717+
1718+
err = c.exception
1719+
self.assertIsInstance(err.__cause__, ZeroDivisionError)
1720+
16831721
def test_for_tuple(self):
16841722
class Done(Exception): pass
16851723

Misc/NEWS

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ What's New in Python 3.7.0 alpha 1?
1010
Core and Builtins
1111
-----------------
1212

13+
- bpo-28893: Set correct __cause__ for errors about invalid awaitables
14+
returned from __aiter__ and __anext__.
15+
1316
- bpo-29683: Fixes to memory allocation in _PyCode_SetExtra. Patch by
1417
Brian Coleman.
1518

Python/ceval.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -1855,13 +1855,13 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
18551855

18561856
awaitable = _PyCoro_GetAwaitableIter(iter);
18571857
if (awaitable == NULL) {
1858-
SET_TOP(NULL);
1859-
PyErr_Format(
1858+
_PyErr_FormatFromCause(
18601859
PyExc_TypeError,
18611860
"'async for' received an invalid object "
18621861
"from __aiter__: %.100s",
18631862
Py_TYPE(iter)->tp_name);
18641863

1864+
SET_TOP(NULL);
18651865
Py_DECREF(iter);
18661866
goto error;
18671867
} else {
@@ -1920,7 +1920,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
19201920

19211921
awaitable = _PyCoro_GetAwaitableIter(next_iter);
19221922
if (awaitable == NULL) {
1923-
PyErr_Format(
1923+
_PyErr_FormatFromCause(
19241924
PyExc_TypeError,
19251925
"'async for' received an invalid object "
19261926
"from __anext__: %.100s",

0 commit comments

Comments
 (0)