Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 306a35c

Browse filesBrowse files
authored
gh-148736: Use ag_frame when walking async generators in asyncio.graph (#148737)
1 parent b618874 commit 306a35c
Copy full SHA for 306a35c

3 files changed

+30-1Lines changed: 30 additions & 1 deletion

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎Lib/asyncio/graph.py‎

Copy file name to clipboardExpand all lines: Lib/asyncio/graph.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def _build_graph_for_future(
6262
coro = coro.cr_await
6363
elif hasattr(coro, 'ag_await'):
6464
# A native async generator or duck-type compatible iterator
65-
st.append(FrameCallGraphEntry(coro.cr_frame))
65+
st.append(FrameCallGraphEntry(coro.ag_frame))
6666
coro = coro.ag_await
6767
else:
6868
break
Collapse file

‎Lib/test/test_asyncio/test_graph.py‎

Copy file name to clipboardExpand all lines: Lib/test/test_asyncio/test_graph.py
+26Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import asyncio
22
import io
3+
import sys
34
import unittest
45
from unittest import mock
56

@@ -147,6 +148,31 @@ async def main():
147148
'async generator CallStackTestBase.test_stack_async_gen.<locals>.gen()',
148149
stack_for_gen_nested_call[1])
149150

151+
def test_ag_frame_used_for_async_generator(self):
152+
# Regression test for gh-148736: the ag_await branch of
153+
# _build_graph_for_future must read ag_frame, not cr_frame.
154+
from asyncio.graph import _build_graph_for_future
155+
156+
sentinel_frame = sys._getframe()
157+
158+
class FakeAsyncGen:
159+
ag_await = None
160+
ag_frame = sentinel_frame
161+
162+
class FakeCoro:
163+
cr_frame = sentinel_frame
164+
cr_await = FakeAsyncGen()
165+
166+
loop = asyncio.new_event_loop()
167+
try:
168+
fut = loop.create_future()
169+
fut.get_coro = lambda: FakeCoro()
170+
result = _build_graph_for_future(fut)
171+
finally:
172+
loop.close()
173+
174+
self.assertEqual(len(result.call_stack), 2)
175+
150176
async def test_stack_gather(self):
151177

152178
stack_for_deep = None
Collapse file
+3Lines changed: 3 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a latent :exc:`AttributeError` in :mod:`asyncio` call-graph capture when
2+
walking an async generator's ``ag_await`` chain: the walker referenced
3+
``cr_frame`` instead of ``ag_frame``.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.