dispatchrun / dispatch-py

Python package to develop applications with Dispatch.
https://pypi.org/project/dispatch-py/
Apache License 2.0
54 stars 3 forks source link

Improve type checking of call results #101

Closed chriso closed 6 months ago

chriso commented 6 months ago

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 fixes #99.

achille-roussel commented 6 months ago

This will also fix #85 since we will be able to await on non-async functions.