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

Update loop task factory typing with kwargs #585

Conversation

ordinary-jamie
Copy link

@ordinary-jamie ordinary-jamie commented Dec 4, 2023

Issue: #584

For PY311 the task factory will be called with the context kwarg. This is not correctly reflected in the typing for Loop.set_task_factory and Loop.get_task_factory.

This commit addresses this with a protocol. Since uvloop requires a minimum Python 3.8 version, in which typing.Protocol is available. Note, neither typing.Unpack for kwargs, (introduced in Python 3.11) or typing.ParmSpec with ParamSpec.kwargs (introduced in Python 3.10) is available for 3.8

Did not explicitly type the context parameter and used **kwargs since the Loop method allows for the legacy API without a context param for <PY311

Also see discussion about name parameter for task factory in asyncio: python/cpython#112623 (comment)

Quick demonstration of typing (see mypy Callback Protocols)

# test.py
import asyncio
from typing import Any, Generator, Protocol, TypeVar

_T = TypeVar("_T")


class TaskFactoryCallable(Protocol):
    def __call__(
        self, loop: asyncio.AbstractEventLoop, coro: Generator[Any, None, _T], **kwargs
    ) -> asyncio.Future[_T]:
        ...


def set_task_factory(factory: TaskFactoryCallable) -> None:
    ...


def task_factory_valid(
    loop: asyncio.AbstractEventLoop, coro: Generator[Any, None, _T], **kwargs
) -> asyncio.Future[_T]:
    return asyncio.Future()


def task_factory_invalid(
    loop: asyncio.AbstractEventLoop, coro: Generator[Any, None, _T]
) -> asyncio.Future[_T]:
    return asyncio.Future()


# Passes mypy
set_task_factory(task_factory_valid)

# Fails mypy
set_task_factory(task_factory_invalid)
mypy test.py 
# test.py:35: error: Argument 1 to "set_task_factory" has incompatible type "Callable[[AbstractEventLoop, Generator[Any, None, _T]], Future[_T]]"; expected "TaskFactoryCallable"  [arg-type]
# Found 1 error in 1 file (checked 1 source file)

@ordinary-jamie ordinary-jamie force-pushed the asyncio-task-factory-typing branch 2 times, most recently from 0aa7b51 to f568881 Compare December 4, 2023 02:28
For `PY311` the task factory will be called with the context kwarg. This
is not correctly reflected in the typing for `Loop.set_task_factory` and
`Loop.get_task_factory`. This commit addresses this with a protocol.
Since `uvloop` requires a minimum Python 3.8 version, in which
`typing.Protocol` is available; the more appropriate `typing.Unpack` for
kwargs is introduced in Python 3.11.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant