[pypy-commit] pypy py3.6: Remember the __cause__ when an exception is raised in __await__.
amauryfa
pypy.commits at gmail.com
Mon Mar 5 03:52:42 EST 2018
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3.6
Changeset: r93958:ab182b33a9c1
Date: 2018-03-05 09:26 +0100
http://bitbucket.org/pypy/pypy/changeset/ab182b33a9c1/
Log: Remember the __cause__ when an exception is raised in __await__.
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1596,14 +1596,15 @@
try:
w_awaitable = get_awaitable_iter(space, w_iter)
except OperationError as e:
- # yay! get_awaitable_iter() carefully builds a useful
- # error message, but here we're eating *all errors*
- # to replace it with a generic one.
if e.async(space):
raise
- raise oefmt(space.w_TypeError,
+ new_error = oefmt(space.w_TypeError,
"'async for' received an invalid object "
"from __aiter__: %T", w_iter)
+ e.normalize_exception(space)
+ new_error.normalize_exception(space)
+ new_error.set_cause(space, e.get_w_value(space))
+ raise new_error
space.warn(space.newtext(
"'%s' implements legacy __aiter__ protocol; "
"__aiter__ should return an asynchronous "
@@ -1628,14 +1629,15 @@
try:
w_awaitable = get_awaitable_iter(space, w_next_iter)
except OperationError as e:
- # yay! get_awaitable_iter() carefully builds a useful
- # error message, but here we're eating *all errors*
- # to replace it with a generic one.
if e.async(space):
raise
- raise oefmt(space.w_TypeError,
+ new_error = oefmt(space.w_TypeError,
"'async for' received an invalid object "
"from __anext__: %T", w_next_iter)
+ e.normalize_exception(space)
+ new_error.normalize_exception(space)
+ new_error.set_cause(space, e.get_w_value(space))
+ raise new_error
self.pushvalue(w_awaitable)
def FORMAT_VALUE(self, oparg, next_instr):
diff --git a/pypy/interpreter/test/test_coroutine.py b/pypy/interpreter/test/test_coroutine.py
--- a/pypy/interpreter/test/test_coroutine.py
+++ b/pypy/interpreter/test/test_coroutine.py
@@ -75,6 +75,24 @@
assert next(cr.__await__()) == 20
"""
+ def test_for_error_cause(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
+
+ c = raises(TypeError, main().send, None)
+ assert 'an invalid object from __anext__' in c.value.args[0], c.value
+ assert isinstance(c.value.__cause__, ZeroDivisionError)
+ """
+
def test_set_coroutine_wrapper(self): """
import sys
async def f():
More information about the pypy-commit
mailing list