gh-154791: Fix asyncio.Future losing traceback on repeated result() call (#154798)

kumaraditya303 <[email protected]> Fri, 31 Jul 2026 09:08:57 -0400 (EDT)
Newsgroups gmane.comp.python.cvs
Message-ID <[email protected]>
https://github.com/python/cpython/commit/93e2c7703c5a3c98a9a7d6bf4dcab4aac0d27c6e
commit: 93e2c7703c5a3c98a9a7d6bf4dcab4aac0d27c6e
branch: main
author: Iaroslav <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2026-07-31T13:06:47Z
summary:

gh-154791: Fix asyncio.Future losing traceback on repeated result() call (#154798)

files:
A Misc/NEWS.d/next/Library/2026-07-28-08-02-41.gh-issue-154791.ey7POa.rst
M Lib/test/test_asyncio/test_futures2.py
M Modules/_asynciomodule.c

diff --git a/Lib/test/test_asyncio/test_futures2.py b/Lib/test/test_asyncio/test_futures2.py
index cf90835ce87cc30..1878cf8adf63a3b 100644
--- a/Lib/test/test_asyncio/test_futures2.py
+++ b/Lib/test/test_asyncio/test_futures2.py
@@ -28,6 +28,26 @@ async def raise_exc():
             else:
                 self.fail('TypeError was not raised')
 
+    async def test_future_traceback_preserved_after_suppress(self):
+        async def raise_exc():
+            raise TypeError(42)
+
+        future = self.cls(raise_exc())
+        try:
+            await future
+        except TypeError:
+            pass
+
+        try:
+            await future
+        except TypeError as e:
+            tb = ''.join(traceback.format_tb(e.__traceback__))
+            self.assertIn('raise_exc', tb,
+                'Original raise site lost after first result() call')
+        else:
+            self.fail('TypeError was not raised')
+
+
     async def test_task_exc_handler_correct_context(self):
         # see https://github.com/python/cpython/issues/96704
         name = contextvars.ContextVar('name', default='foo')
diff --git a/Misc/NEWS.d/next/Library/2026-07-28-08-02-41.gh-issue-154791.ey7POa.rst b/Misc/NEWS.d/next/Library/2026-07-28-08-02-41.gh-issue-154791.ey7POa.rst
new file mode 100644
index 000000000000000..35008e35314b907
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-07-28-08-02-41.gh-issue-154791.ey7POa.rst
@@ -0,0 +1,5 @@
+Fix :class:`asyncio.Future` (C implementation) losing the initial exception
+traceback frames when ``Future.result()`` is called more than once. Previously,
+the C implementation cleared the stored traceback after the first call, causing
+subsequent raises to omit the original raise site. The pure-Python
+implementation was unaffected.
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index 0cd41d0b4c4d0dc..ec6f35f161136c1 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -769,7 +769,6 @@ future_get_result(asyncio_state *state, FutureObj *fut, PyObject **result)
             return -1;
         }
         *result = Py_NewRef(fut->fut_exception);
-        Py_CLEAR(fut->fut_exception_tb);
         return 1;
     }
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]