KEMBAR78
Mypy misunderstands poorly documented class of async generators · Issue #12924 · python/mypy · GitHub
Skip to content

Mypy misunderstands poorly documented class of async generators #12924

@jhance

Description

@jhance

There is not much literature on expressions of the form (await f(x) for x in xs), but I did find https://bugs.python.org/issue32113 in which we see discussion that they are indeed valid. I didn't find any mention of them in any of the async comprehension or generator PEPs, although would love to see it if someone can find it.

Consider the following definition:

async def foo() -> Iterable[int]:               
    async def bar(i: int) -> int:
        return i  
    
    xs = [1, 2, 3]
    
    return (await bar(x) for x in xs)

Mypy provides no error here.

Meanwhile, according to the linked bug (and also according to running the program), this is equivalent to:

async def foo_errors() -> Iterable[int]:
    async def bar(i: int) -> int:
        return i

    xs = [1, 2, 3]
    
    for x in xs:
        v = await bar(x)
        yield v

In which case mypy correctly has error "The return type of an async generator function should be "AsyncGenerator" or one of its supertypes". This is rather bad as this is an easy mistake to make, and results in code like for x in await foo() being considered valid by mypy.

The error likely comes from the fact that reveal_type((await bar(x) for x in xs)) reveals typing.Generator[int, None, None] instead of typing.AsyncGenerator.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-asyncasync, await, asyncio

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions