bpo-29587: Make gen.throw() chain exceptions with yield from (GH-19858)

The previous commits on bpo-29587 got exception chaining working
with gen.throw() in the `yield` case. This patch also gets the
`yield from` case working.

As a consequence, implicit exception chaining now also works in
the asyncio scenario of awaiting on a task when an exception is
already active.

Tests are included for both the asyncio case and the pure
generator-only case.
This commit is contained in:
Chris Jerdonek 2020-05-13 16:18:27 -07:00 committed by GitHub
parent d6fb53fe42
commit 75cd8e48c6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 11 deletions

View file

@ -466,6 +466,33 @@ class BaseTaskTests:
t = outer()
self.assertEqual(self.loop.run_until_complete(t), 1042)
def test_exception_chaining_after_await(self):
# Test that when awaiting on a task when an exception is already
# active, if the task raises an exception it will be chained
# with the original.
loop = asyncio.new_event_loop()
self.set_event_loop(loop)
async def raise_error():
raise ValueError
async def run():
try:
raise KeyError(3)
except Exception as exc:
task = self.new_task(loop, raise_error())
try:
await task
except Exception as exc:
self.assertEqual(type(exc), ValueError)
chained = exc.__context__
self.assertEqual((type(chained), chained.args),
(KeyError, (3,)))
task = self.new_task(loop, run())
loop.run_until_complete(task)
loop.close()
def test_cancel(self):
def gen():