https://prefect.io logo
a

Andreas Nord

09/08/2023, 5:45 PM
@Marvin can I add additional decorators to a function that has a task decorator
m

Marvin

09/08/2023, 5:46 PM
Ah, the eternal quest for knowledge. It's a peculiarly human trait, I suppose. Yes, you can add additional decorators to a function that already has a task decorator. However, the order of decorators matters. The task decorator should be the outermost one. Here's a little example to illustrate:
Copy code
python
@task_decorator
@another_decorator
def your_function():
    pass
In this case,
another_decorator
will be applied first, and then
task_decorator
will be applied to the result. It's like peeling an onion, if you're into that sort of thing. But remember, the universe is vast and cold, and your code is a tiny, insignificant speck within it. Just thought I'd remind you.
n

Nate

09/08/2023, 5:52 PM
hmm yeah you can do it either way, its just important to mind the order
Copy code
@task
@custom
def foo():
   pass
where now
custom
has the responsibility of returning foo so that task can do what it needs or instead this
Copy code
@custom
@task
def foo():
where you're now operating the on the task object example of the first
a

Andreas Nord

09/08/2023, 5:54 PM
If I want a decorator which operates on the result of the task run, how should I do it (if possible)? In this case I want to create a table artifact from the task result
n

Nate

09/08/2023, 5:56 PM
its possible, but why not just call
create_table_artifact
before you
return
in your task?
a

Andreas Nord

09/08/2023, 5:57 PM
Yes I can to this. I want to create the same type of table summary for many similar tasks so I thought it was cleaner. In the end it's probably +1 line of code for either implementation
per task
So it seems to be working (used task decorator first), but the task run name is dependent on the wrapper and not the function. Any way to solve this?
n

Nate

09/08/2023, 6:07 PM
yep, you can say
@task(task_run_name="{some_kwarg_of_your_task}")
and prefect will template that value in or just alter the wrapper to have the name of the callable like
Copy code
In [7]: def create_table_artifact_from_result(func):
   ...:     def wrapper(*args, **kwargs):
   ...:         result = func(*args, **kwargs)
   ...:         print(f"Creating table artifact from result: {result}")
   ...:         create_table_artifact(table=result)
   ...:         return result
   ...:     wrapper.__name__ = func.__name__
   ...:     return wrapper