This PR improves type checking of calls to functions registered via @dispatch.function. The previous PR improved type checking of call arguments (https://github.com/stealthrocket/dispatch-py/pull/100), while this PR focuses on call results.
The wrapped functions now return a Coroutine[Any, Any, T] when called, allowing mypy to check that the resulting coroutines are awaited properly, and that the return values (of type T) are used correctly. Here's an example of both new errors:
@dispatch.function
async def foo(a: int, b: str = "foo") -> list[str]:
return [b] * a
@dispatch.function
async def bar() -> str:
results = await foo(1, "x")
return results[0] + 3 # error: Unsupported operand types for + ("str" and "int")
foo(1, "abc") # error: Value of type "Coroutine[Any, Any, list[str]]" must be used
I had to make a breaking change to get this working. At the moment Dispatch allows users to register both synchronous and asynchronous functions, but the way in which you interact with the decorated functions is not consistent. Async functions (coroutines) are called through Dispatch. Synchronous functions are called directly. The return value of the @dispatch.function__call__ is either a Coroutine[Any, Any, T] or just a T depending on the function color. In this PR, I've updated it so that all @dispatch.function calls go through Dispatch asynchronously. Therefore, all @dispatch.function calls return a Coroutine[Any, Any, T] which must be awaited.
This PR improves type checking of calls to functions registered via
@dispatch.function
. The previous PR improved type checking of call arguments (https://github.com/stealthrocket/dispatch-py/pull/100), while this PR focuses on call results.The wrapped functions now return a
Coroutine[Any, Any, T]
when called, allowing mypy to check that the resulting coroutines are awaited properly, and that the return values (of typeT
) are used correctly. Here's an example of both new errors:I had to make a breaking change to get this working. At the moment Dispatch allows users to register both synchronous and asynchronous functions, but the way in which you interact with the decorated functions is not consistent. Async functions (coroutines) are called through Dispatch. Synchronous functions are called directly. The return value of the
@dispatch.function
__call__
is either aCoroutine[Any, Any, T]
or just aT
depending on the function color. In this PR, I've updated it so that all@dispatch.function
calls go through Dispatch asynchronously. Therefore, all@dispatch.function
calls return aCoroutine[Any, Any, T]
which must be awaited.This fixes #99.