Thread
#prefect-community
    Nash Taylor

    Nash Taylor

    4 months ago
    I feel like I'm going to gain a reputation as the guy who only ever asks about type safety but... I've got pyright integrated into my environment now, which is working far better with Prefect than Mypy did. It just requires one small hack, and it makes me wonder why this isn't part of the library: I had to add
    py.typed
    on my own. I see that there is a
    py.typed
    on the master branch; was there a conscious decision made not to include this marker file in 2.0? If so, why? Without the marker file, I get:
    from prefect.flows import flow
    
    reveal_type(flow)  # Unknown
    With the marker file, I get:
    from prefect.flows import flow
    
    reveal_type(flow)  # Overload[(__fn: (**P@flow) -> R@flow, /) -> Flow[P@flow, R@flow], (*, name: str = None, version: str = None, task_runner: BaseTaskRunner = ConcurrentTaskRunner, description: str = None, timeout_seconds: int | float = None, validate_parameters: bool = True) -> (((**P@flow) -> R@flow) -> Flow[P@flow, R@flow]), (__fn: Unknown | None = None, *, name: str = None, version: str = None, task_runner: BaseTaskRunner = ConcurrentTaskRunner, description: str = None, timeout_seconds: int | float = None, validate_parameters: bool = True) -> (Flow[P, R] | (((**P) -> R) -> Flow[P, R]))]
    which is much better. For example, now when I decorate a function with
    @task
    and use it in an
    @flow
    , the return type of the task is known to have a
    .result()
    method. When it was just an Unknown, pyright would complain that I'm accessing a method that doesn't exist. For someone who enforces fully passing mypy (now pyright) checks on every pull request, this is kind of a necessity.
    Michael Adkins

    Michael Adkins

    4 months ago
    Oh we’re not omitting that on purpose
    We need to add it to the MANIFEST I guess
    Nash Taylor

    Nash Taylor

    4 months ago
    So is it fine for now for me to just
    touch py.typed
    To get by while developing?
    Alvaro Durán Tovar

    Alvaro Durán Tovar

    4 months ago
    Nice, is this typing not recognized by mypy then?
    Nash Taylor

    Nash Taylor

    4 months ago
    In mypy, presumably due to their lack of full support for [PEP612](https://peps.python.org/pep-0612/), when it tries to type the result of
    Task.__call__
    (i.e. type your function you’ve decorated with
    @task
    ), it always chooses the [first overload](https://github.com/PrefectHQ/prefect/blob/orion/src/prefect/tasks.py#L231-L255),
    Task[P, NoReturn]
    , whose return type is
    PrefectFuture[None, Sync]
    . Basically, it assumes that every single user function decorated with
    @task
    has a return type of
    None
    , which causes
    .result()
    to always be None
    Pyright supports PEP612, so for example when you have
    @task
    def my_task(a: str, b: int) -> float:
         return len(a) + b + 0.5
    it picks up the third overload
    Task[P, T]
    and returns a
    PrefectFuture[T, Sync]
    , which here is a
    PrefectFuture[float, Sync]
    . And therefore
    my_task("a", 0).result()
    is a
    float
    … since when does Slack not support markdown-formatted links? huh.