MagicStack / uvloop

Ultra fast asyncio event loop.
Apache License 2.0
10.45k stars 548 forks source link

Incorrect typing for set_task_factory #584

Closed ordinary-jamie closed 11 months ago

ordinary-jamie commented 12 months ago

For PY311 the task factory will be called with context=context. This isn't typed in the .pyi file correctly

Running mypy with this script will raise an error

# uvloop-task-factory-typing.py
import asyncio

import uvloop

def task_factory(loop, coro, context) -> asyncio.Future:
    return asyncio.Future()

uvloop.Loop().set_task_factory(task_factory)

mypy --version
# mypy 1.7.0 (compiled: yes)

mypy uvloop-task-factory-typing.py 
# uvloop-task-factory-typing.py:11: error: Argument 1 to "set_task_factory" of "Loop" has incompatible type "Callable[[Any, Any, Any], Future[Any]]"; expected "Callable[[AbstractEventLoop, Generator[Any, None, Never]], Future[Never]] | None"  [arg-type]
# Found 1 error in 1 file (checked 1 source file)
ordinary-jamie commented 12 months ago

Sorry, my mistake -- mypy won't raise an error if context is a kwarg with a default value.

Notwithstanding, is it worth updating the typing to let users know that either a context kwarg or a unpacked **kwargs is required on the task factory?

Using just a 2-arg task factory as the type hints currently suggest will raise an error

import asyncio

import uvloop

async def foo():
    return "bar"

def main():
    loop = uvloop.new_event_loop()

    def task_factory(loop, coro):
        return asyncio.Task(coro, loop=loop)

    loop.set_task_factory(task_factory)
    loop.run_until_complete(foo())

main()
TypeError: main.<locals>.task_factory() got an unexpected keyword argument 'context'
sys:1: RuntimeWarning: coroutine 'foo' was never awaited