diff --git a/Lib/asyncio/base_tasks.py b/Lib/asyncio/base_tasks.py index c907b683413732..2e297c6e0802be 100644 --- a/Lib/asyncio/base_tasks.py +++ b/Lib/asyncio/base_tasks.py @@ -42,8 +42,11 @@ def _task_get_stack(task, limit): elif hasattr(task._coro, 'ag_frame'): # case 3: async generators f = task._coro.ag_frame + elif not task.done() and hasattr(task._coro, 'aga_gen'): + # case 4: async generator's asend/athrow/aclose + f = task._coro.aga_gen.ag_frame else: - # case 4: unknown objects + # case 5: unknown objects f = None if f is not None: while f is not None: diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index d4d3863923e79e..277b856f57a136 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -335,6 +335,40 @@ async def runner(): self.loop.run_until_complete(runner()) + def test_get_stack_async_generator(self): + # gh-161178 + async def gen(): + try: + yield + except ValueError: + pass + finally: + await asyncio.sleep(0) + yield + + async def runner(method, args): + agen = gen() + await anext(agen) + task = self.new_task(self.loop, getattr(agen, method)(*args)) + await asyncio.sleep(0) + frame = agen.ag_frame + stack = task.get_stack() + await task + try: + self.assertEqual(stack, [frame]) + self.assertEqual(task.get_stack(), []) + finally: + await agen.aclose() + + for method, args in ( + ('__anext__', ()), + ('asend', (None,)), + ('athrow', (ValueError(),)), + ('aclose', ()), + ): + with self.subTest(method=method): + self.loop.run_until_complete(runner(method, args)) + def test_task_repr(self): self.loop.set_debug(False) diff --git a/Misc/NEWS.d/next/Library/2026-11-02-16-28-11.gh-issue-161178.D3-23R.rst b/Misc/NEWS.d/next/Library/2026-11-02-16-28-11.gh-issue-161178.D3-23R.rst new file mode 100644 index 00000000000000..1130fbe95ba019 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-11-02-16-28-11.gh-issue-161178.D3-23R.rst @@ -0,0 +1,2 @@ +Fix :meth:`asyncio.Task.print_stack` to include frames from async generator +operations. Patch by Timofei Ivankov