bpo-45390: Propagate CancelledError's message from cancelled task to its awaiter (GH-31383)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
Andrew Svetlov 2022-02-21 22:59:04 +02:00 committed by GitHub
parent 59585d6b2e
commit 4140bcb1cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 79 additions and 39 deletions

View file

@ -124,9 +124,11 @@ class BaseTaskTests:
t.cancel('my message')
self.assertEqual(t._cancel_message, 'my message')
with self.assertRaises(asyncio.CancelledError):
with self.assertRaises(asyncio.CancelledError) as cm:
self.loop.run_until_complete(t)
self.assertEqual('my message', cm.exception.args[0])
def test_task_cancel_message_setter(self):
async def coro():
pass
@ -135,9 +137,11 @@ class BaseTaskTests:
t._cancel_message = 'my new message'
self.assertEqual(t._cancel_message, 'my new message')
with self.assertRaises(asyncio.CancelledError):
with self.assertRaises(asyncio.CancelledError) as cm:
self.loop.run_until_complete(t)
self.assertEqual('my new message', cm.exception.args[0])
def test_task_del_collect(self):
class Evil:
def __del__(self):
@ -590,11 +594,11 @@ class BaseTaskTests:
with self.assertRaises(asyncio.CancelledError) as cm:
loop.run_until_complete(task)
exc = cm.exception
self.assertEqual(exc.args, ())
self.assertEqual(exc.args, expected_args)
actual = get_innermost_context(exc)
self.assertEqual(actual,
(asyncio.CancelledError, expected_args, 2))
(asyncio.CancelledError, expected_args, 0))
def test_cancel_with_message_then_future_exception(self):
# Test Future.exception() after calling cancel() with a message.
@ -624,11 +628,39 @@ class BaseTaskTests:
with self.assertRaises(asyncio.CancelledError) as cm:
loop.run_until_complete(task)
exc = cm.exception
self.assertEqual(exc.args, ())
self.assertEqual(exc.args, expected_args)
actual = get_innermost_context(exc)
self.assertEqual(actual,
(asyncio.CancelledError, expected_args, 2))
(asyncio.CancelledError, expected_args, 0))
def test_cancellation_exception_context(self):
loop = asyncio.new_event_loop()
self.set_event_loop(loop)
fut = loop.create_future()
async def sleep():
fut.set_result(None)
await asyncio.sleep(10)
async def coro():
inner_task = self.new_task(loop, sleep())
await fut
loop.call_soon(inner_task.cancel, 'msg')
try:
await inner_task
except asyncio.CancelledError as ex:
raise ValueError("cancelled") from ex
task = self.new_task(loop, coro())
with self.assertRaises(ValueError) as cm:
loop.run_until_complete(task)
exc = cm.exception
self.assertEqual(exc.args, ('cancelled',))
actual = get_innermost_context(exc)
self.assertEqual(actual,
(asyncio.CancelledError, ('msg',), 1))
def test_cancel_with_message_before_starting_task(self):
loop = asyncio.new_event_loop()
@ -648,11 +680,11 @@ class BaseTaskTests:
with self.assertRaises(asyncio.CancelledError) as cm:
loop.run_until_complete(task)
exc = cm.exception
self.assertEqual(exc.args, ())
self.assertEqual(exc.args, ('my message',))
actual = get_innermost_context(exc)
self.assertEqual(actual,
(asyncio.CancelledError, ('my message',), 2))
(asyncio.CancelledError, ('my message',), 0))
def test_cancel_yield(self):
async def task():
@ -2296,15 +2328,17 @@ class BaseTaskTests:
try:
loop.run_until_complete(main())
except asyncio.CancelledError as exc:
self.assertEqual(exc.args, ())
exc_type, exc_args, depth = get_innermost_context(exc)
self.assertEqual((exc_type, exc_args),
(asyncio.CancelledError, expected_args))
# The exact traceback seems to vary in CI.
self.assertIn(depth, (2, 3))
self.assertEqual(exc.args, expected_args)
actual = get_innermost_context(exc)
self.assertEqual(
actual,
(asyncio.CancelledError, expected_args, 0),
)
else:
self.fail('gather did not propagate the cancellation '
'request')
self.fail(
'gather() does not propagate CancelledError '
'raised by inner task to the gather() caller.'
)
def test_exception_traceback(self):
# See http://bugs.python.org/issue28843