Understanding the code#
This is a simple “Hello, world!” example consisting of flat directory:
.
├── LICENSE
├── README.md
├── hello_world.py
├── pyproject.toml
└── uv.lock
Python code#
The hello_world.py
file illustrates the essential components of a Union workflow:
"""Hello World"""
import union
image_spec = union.ImageSpec(
# Build the image using Union's built-in cloud builder (not locally on your machine)
builder="union",
# The name of the image. This image will be used byt he say_hello task
name="say-hello-image",
# Lock file with dependencies to install in image
requirements="uv.lock",
)
@union.task(container_image=image_spec)
def say_hello(name: str) -> str:
return f"Hello, {name}!"
@union.workflow
def hello_world_wf(name: str = "world") -> str:
greeting = say_hello(name=name)
return greeting
ImageSpec#
The ImageSpec
object is used to define the container image that will run the tasks in the workflow.
Here we have the simplest possible ImageSpec
object, which specifies:
The
builder
to use to build the image. We specifyunion
to indicate that the image is built using Union’s cloud image builder.The
name
of the image. This name will be used to identify the image in the container registry.The
requirements
parameter. We specify that the requirements should be read from theuv.lock
file.
See ImageSpec for more information.
Tasks#
The @union.task
decorator indicates a Python function that defines a task.
A task tasks some input and produces an output.
When deployed to Union cluster, each task runs in its own Kubernetes pod.
For a full list of task parameters, see Task parameters.
Workflow#
The @union.workflow
decorator indicates a function that defines a workflow.
This function contains references to the tasks defined elsewhere in the code.
A workflow appears to be a Python function but is actually a DSL that only supports a subset of Python syntax and semantics.
When deployed to Union, the workflow function is “compiled” to construct the directed acyclic graph (DAG) of tasks, defining the order of execution of task pods and the data flow dependencies between them.
@union.task
and @union.workflow
syntax
The
@union.task
and@union.workflow
decorators will only work on functions at the top-level scope of the module.You can invoke tasks and workflows as regular Python functions and even import and use them in other Python modules or scripts.
Task and workflow function signatures must be type-annotated with Python type hints.
Task and workflow functions must be invoked with keyword arguments.
pyproject.toml#
The pyproject.toml is the standard project configuration used by uv
.
In particular, it specifies the project dependencies and the Python version to use.
The default pyproject.toml
file created by union init
from the union-simple
template looks like this
[project]
name = "union-simple"
version = "0.1.0"
description = "A simple Union project"
readme = "README.md"
requires-python = ">=3.9,<3.13"
dependencies = ["union"]
(You can update to match the actual name of your project, my-project
, if you like).
The most important part of the file is the list of dependencies, in this case consisting of only one package, union
.
See uv > Configuration > Configuration files for details.
uv.lock#
The uv.lock
file is generated from pyproject.toml
by uv sync
command.
It contains the exact versions of the dependencies required by the project.
See uv > Concepts > Projects > Locking and syncing for details.