microsoft / pyright

Static Type Checker for Python
Other
13.1k stars 1.4k forks source link

How to proper type hint list of Futures/Tasks? #2246

Closed B4rtware closed 3 years ago

B4rtware commented 3 years ago

This is not a bug report, but a question on how to write a correctly typed piece of code.

Description: I would like to type hint my list of tasks. Unfortunately, I am not able to define the type so that pyright does not throw an error. The given code example throws: Type of "tasks" is partially unknown. (I also know that all of my courotines inside that List will return None.)

import asyncio
from typing import List

tasks: List[asyncio.Task] = []

async def foo() -> None:
    print("Hello World!")

async def main():
    tasks.append(asyncio.create_task(foo()))

asyncio.run(main())

I have tried to use asyncio.Task[None] which is also proposed via pyright by using

a = asyncio.create_task(foo())

and hovering over the variable a -> Task[None]. So this code snippet:

import asyncio
from typing import List

tasks: List[asyncio.Task[None]] = []

async def foo() -> None:
    print("Hello World!")

async def main():
    tasks.append(asyncio.create_task(foo()))

asyncio.run(main())

does not throw an error by pyright but I get a runtime error:

Traceback (most recent call last):
  File "...\main.py", line 4, in <module>
    tasks: List[asyncio.Task[None]] = []
TypeError: 'type' object is not subscriptable

I have also tried to use the typing.Awaitable this gives no errors but hides the Task functions because it does not exposes the Future or Task interface.

And I guess the TypeError above occurs because of the same reason we can't use the built in type list for type hinting before 3.9 and without future.

I am using pyright 1.1.164 and strict mode.

Do you know how I can type hint it correctly?

hmc-cs-mdrissi commented 3 years ago

Wrap your type in a string.

tasks: List["asyncio.Task[None]"] = []

Other option add

from __future__ import annotations to the top of your file. That will treat all type annotations as strings.

erictraut commented 3 years ago

Pyright should warn you if you attempt to subscript a type that will generate a runtime exception. I didn't realize that asyncio.Task didn't support subscripting prior to Python 3.9. I've updated the code so it knows about this case.