Skip to content
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

Async functions without yields which return async iterables have wrong signature #1140

Closed
audoh-tickitto opened this issue Apr 9, 2021 · 3 comments
Labels
bug Something isn't working fixed in next version (main) A fix has been implemented and will appear in an upcoming version

Comments

@audoh-tickitto
Copy link

audoh-tickitto commented Apr 9, 2021

Environment data

  • Language Server version: 2021.4.0 (pyright 2918da1d)
  • OS and version: Ubuntu 20.04.2 LTS
  • Python version (& distribution if applicable, e.g. Anaconda): Python 3.9.2 acquired via pyenv 1.2.23

Expected behaviour

Non-generator (no yield) async functions which return async iterables, generators etc should have a return type of Coroutine[Any, Any, AsyncIterable] (replace AsyncIterable with AsyncGenerator or other relevant type)

Actual behaviour

Non-generator (no yield) async functions which return async iterables, generators etc have a return type of AsyncIterable (replace AsyncIterable with AsyncGenerator or other relevant type)

Logs

Code Snippet / Additional information

import asyncio
from typing import AsyncGenerator, AsyncIterable, List


async def get_data() -> List[int]:
    await asyncio.sleep(1)
    return [1, 2, 3]


async def generate(nums: List[int]) -> AsyncGenerator[str, None]:
    for n in nums:
        await asyncio.sleep(1)
        yield f"The number is {n}"


async def get_generator() -> AsyncGenerator[str, None]:
    data = await get_data()
    return generate(data)


async def demo_bug() -> None:
    gen = await get_generator()  # Pylance: "AsyncGenerator[str, None]" is not awaitable
    async for s in gen:
        print(s)


loop = asyncio.get_event_loop()
loop.run_until_complete(demo_bug())

When run in Python, the expected output is produced:

The number is 1
The number is 2
The number is 3
@github-actions github-actions bot added the triage label Apr 9, 2021
@audoh-tickitto audoh-tickitto changed the title Non-generator async functions which return async iterators Non-generator async functions which return async iterables Apr 9, 2021
@audoh-tickitto audoh-tickitto changed the title Non-generator async functions which return async iterables Async functions without yields which return async iterables have wrong signature Apr 9, 2021
@erictraut
Copy link
Contributor

Thanks for the bug report. Pylance wasn't correctly handling the case where an async method had a declared return type of AsyncGenerator but was not itself a generator (i.e. had no yield statement). In that case, the effective return type of the method needs to be wrapped in a Coroutine type.

@erictraut
Copy link
Contributor

This will be fixed in the next release of Pylance.

@erictraut erictraut added bug Something isn't working fixed in next version (main) A fix has been implemented and will appear in an upcoming version and removed triage labels Apr 10, 2021
@jakebailey
Copy link
Member

This issue has been fixed in version 2021.4.1, which we've just released. You can find the changelog here: https://github.com/microsoft/pylance-release/blob/main/CHANGELOG.md#202141-14-april-2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fixed in next version (main) A fix has been implemented and will appear in an upcoming version
Projects
None yet
Development

No branches or pull requests

3 participants