Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 4 additions & 14 deletions src/decompiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19314,20 +19314,10 @@ let reopen = self
return true;
}
let target = inst.target.unwrap_or(inst.end());
// async for: the iterable expression is an Await, or we are
// inside an async def using GET_AITER
let is_async = matches!(
self.stack.last(),
Some(Sv::E(e)) if matches!(&**e, Expr::Await(_))
);
if is_async {
if let Some(Sv::E(e)) = self.stack.last_mut() {
if let Expr::Await(inner) = &**e {
*e = inner.clone();
}
}
}
self.handle_for_iter(target, is_async);
// FOR_ITER iterates synchronously, even when the collection
// was produced by `await fetch()`. Genuine async iteration
// uses GET_AITER/GET_ANEXT and its separate decoder path.
self.handle_for_iter(target, false);
true
}
Op::FOR_LOOP => {
Expand Down
14 changes: 14 additions & 0 deletions tests/behavior/cases/b_awaited_synchronous_iteration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# MIN_VERSION: 3.9
import asyncio

async def awaited(read):
result = []
for item in await read():
result.append(item)
return result


async def read():
print("read")
return [1, 2, 3]
print(asyncio.run(awaited(read)))
23 changes: 23 additions & 0 deletions tests/fixtures/awaited_synchronous_iteration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Versioned .pyc files are consumed by tests/integration.rs.

# async/await syntax starts in Python 3.5.

async def awaited(read):
result = []
for item in await read():
result.append(item)
return result


async def asynchronous(read):
result = []
async for item in read():
result.append(item)
return result


async def sync(read):
result = []
for item in read():
result.append(item)
return result
25 changes: 25 additions & 0 deletions tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,28 @@ fn py314_hello() {
"py3.14 hello",
);
}

#[test]
fn awaited_collections_use_synchronous_iteration() {
for version in ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] {
let (src, clean) = decompile_fixture(&format!("awaited_synchronous_iteration.{version}.pyc"));
assert!(clean, "Python {version}: output marked incomplete:\n{src}");
assert_contains(&src, &[
r#"async def awaited(read):
result = []
for item in await read():
result.append(item)
return result"#,
r#"async def asynchronous(read):
result = []
async for item in read():
result.append(item)
return result"#,
r#"async def sync(read):
result = []
for item in read():
result.append(item)
return result"#,
], version);
}
}
Binary file added tests/pyc/awaited_synchronous_iteration.3.10.pyc
Binary file not shown.
Binary file added tests/pyc/awaited_synchronous_iteration.3.11.pyc
Binary file not shown.
Binary file added tests/pyc/awaited_synchronous_iteration.3.12.pyc
Binary file not shown.
Binary file added tests/pyc/awaited_synchronous_iteration.3.13.pyc
Binary file not shown.
Binary file added tests/pyc/awaited_synchronous_iteration.3.14.pyc
Binary file not shown.
Binary file added tests/pyc/awaited_synchronous_iteration.3.8.pyc
Binary file not shown.
Binary file added tests/pyc/awaited_synchronous_iteration.3.9.pyc
Binary file not shown.