https://github.com/python/cpython/commit/5b9e06e5b479f4405f84f1f635f8dd8b91950ded
commit: 5b9e06e5b479f4405f84f1f635f8dd8b91950ded
branch: 3.15
author: Timofei Ivankov <[email protected]>
committer: hugovk <[email protected]>
date: 2026-09-07T15:35:35+03:00
summary:
[3.15] gh-156988: Fix asyncio call graph loss at sync generators (#157004)
files:
A Misc/NEWS.d/next/Library/2026-09-05-18-23-30.gh-issue-156988.nEUQE6.rst
M Lib/asyncio/graph.py
M Lib/test/test_asyncio/test_graph.py
diff --git a/Lib/asyncio/graph.py b/Lib/asyncio/graph.py
index 54df7afa5553b97..d0a54f3625b37e5 100644
--- a/Lib/asyncio/graph.py
+++ b/Lib/asyncio/graph.py
@@ -155,7 +155,9 @@ def capture_call_graph(
f = sys._getframe(depth) if limit != 0 else None
try:
while f is not None:
- is_async = f.f_generator is not None
+ # gh-156988: sync gen should not clear the call chain
+ is_async = isinstance(
+ f.f_generator, (types.CoroutineType, types.AsyncGeneratorType))
call_stack.append(FrameCallGraphEntry(f))
if is_async:
diff --git a/Lib/test/test_asyncio/test_graph.py
b/Lib/test/test_asyncio/test_graph.py
index 690f8f58b8f10da..50fa18e888fd22b 100644
--- a/Lib/test/test_asyncio/test_graph.py
+++ b/Lib/test/test_asyncio/test_graph.py
@@ -425,6 +425,26 @@ async def boom():
self.assertEqual(asyncio.capture_call_graph(task).call_stack,
())
self.assertIn(f"name={task.get_name()!r}", buf.getvalue())
+ async def test_capture_call_graph_generator_keeps_caller_frames(self):
+ # gh-156988: sync gen should not clear the call chain
+ stack = None
+
+ def gen():
+ nonlocal stack
+ graph = asyncio.capture_call_graph()
+ stack = [entry.frame.f_code.co_name for entry in graph.call_stack]
+ yield
+
+ def middle():
+ for _ in gen():
+ pass
+
+ async def main():
+ middle()
+
+ await main()
+ self.assertEqual(stack[:3], ['gen', 'middle', 'main'])
+
@unittest.skipIf(
not hasattr(asyncio.futures, "_c_future_add_to_awaited_by"),
diff --git
a/Misc/NEWS.d/next/Library/2026-09-05-18-23-30.gh-issue-156988.nEUQE6.rst
b/Misc/NEWS.d/next/Library/2026-09-05-18-23-30.gh-issue-156988.nEUQE6.rst
new file mode 100644
index 000000000000000..6cb2f1f4cf14ae0
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-09-05-18-23-30.gh-issue-156988.nEUQE6.rst
@@ -0,0 +1,2 @@
+:func:`asyncio.print_call_graph` no longer truncates the call stack at a
+synchronous generator.
_______________________________________________
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]