Skip to content

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.
@ordinary-jamie ordinary-jamie force-pushed the asyncio-task-factory-typing branch from f568881 to c859398 Compare December 4, 2023 05:49
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.

1 participant