Task
The simplest form of tasks are functions that just run Python code, and the easiest way to define them is by using the quickie.task() decorator.
from quickie import task
@task
def hello():
print("Hello, World!")
This will return a quickie.tasks.Task instance, equivalent to:
from quickie import Task
@task
class hello(Task):
def run(self):
print("Hello, World!")
The rest of the task classes, such as Script and Command are built on top of this class, and simply
replace the run method with a different implementation.
Function based vs Class based tasks
Defining tasks as functions is usually simpler and more concise, but defining them as classes allows for more customization and control.
Calling tasks from within run()
A task’s __call__() method runs the full lifecycle
(condition → before → run → after → cleanup) and returns whatever run()
returns. This means you can compose tasks freely from inside another task’s
run() method and work with their results directly:
from quickie import task, Task
@task
def fetch():
return ["item1", "item2"]
@task
def transform(items):
return [item.upper() for item in items]
class Pipeline(Task):
def run(self):
items = fetch() # calls full lifecycle, returns list
return transform(items) # passes result directly
Note
before, after, and cleanup return values are always discarded.
They are intended for declarative, fire-and-forget side effects. When you
need to pass a result from one task to another, call the dependency
directly from run() as shown above, rather than using before/after.
Return values
Every task type has a defined return contract:
Task— returns whateverrun()returns (any value).Group— returnslist[Any], one entry per sub-task, in definition order.ThreadGroup— returnslist[Any], one entry per sub-task, in definition order (not completion order).
When a task’s condition fails or Skip is raised inside
run(), __call__() returns None.