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

Stricter typing for TaskGroup.start() #678

Open
jonathanslenders opened this issue Jan 25, 2024 · 1 comment
Open

Stricter typing for TaskGroup.start() #678

jonathanslenders opened this issue Jan 25, 2024 · 1 comment
Labels
enhancement New feature or request

Comments

@jonathanslenders
Copy link
Contributor

jonathanslenders commented Jan 25, 2024

Looking at how we type TaskGroup.start_soon, we can do the same approach to have stricter type checking on TaskGroup.start.

We can do the following:

from typing_extensions import Protocol
from typing_extensions import TypeVarTuple, Unpack, TypeVar, Generic


T = TypeVar("T")


class TaskStatus(Generic[T]):
    def ready(self, result: T) -> None:
        ...


# ---

PosArgsT = TypeVarTuple("PosArgsT")
TaskStatusResult = TypeVar("TaskStatusResult")


class _StartFunc(Protocol[Unpack[PosArgsT], TaskStatusResult]):
    async def __call__(
        self, *args: Unpack[PosArgsT], task_status: TaskStatus[TaskStatusResult]
    ) -> None:
        ...


class TaskGroup:
    async def start(
        self,
        func: _StartFunc[Unpack[PosArgsT], TaskStatusResult],
        *args: Unpack[PosArgsT],
    ) -> TaskStatusResult:
        ...

Example usage::

async def task(a: int, b: str, task_status: TaskStatus[bool]) -> None:
    task_status.ready(True)

async def main() -> None:
    tg = TaskGroup()
    r: float = await tg.start(task, 6, "t")

On the last line, typing the result as float is still important, otherwise it will be Any. Mypy's type inference is lacking here. But if we would type it as str, then mypy would say:

error: Argument 1 to "start" of "TaskGroup" has incompatible type "Callable[[int, str, TaskStatus[bool]], Coroutine[Any, Any, None]]"; expected "_StartFunc[int, str, str]"  [arg-type]

That is significantly better than object what we currently have here:
https://github.com/agronholm/anyio/blob/master/src/anyio/abc/_tasks.py#L70

What do you think?

@jonathanslenders
Copy link
Contributor Author

I just see previous attempts have been made to supply types for start().

See: #511
And most recent mypy issue: python/mypy#16522

When trying to finalize a PR, I was hitting exactly those issues, so I guess we have to wait for mypy...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant