From beb04c5f9f4be0dc144695f398ec68b129aadf92 Mon Sep 17 00:00:00 2001 From: rsp4jack Date: Tue, 2 Apr 2024 21:00:46 +0800 Subject: [PATCH 1/4] Persist traceback for _convert_future_exc --- Lib/asyncio/futures.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index 5d35321db7943b..ba525ea62f254b 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -319,11 +319,11 @@ def _set_result_unless_cancelled(fut, result): def _convert_future_exc(exc): exc_class = type(exc) if exc_class is concurrent.futures.CancelledError: - return exceptions.CancelledError(*exc.args) + return exceptions.CancelledError(*exc.args).with_traceback(exc.__traceback__) elif exc_class is concurrent.futures.TimeoutError: - return exceptions.TimeoutError(*exc.args) + return exceptions.TimeoutError(*exc.args).with_traceback(exc.__traceback__) elif exc_class is concurrent.futures.InvalidStateError: - return exceptions.InvalidStateError(*exc.args) + return exceptions.InvalidStateError(*exc.args).with_traceback(exc.__traceback__) else: return exc From 1e285ace4ac4d3008670171f66fd0b8b25d13835 Mon Sep 17 00:00:00 2001 From: rsp4jack Date: Tue, 2 Apr 2024 21:03:46 +0800 Subject: [PATCH 2/4] Add regression test for #117459 --- Lib/test/test_asyncio/test_futures.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index d3e8efec1c04c2..458b70451a306a 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -5,6 +5,7 @@ import re import sys import threading +import traceback import unittest from unittest import mock from types import GenericAlias @@ -416,6 +417,24 @@ def test_copy_state(self): _copy_future_state(f_cancelled, newf_cancelled) self.assertTrue(newf_cancelled.cancelled()) + try: + raise concurrent.futures.InvalidStateError + except BaseException as e: + f_exc = e + + f_conexc = self._new_future(loop=self.loop) + f_conexc.set_exception(f_exc) + + newf_conexc = self._new_future(loop=self.loop) + _copy_future_state(f_conexc, newf_conexc) + self.assertTrue(newf_conexc.done()) + try: + newf_conexc.result() + except BaseException as e: + newf_exc = e # assertRaises context manager drops the traceback + newf_tb = ''.join(traceback.format_tb(newf_exc.__traceback__)) + self.assertEqual(newf_tb.count('raise concurrent.futures.InvalidStateError'), 1) + def test_iter(self): fut = self._new_future(loop=self.loop) From a3dfaee22664535f67012744882a148d34939119 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Tue, 2 Apr 2024 13:13:47 +0000 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2024-04-02-13-13-46.gh-issue-117459.jiIZmH.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2024-04-02-13-13-46.gh-issue-117459.jiIZmH.rst diff --git a/Misc/NEWS.d/next/Library/2024-04-02-13-13-46.gh-issue-117459.jiIZmH.rst b/Misc/NEWS.d/next/Library/2024-04-02-13-13-46.gh-issue-117459.jiIZmH.rst new file mode 100644 index 00000000000000..549bd44112befe --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-04-02-13-13-46.gh-issue-117459.jiIZmH.rst @@ -0,0 +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. From 214f7934ae4db7e7dd32e76a038a4332fa59b8bf Mon Sep 17 00:00:00 2001 From: rsp4jack Date: Wed, 3 Apr 2024 21:00:10 +0800 Subject: [PATCH 4/4] Remove redundant check for TimeoutError As https://github.com/python/cpython/issues/117459#issuecomment-2034320722 said, TimeoutError is a builtin exception now --- Lib/asyncio/futures.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index ba525ea62f254b..9c1b5e49e1a70b 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -320,8 +320,6 @@ def _convert_future_exc(exc): exc_class = type(exc) if exc_class is concurrent.futures.CancelledError: return exceptions.CancelledError(*exc.args).with_traceback(exc.__traceback__) - elif exc_class is concurrent.futures.TimeoutError: - return exceptions.TimeoutError(*exc.args).with_traceback(exc.__traceback__) elif exc_class is concurrent.futures.InvalidStateError: return exceptions.InvalidStateError(*exc.args).with_traceback(exc.__traceback__) else: