Hi Prefect! Quick question: PyCharm keeps telling ...
# prefect-community
d
Hi Prefect! Quick question: PyCharm keeps telling me that the documentation-approved way of using the
@task
decorator is lacking a positional argument. For example:
Copy code
@task
def add_one(x: int) -> int:
    return x + 1


@task()
def add_two(x: int) -> int:
    return x + 2
The
@task
decorator over
add_one
is how I’ve seen it in the docs, but it seems like the decorator for
add_two
is how PyCharm likes it. Am I missing something?
👍 1
j
Both work fine and function identically, some type checkers don't do well with decorators that can work both with and without
()
. Use whichever one you want.
d
Ah, gotcha. For what it’s worth, PyCharm does seem to handle other cases of this correctly. These both work with no warnings, for example:
Copy code
from dataclasses import dataclass

@dataclass
class PointA:
    x: float
    y: float

@dataclass()
class PointB:
    x: float
    y: float
No worries though. Thanks @Jim Crist-Harif!
j
Perhaps there's something we could do to annotate things so that would work, or maybe pycharm special cases that (since it's a builtin). Not sure.
d
No promises, but I took a look at the source for the
@dataclass
decorator and tried adopting it for
@task
. This seems to work, and doesn’t look too different from the current
@task
.
Copy code
def task(
    fn: Callable = None, **task_init_kwargs: Any
) -> Union[
    "prefect.tasks.core.function.FunctionTask",
    Callable[[Callable], "prefect.tasks.core.function.FunctionTask"],
]:
    def wrap(fn):
        return prefect.tasks.core.function.FunctionTask(
            fn=fn,
            **task_init_kwargs,
        )

    # See if we're being called as @task or @task().
    if fn is None:
        # We're called with parens.
        return wrap

    # We're called as @task without parens.
    return wrap(fn)
And no more complaints from PyCharm on either
@task
or
@task()
! Happy to test it some more and/or open a PR, if it’s of interest.
Or maybe this works better, since we need a callable to `FunctionTask`:
Copy code
def task(
    fn: Callable = None, **task_init_kwargs: Any
) -> Union[
    "prefect.tasks.core.function.FunctionTask",
    Callable[[Callable], "prefect.tasks.core.function.FunctionTask"],
]:
    def wrap(fn):
        if fn is None:
            return lambda void_fn: prefect.tasks.core.function.FunctionTask(
                fn=void_fn,
                **task_init_kwargs,
            )
        return prefect.tasks.core.function.FunctionTask(
            fn=fn,
            **task_init_kwargs,
        )

    # See if we're being called as @task or @task().
    if fn is None:
        # We're called with parens.
        return wrap

    # We're called as @task without parens.
    return wrap(fn)
j
Sure, if you want to open a PR that'd be great. Thanks!