Lightweight Python workflow orchestration platform
Project description
Piply
Piply is a lightweight Python pipeline framework for teams that want YAML-defined workflows, schedules, retries, logs, sensors, and an operations UI without running a heavy orchestration stack.
It stays small on purpose:
- local dependency-aware DAG execution
- SQLite for runs, logs, task outputs, queue state, sensors, and pause overrides
- FastAPI plus server-rendered UI
- no Redis, Celery, Airflow, Prefect, or external queue required
Features
- Multi-task pipelines with
depends_on - Python script, Python callable, CLI, API, webhook, email, and SSH tasks
- Reusable YAML
variableswith{name}interpolation .env, environment variables, explicit secrets, and reusable SQL connections- Task output passing through
context["task_id"] - Pipeline-to-pipeline output and tenant context passing
- Metadata-driven
entitiesexpansion for reusable task templates - Optional
pipeline_templatesandpipeline_deploymentsfor advanced reuse - Per-task upstream failure behavior:
skip,fail, orcontinue - Heartbeat-backed runtime recovery for interrupted runs and stale scheduler state
- Schedules, sensors, retries, cancellation, reruns, and searchable logs
- Dashboard, Pipelines, Execution Matrix, Logs, Settings, and run detail pages
Quick Start
pip install -e .
copy .env.example .env
piply validate --config piply-demo/piply.yaml
piply start --config piply-demo/piply.yaml
Open http://127.0.0.1:8000.
Run on a different port when 8000 is already in use:
piply start --config piply-demo/piply.yaml --port 8080
piply start --config piply-demo/piply.yaml --host 0.0.0.0 --port 8080
Create a starter workspace:
piply init my-piply-project
piply run extract_flow --config my-piply-project/piply.yaml --wait
Minimal YAML
version: "1"
title: Piply Workspace
workspace: .
variables:
scripts_dir: pipelines
batch_id: demo-batch
connections:
app_db: sqlite:///sensor_demo.db
pipelines:
extract_flow:
schedule:
every: 15m
retry:
attempts: 2
mode: resume
delay_seconds: 10
triggers_on_success:
- report_flow
tasks:
extract:
type: python
path: "{scripts_dir}/extract.py"
function: extract_data
transform:
type: python
path: "{scripts_dir}/extract.py"
function: transform_data
depends_on: [extract]
validate:
type: cli
command: python {scripts_dir}/validate_cli.py {batch_id}
cwd: .
depends_on: [transform]
report_flow:
tasks:
build_report:
type: python
path: "{scripts_dir}/report.py"
function: build_report
Python callable tasks can consume upstream outputs:
def transform_data(context):
extracted = context["extract"]
return {"records": extracted["records"] + 1}
For plain commands, omit shell so Piply uses the platform default shell. Set
shell: bash only for Bash-specific syntax and only on machines where Bash is
installed and available on PATH:
tasks:
load_env_and_run:
type: cli
shell: bash
command: set -a && source .env && set +a && conda run -n py312_extract python {scripts_dir}/job.py
cwd: .
Dynamic Entity Mapping
Use entities when one task template should run once per business value. Piply expands templates at runtime into normal DAG tasks, so existing retries, logs, outputs, and parallel execution continue to work.
pipelines:
extract_flow:
entities:
report:
- payment
- adjustment
- refund
max_parallel_tasks: 3
tasks:
extract:
type: python
path: pipelines/extract.py
function: extract_data
kwargs:
report: "{report}"
validate:
type: cli
command: python validate.py --report {report}
depends_on: [extract]
Runtime tasks are generated as payment.extract -> payment.validate, adjustment.extract -> adjustment.validate, and refund.extract -> refund.validate.
Advanced Deployments
Simple pipelines: YAML remains the default. For repeated tenant or environment rollouts, define a reusable template and deployment-specific schedules or variables:
pipeline_templates:
report_pipeline:
tasks:
extract:
type: python
path: pipelines/extract.py
function: extract_data
kwargs:
tenant: "{tenant}"
pipeline_deployments:
client_a_reporting:
template: report_pipeline
schedule:
every: 15m
variables:
tenant: client_a
client_b_reporting:
template: report_pipeline
schedule:
cron: "0 * * * *"
tenant: client_b
Each deployment becomes a normal runnable pipeline id, so the scheduler, UI, CLI, and API keep working without a second execution model.
Deployment Variables In Downstream Pipelines
Variables from a deployment are automatically passed to a downstream pipeline started through triggers_on_success. This is useful when several deployments share one downstream workflow. Parent deployment variables take precedence for the triggered run; a manual run of the downstream pipeline uses the downstream pipeline's own variables or top-level defaults.
pipelines:
Bronze_to_Silver:
tasks:
dbt:
type: cli
command: DBT_CLIENT={practice} dbt run --selector appointment_silver
pipeline_templates:
ECW_Extract_test:
tasks:
extract:
type: cli
command: echo extract
pipeline_deployments:
BENNETT_ETL_Flow:
template: ECW_Extract_test
variables:
practice: BENNETT
triggers_on_success: [Bronze_to_Silver]
When BENNETT_ETL_Flow succeeds, Piply runs Bronze_to_Silver with DBT_CLIENT=BENNETT. A deployment for PALOS would use the same target and set practice: PALOS.
Common CLI
piply --version
piply init my-piply-project
piply validate --config piply-demo/piply.yaml
piply list --config piply-demo/piply.yaml
piply run extract_flow --config piply-demo/piply.yaml --wait
piply run extract_flow --tenant acme --param batch=2026-05-26 --config piply-demo/piply.yaml
piply tasks list extract_flow --config piply-demo/piply.yaml
piply tasks run extract_flow validate --tenant acme --param region=west --config piply-demo/piply.yaml
piply tasks retry <run_id> <task_id> --mode resume --config piply-demo/piply.yaml
piply runs --config piply-demo/piply.yaml
piply logs <run_id> --config piply-demo/piply.yaml
piply pause extract_flow --config piply-demo/piply.yaml
piply resume extract_flow --config piply-demo/piply.yaml
piply start --config piply-demo/piply.yaml
piply start --config piply-demo/piply.yaml --port 8080
piply stop --config piply-demo/piply.yaml
Docs
- Usage Guide: detailed YAML examples,
.env, multi-tenant runs, sensors, and every CLI command - Wiki Overview: architecture and feature summary
- UI And API Guide: screens, actions, and API examples
- Implementation Summary: runtime modules and verification expectations
- Technical Architecture: maintainer-focused deep dive into execution, scheduler, state, storage, UI, and extension points
Roadmap
Planned features:
piply logs --follow- plugin hooks for custom operators and sensors
- managed external secret backends
- richer queue, worker, and artifact metrics
- UI-safe pipeline editing
- task groups, conditional branches, and richer mapped-run visualization
- Optional distributed runner while keeping local mode as the default
-
Task Priority Support
Introduce optional task priority support.
Goal:
When multiple runnable tasks are available for execution, the scheduler should prefer higher-priority tasks.
User-friendly syntax:
tasks:
extract***: type: python
transform**: type: python
validate*: type: python
Interpretation:
*** = priority 3 ** = priority 2
- = priority 1
Internally normalize task IDs:
extract*** → extract
transform** → transform
Store priority separately.
Equivalent explicit syntax:
tasks:
extract: priority: 3
transform: priority: 2
validate: priority: 1
Both syntaxes should be supported.
Execution Rules:
- Higher priority tasks execute first.
- Only among currently runnable tasks.
- Dependencies still take precedence.
- Priority does not bypass dependencies.
- Equal-priority tasks may execute FIFO or randomly.
Requirements:
- Backward compatible.
- UI should display priority visually.
- DAG graph should indicate priority.
- Runtime metadata should persist priority.
- Dynamic task expansion should inherit priority.
- Scheduler should sort ready tasks using priority.
Recommended scheduling order:
- Priority DESC
- Ready Time ASC
- Created Time ASC
- Random tie-breaker
The Pipelines page supports Grid and List views. The selected view is remembered in the browser.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mr_piply-0.1.9.tar.gz.
File metadata
- Download URL: mr_piply-0.1.9.tar.gz
- Upload date:
- Size: 113.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
006da6fffca92ef1d49f36dd8a9a61fd21cda2b55ea5c4a948b1f9629cb5a08b
|
|
| MD5 |
1d65d9cd1dd5a7e83afba66a2227d303
|
|
| BLAKE2b-256 |
7e459890e15a79aa761dd6d535f022488ab7fa6431938417e1346035b934b596
|
File details
Details for the file mr_piply-0.1.9-py3-none-any.whl.
File metadata
- Download URL: mr_piply-0.1.9-py3-none-any.whl
- Upload date:
- Size: 122.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aad8151d72dcc78de04eeb457b7bce11b1eea9d2025b2d75b583890f72e27909
|
|
| MD5 |
99972778b0818dc343acf08c2be36fbf
|
|
| BLAKE2b-256 |
48779559c5b8b149ce4c59a33b33eebf5b4396b9d328ce38f8b7f31abd617232
|