Skip to content

Commit 8584334

Browse files
authored
gh-117459: Keep the traceback in _convert_future_exc (#117460)
1 parent b4fe02f commit 8584334

File tree

3 files changed

+22
-4
lines changed

3 files changed

+22
-4
lines changed

Lib/asyncio/futures.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,9 @@ def _set_result_unless_cancelled(fut, result):
319319
def _convert_future_exc(exc):
320320
exc_class = type(exc)
321321
if exc_class is concurrent.futures.CancelledError:
322-
return exceptions.CancelledError(*exc.args)
323-
elif exc_class is concurrent.futures.TimeoutError:
324-
return exceptions.TimeoutError(*exc.args)
322+
return exceptions.CancelledError(*exc.args).with_traceback(exc.__traceback__)
325323
elif exc_class is concurrent.futures.InvalidStateError:
326-
return exceptions.InvalidStateError(*exc.args)
324+
return exceptions.InvalidStateError(*exc.args).with_traceback(exc.__traceback__)
327325
else:
328326
return exc
329327

Lib/test/test_asyncio/test_futures.py

+19
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import re
66
import sys
77
import threading
8+
import traceback
89
import unittest
910
from unittest import mock
1011
from types import GenericAlias
@@ -416,6 +417,24 @@ def test_copy_state(self):
416417
_copy_future_state(f_cancelled, newf_cancelled)
417418
self.assertTrue(newf_cancelled.cancelled())
418419

420+
try:
421+
raise concurrent.futures.InvalidStateError
422+
except BaseException as e:
423+
f_exc = e
424+
425+
f_conexc = self._new_future(loop=self.loop)
426+
f_conexc.set_exception(f_exc)
427+
428+
newf_conexc = self._new_future(loop=self.loop)
429+
_copy_future_state(f_conexc, newf_conexc)
430+
self.assertTrue(newf_conexc.done())
431+
try:
432+
newf_conexc.result()
433+
except BaseException as e:
434+
newf_exc = e # assertRaises context manager drops the traceback
435+
newf_tb = ''.join(traceback.format_tb(newf_exc.__traceback__))
436+
self.assertEqual(newf_tb.count('raise concurrent.futures.InvalidStateError'), 1)
437+
419438
def test_iter(self):
420439
fut = self._new_future(loop=self.loop)
421440

Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:meth:`asyncio.asyncio.run_coroutine_threadsafe` now keeps the traceback of :class:`CancelledError`, :class:`TimeoutError` and :class:`InvalidStateError` which are raised in the coroutine.

0 commit comments

Comments
 (0)