-
Notifications
You must be signed in to change notification settings - Fork 767
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generator with await not considered an AsyncGenerator #1348
Comments
I'm surprised that this code runs without generating a runtime exception. PEP 492, which introduced the
Likewise, PEP 530, which introduced the use of
Perhaps you can help me understand why the Python interpreter appears to allow the use of |
That aspect surprised me as well to be honest and is more likely just lenience in the Python interpreter allowing it to run technically invalid code as if it were valid. Originally the sample code did use an async function, but I removed it once I realised it still held up. Edit: actually, on second thought, it makes sense that await would be allowed within a generator expression in a non-async function - otherwise what you actually have is a coroutine function which resolves to an async generator (and has to be called with 'await' as in the amended example, rather than directly returning the asynchronous generator). I agree though it seems to contradict the PEP. Perhaps it's documented elsewhere. However, with regards to comprehensions - I believe that would be referring specifically to list comprehensions, rather than generators - I don't believe there's any way a synchronous generator could involve an await, regardless of the function which called it. Therefore, the issue of asynchronous generators still holds if you make the function async and ignore the weirdness of having an await in a non-async function: import asyncio
from typing import AsyncGenerator
async def get_value(v: int) -> int:
await asyncio.sleep(1)
return v + 1
async def get_generator() -> AsyncGenerator[int, None]:
return (await get_value(v) for v in [1, 2, 3])
async def test() -> None:
print(type(await get_generator()))
async for x in await get_generator():
print(x)
asyncio.get_event_loop().run_until_complete(test()) I'll revise the original issue accordingly. |
I think the code was technically valid for the |
Yes, actually I think that PEP, when it refers to comprehension, means specifically list/dict/set comprehension (as the examples in that section would suggest), and not generators. Async comprehension is only legal in an async function of course because the function must await the result to be able to have a list/dict/set, but not the case with async generators. |
I've updated the type checking logic to allow these cases without generating false positive errors. |
This issue has been fixed in version 2021.6.0, which we've just released. You can find the changelog here: https://github.com/microsoft/pylance-release/blob/main/CHANGELOG.md#202160-2-june-2021 |
Environment data
Expected behaviour
Actual behaviour
Logs
N/A (should be reproducible from code snippet)
Code Snippet / Additional information
Python result:
Pylance error:
![image](https://user-images.githubusercontent.com/71696787/119673437-40850100-be33-11eb-8158-2456fb321b55.png)
Note: the exact same issues seem to be present in mypy:
python/mypy#10534
The text was updated successfully, but these errors were encountered: