API Reference
This page is automatically generated from the source code docstrings.
Process
Process(tasks: list[Task], name: str = '')
Manages and executes a collection of interdependent tasks.
A Process orchestrates the execution of multiple tasks, handling dependency resolution, task ordering. Task execution can be performed in parallel or sequentially. It provides logging management and error propagation for dependent tasks. If a task fails, all tasks depending on it are marked as failed without execution, but non-dependent tasks continue to run.
Attributes:
| Name | Type | Description |
|---|---|---|
tasks |
list[Task]
|
List of tasks to be executed, automatically sorted by dependencies. |
name |
str
|
Human-readable name for the process ( |
runner |
ProcessRunner
|
The runner responsible for executing the tasks. |
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tasks
|
list[Task]
|
The tasks to orchestrate. Order does not matter — the constructor topologically sorts the list in place. The list is mutated during construction; pass a copy if the original ordering matters. |
required |
name
|
str
|
Human-readable name for the process. Recorded on the resulting
|
''
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If tasks is not a list or contains non-Task elements. |
ValueError
|
If duplicate task names are found. |
DependencyNotFoundError
|
If a task depends on a non-existent task. |
CircularDependencyError
|
If circular dependencies are detected among tasks. |
Source code in src/processes/process.py
57 58 59 60 61 62 63 64 65 66 | |
__enter__
__enter__() -> Self
Called when entering the 'with' block.
Source code in src/processes/process.py
81 82 83 | |
__exit__
__exit__(
exc_type: type[BaseException] | None,
exc_value: BaseException | None,
traceback: TracebackType | None,
) -> Literal[False]
Called when exiting the 'with' block, even if an error occurred.
Source code in src/processes/process.py
85 86 87 88 89 90 91 92 93 | |
get_task
get_task(task_name: str) -> Task
Retrieve a task by name in O(1).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_name
|
str
|
The name of the task to retrieve. |
required |
Returns:
| Type | Description |
|---|---|
Task
|
The task with the specified name. |
Raises:
| Type | Description |
|---|---|
TaskNotFoundError
|
If no task with the given name exists. |
Source code in src/processes/process.py
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | |
add_task
add_task(task: Task) -> None
Add a task to the process and re-resolve the graph.
The graph is re-validated and re-sorted, and any pending run state is reset (a fresh runner is built). If the new task makes the graph invalid, the process is left unchanged and the original error is raised.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task
|
Task
|
The task to add. |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If a task with the same name already exists. |
DependencyNotFoundError
|
If |
CircularDependencyError
|
If adding |
Source code in src/processes/process.py
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | |
remove_task
remove_task(task_name: str) -> None
Remove a task from the process and re-resolve the graph.
Rejected if any other task still depends on task_name — remove the
dependents first. On success the removed task's logger handlers are
closed (the process no longer owns them) and a fresh runner is built.
Note: if the same Task instance is shared with another Process,
closing its handlers here affects that process too.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_name
|
str
|
Name of the task to remove. |
required |
Raises:
| Type | Description |
|---|---|
TaskNotFoundError
|
If no task with that name exists. |
ValueError
|
If other tasks depend on it. |
Source code in src/processes/process.py
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | |
add_task_dependency
add_task_dependency(
task_name: str, dependency: TaskDependency
) -> None
Add a dependency to an existing task and re-resolve the graph.
Note: this mutates the Task instance's dependencies list; if the
task is shared with another Process, that process sees the change too.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_name
|
str
|
Name of the (dependent) task that gains the dependency. |
required |
dependency
|
TaskDependency
|
The dependency to add. Its |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
TaskNotFoundError
|
If |
ValueError
|
If |
DependencyNotFoundError
|
If |
CircularDependencyError
|
If the dependency introduces a cycle (including a self-dependency). |
Source code in src/processes/process.py
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | |
run
run(
parallel: bool | None = None, max_workers: int = 4
) -> ProcessExecutionReport
Execute all tasks in the process.
Runs tasks sequentially or in parallel while respecting dependencies. Dependencies are always resolved before dependent tasks are executed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parallel
|
bool
|
Whether to run tasks in parallel while respecting dependencies. If None, automatically set to True for processes with 10 or more tasks, False otherwise. Defaults to None. |
None
|
max_workers
|
int
|
Maximum number of worker threads for parallel execution. Defaults to 4. Only used when parallel=True. If set to 1, falls back to sequential execution. Values below 1 are clamped to 1. |
4
|
Returns:
| Type | Description |
|---|---|
ProcessExecutionReport
|
Per-task breakdown of the run, in topological order. |
Source code in src/processes/process.py
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | |
get_dependant_tasks
get_dependant_tasks(task_name: str) -> list[Task]
Retrieve all tasks that directly or indirectly depend on a given task.
Uses a pre-built adjacency map for O(V+E) traversal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_name
|
str
|
The name of the task to find dependants for. |
required |
Returns:
| Type | Description |
|---|---|
list[Task]
|
List of all tasks that depend on the specified task, including transitive dependants. |
Source code in src/processes/process.py
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | |
close_loggers
close_loggers() -> None
Close and clean up all logger handlers for all tasks.
Should be called when the process is done to ensure proper resource cleanup.
Source code in src/processes/process.py
377 378 379 380 381 382 383 | |
Task
Task(
name: str,
func: Callable[..., Any],
log_path: str | None = None,
args: tuple[Any, ...] = (),
kwargs: dict[str, Any] | None = None,
dependencies: list[TaskDependency] | None = None,
traced_vars_frame_filter: str | None = None,
timeout: float | None = None,
retries: int | None = 0,
retry_on: tuple[type[Exception], ...] | None = None,
)
A Task represents a unit of work to be executed within a Process.
A Task encapsulates a callable function with its arguments, dependencies on other tasks, and logging configuration. Tasks can be executed by the Process class, sequentially or in parallel, with automatic dependency resolution and result passing between dependent tasks.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Unique name for the task (cannot contain spaces). |
log_path |
str | None
|
File path where task logs will be written. |
func |
Callable
|
The function to execute when the task runs. |
args |
tuple
|
Positional arguments to pass to the function. Defaults to empty tuple. |
kwargs |
dict
|
Keyword arguments to pass to the function. Defaults to empty dict. |
dependencies |
list[TaskDependency]
|
List of tasks this task depends on. Defaults to empty list. |
traced_vars_frame_filter |
str | None
|
Substring selecting which traceback frame's local variables are
captured into the failure context on error. |
timeout |
float | None
|
Seconds allowed per attempt before a |
retries |
int
|
Additional attempts after the first failure. |
retry_on |
tuple[type[Exception], ...] | None
|
Exception types that trigger a retry. When |
logger |
Logger
|
Logger instance for this task, automatically configured. |
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Unique task name; must not contain spaces. Normalized to lowercase, so task names (and the dependency references that point at them) are matched case-insensitively. |
required |
func
|
Callable[..., Any]
|
The callable executed when the task runs. |
required |
log_path
|
str | None
|
File path the task's log records are written to (one |
None
|
args
|
tuple[Any, ...]
|
Positional arguments forwarded to |
()
|
kwargs
|
dict[str, Any] | None
|
Keyword arguments forwarded to |
None
|
dependencies
|
list[TaskDependency] | None
|
Tasks this task depends on. |
None
|
traced_vars_frame_filter
|
str | None
|
Substring used to select the traceback frame whose local variables are
captured into the failure context (and thus into both the logfile and
any report notification). When |
None
|
timeout
|
float | None
|
Seconds allowed per attempt before |
None
|
retries
|
int | None
|
Number of additional attempts after the first failure. |
0
|
retry_on
|
tuple[type[Exception], ...] | None
|
Exception types that trigger a retry. Evaluated only when
|
None
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If any parameter is not of the expected type, |
ValueError
|
If |
Source code in src/processes/task.py
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | |
get_dependencies_names
get_dependencies_names() -> set[str]
Get the names of all tasks this task depends on.
Returns:
| Type | Description |
|---|---|
set[str]
|
Set of dependency task names. |
Source code in src/processes/task.py
225 226 227 228 229 230 231 232 233 234 | |
close_handlers
close_handlers() -> None
Close and detach every handler on this task's logger.
The task owns the lifecycle of the logger it builds in __init__;
this is the single teardown path used by Process.close_loggers and
Process.remove_task. Safe to call more than once.
Source code in src/processes/task.py
236 237 238 239 240 241 242 243 244 245 | |
run
run(executing_process: Process | None = None) -> TaskResult
Execute the task, retrying on transient failures up to retries times.
Never propagates: a failure while resolving dependency arguments (before
any attempt runs) is captured and returned as an ERRORED result with
attempts=0, just like a failure inside the task's function.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
executing_process
|
Process
|
Parent process; used to inject dependency results and to build the downstream impact list on failure. |
None
|
Returns:
| Type | Description |
|---|---|
TaskResult
|
|
Source code in src/processes/task.py
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 | |
TaskDependency
TaskDependency(
task_name: str,
use_result_as_additional_args: bool = False,
use_result_as_additional_kwargs: bool = False,
additional_kwarg_name: str = "",
)
Represents a dependency relationship between tasks.
Defines how a task depends on another task, including how the result of the dependency should be passed to the dependent task (as additional positional arguments, keyword arguments, or both).
Attributes:
| Name | Type | Description |
|---|---|---|
task_name |
str
|
The name of the task this dependency refers to. Normalized to lowercase
to match :class: |
use_result_as_additional_args |
bool
|
If True, the result of the dependency task will be passed as an additional positional argument as the last argument. Defaults to False. |
use_result_as_additional_kwargs |
bool
|
If True, the result of the dependency task will be passed as a keyword argument. Defaults to False. |
additional_kwarg_name |
str
|
The name of the keyword argument to use if |
Raises:
| Type | Description |
|---|---|
TypeError
|
If any parameter type is invalid or if use_result_as_additional_kwargs is True but additional_kwarg_name is not a string. |
Source code in src/processes/task_types.py
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | |
__hash__
__hash__() -> int
Return hash of the dependency based on task name.
Returns:
| Type | Description |
|---|---|
int
|
Hash value based on the task_name attribute. |
Source code in src/processes/task_types.py
193 194 195 196 197 198 199 200 201 202 | |
TaskResult
TaskResult(
status: TaskStatus,
result: Any,
exception: Exception | None,
error_data: ErrorData | None = None,
elapsed_seconds: float = 0.0,
attempts: int = 0,
)
Container for the result of a task execution.
Holds the outcome of running a task, including its status, return value, and any exception that occurred.
Attributes:
| Name | Type | Description |
|---|---|---|
status |
TaskStatus
|
Outcome of the task: |
worked |
bool
|
True if |
result |
Any
|
The return value of the task's function if execution succeeded, None if failed. |
exception |
Exception | None
|
The exception object if execution failed, None if successful. |
error_data |
ErrorData | None
|
Structured failure context (function, args, kwargs, traceback, traced variables, downstream impact) when execution failed; None if the task succeeded. |
elapsed_seconds |
float
|
Wall-clock time spent running the task across all attempts, in
seconds. Defaults to |
attempts |
int
|
Number of attempts actually executed (1 or more if the task ran,
0 if it never ran). Defaults to |
Source code in src/processes/task_types.py
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | |
worked
property
worked: bool
True if the task executed successfully, False otherwise.
pending
classmethod
pending() -> TaskResult
Build the placeholder result for a task that has not run yet.
Source code in src/processes/task_types.py
90 91 92 93 | |
skipped
classmethod
skipped() -> TaskResult
Build the result for a task skipped after an upstream dependency failed.
Source code in src/processes/task_types.py
95 96 97 98 | |
success
classmethod
success(
result: Any,
*,
elapsed_seconds: float = 0.0,
attempts: int = 0,
) -> TaskResult
Build the result for a task whose function returned without raising.
Source code in src/processes/task_types.py
100 101 102 103 104 105 106 107 108 109 | |
errored
classmethod
errored(
exception: Exception,
*,
error_data: ErrorData | None = None,
elapsed_seconds: float = 0.0,
attempts: int = 0,
) -> TaskResult
Build the result for a task whose function raised after exhausting retries.
Source code in src/processes/task_types.py
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | |
ProcessExecutionReport
dataclass
ProcessExecutionReport(
entries: dict[str, TaskReportEntry] = dict(),
process_name: str = "",
)
Per-task breakdown of a finished :meth:Process.run call.
Attributes:
| Name | Type | Description |
|---|---|---|
entries |
dict[str, TaskReportEntry]
|
Mapping of task name to its report entry, ordered the same way as
|
process_name |
str
|
Name of the process the report came from ( |
successes
property
successes: dict[str, TaskReportEntry]
Entries for tasks whose status is SUCCESS.
errored
property
errored: dict[str, TaskReportEntry]
Entries for tasks whose status is ERRORED.
skipped
property
skipped: dict[str, TaskReportEntry]
Entries for tasks whose status is SKIPPED.
from_results
classmethod
from_results(
process: Process, results: dict[str, TaskResult]
) -> ProcessExecutionReport
Build a report from a finished process run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
process
|
Process
|
The process that was run. Used for task definitions (name, function, args, kwargs) and topological ordering. |
required |
results
|
dict[str, TaskResult]
|
One |
required |
Returns:
| Type | Description |
|---|---|
ProcessExecutionReport
|
One entry per task in |
Source code in src/processes/execution_report.py
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | |
to_json
to_json(
*, indent: int | None = None, **dumps_kwargs: Any
) -> str
Serialize the whole report to a JSON string without dropping any field.
Every entry and every field is included. Values that are not natively
JSON-serializable are rendered faithfully rather than omitted:
TaskStatus as its string value, the nested ErrorData as an
object, and any arbitrary object appearing in args, kwargs or
result via repr(). The content is therefore lossless, though
repr-rendered objects are not round-trippable into live objects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
indent
|
int
|
Forwarded to |
None
|
**dumps_kwargs
|
Any
|
Forwarded to |
{}
|
Returns:
| Type | Description |
|---|---|
str
|
A JSON object |
Source code in src/processes/execution_report.py
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | |
notify
notify(
*channels: ReportChannel,
only_errors: bool = False,
tasks: list[str] | None = None,
show_warnings: bool = True,
) -> None
Deliver the report through each channel, in order.
Each channel renders and sends the report itself (email, webhook, ...).
What detail is included is configured per channel (see ReportContent).
If a channel raises, the exception is caught so the remaining channels
still receive the report; a UserWarning is emitted when
show_warnings is True.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*channels
|
ReportChannel
|
Channels to deliver the report to. No-op if none are given. |
()
|
only_errors
|
bool
|
When |
False
|
tasks
|
list[str]
|
Restrict the report to these task names, compared case-insensitively.
|
None
|
show_warnings
|
bool
|
Emit a |
True
|
Source code in src/processes/execution_report.py
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | |
TaskReportEntry
dataclass
TaskReportEntry(
name: str,
function: str,
args: tuple[Any, ...],
kwargs: dict[str, Any],
status: TaskStatus,
elapsed_seconds: float,
attempts: int,
result: Any | None = None,
error: ErrorData | None = None,
)
Per-task entry in a :class:ProcessExecutionReport.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
The task's name. |
function |
str
|
Name of the function the task runs. |
args |
tuple[Any, ...]
|
Positional arguments the task was constructed with. |
kwargs |
dict[str, Any]
|
Keyword arguments the task was constructed with. |
status |
TaskStatus
|
Outcome of the task: |
elapsed_seconds |
float
|
Wall-clock time spent running the task across all attempts. |
attempts |
int
|
Number of attempts actually executed. |
result |
Any | None
|
The task's return value if |
error |
ErrorData | None
|
Structured failure context if |
TaskStatus
Bases: Enum
Outcome of a task within a process execution.
Attributes:
| Name | Type | Description |
|---|---|---|
PENDING |
The task has not been executed yet. |
|
SUCCESS |
The task ran and its function returned without raising. |
|
ERRORED |
The task ran and its function raised an exception (after exhausting retries, if any). |
|
SKIPPED |
The task never ran because an upstream dependency failed. |
ErrorData
dataclass
ErrorData(
task_name: str = "?",
function: str = "?",
args: tuple[Any, ...] = (),
kwargs: dict[str, Any] = dict(),
downstream_impact: list[str] = list(),
exception: str = "",
traceback_str: str = "",
traced_vars: dict[str, str] = dict(),
traced_vars_location: str = "",
)
Typed view of a task failure, extracted from record.task_context.
Attributes:
| Name | Type | Description |
|---|---|---|
task_name |
str
|
Name of the task that failed. Defaults to |
function |
str
|
Name of the function that was executing. Defaults to |
args |
tuple[Any, ...]
|
Positional arguments the function was called with. Defaults to |
kwargs |
dict[str, Any]
|
Keyword arguments the function was called with. Defaults to |
downstream_impact |
list[str]
|
Names of tasks skipped as a result of this failure. Defaults to |
exception |
str
|
String representation of the raised exception. Defaults to |
traceback_str |
str
|
Full formatted traceback. Defaults to |
traced_vars |
dict[str, str]
|
Mapping of local variable names to |
traced_vars_location |
str
|
|
SMTPConfig
dataclass
SMTPConfig(mailhost: tuple[str, int], fromaddr: str, toaddrs: list[str], credentials: tuple[str, str] | None = None, secure: tuple[] | tuple[str] | tuple[str, str] | tuple[str, str, SSLContext] | None = None, timeout: int = 5)
SMTP transport configuration for HTML email error alerts.
Attributes:
| Name | Type | Description |
|---|---|---|
mailhost |
tuple[str, int]
|
|
fromaddr |
str
|
Sender email address. |
toaddrs |
list[str]
|
Recipient email addresses. |
credentials |
tuple[str, str] | None
|
|
secure |
tuple[] | tuple[str] | tuple[str, str] | tuple[str, str, SSLContext] | None
|
Security configuration. Use |
timeout |
int
|
Connection timeout in seconds. Defaults to |
HTMLEmailStyle
dataclass
HTMLEmailStyle(
palette: str = _DEFAULT_PALETTE,
language: str = _DEFAULT_LANGUAGE,
)
HTML presentation settings for the report email.
Both fields default to a neutral, English email — pass only what you want to override.
Attributes:
| Name | Type | Description |
|---|---|---|
palette |
str
|
Color scheme: |
language |
str
|
ISO 639-1 code for the email body text: |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |