mr-piply 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mr_piply-0.1.3/MANIFEST.in +1 -0
- mr_piply-0.1.3/PKG-INFO +222 -0
- mr_piply-0.1.3/README.md +180 -0
- mr_piply-0.1.3/mr_piply.egg-info/PKG-INFO +222 -0
- mr_piply-0.1.3/mr_piply.egg-info/SOURCES.txt +118 -0
- mr_piply-0.1.3/mr_piply.egg-info/dependency_links.txt +1 -0
- mr_piply-0.1.3/mr_piply.egg-info/entry_points.txt +2 -0
- mr_piply-0.1.3/mr_piply.egg-info/requires.txt +24 -0
- mr_piply-0.1.3/mr_piply.egg-info/top_level.txt +1 -0
- mr_piply-0.1.3/piply/api/__init__.py +3 -0
- mr_piply-0.1.3/piply/api/app.py +100 -0
- mr_piply-0.1.3/piply/api/auth.py +82 -0
- mr_piply-0.1.3/piply/api/routes/__init__.py +1 -0
- mr_piply-0.1.3/piply/api/routes/dashboard.py +37 -0
- mr_piply-0.1.3/piply/api/routes/execution.py +83 -0
- mr_piply-0.1.3/piply/api/routes/pipelines.py +158 -0
- mr_piply-0.1.3/piply/api/routes/runs.py +165 -0
- mr_piply-0.1.3/piply/api/routes/ui.py +308 -0
- mr_piply-0.1.3/piply/api/schemas.py +413 -0
- mr_piply-0.1.3/piply/cli/__init__.py +1 -0
- mr_piply-0.1.3/piply/cli/main.py +540 -0
- mr_piply-0.1.3/piply/core/__init__.py +29 -0
- mr_piply-0.1.3/piply/core/context.py +69 -0
- mr_piply-0.1.3/piply/core/graph.py +69 -0
- mr_piply-0.1.3/piply/core/loader.py +982 -0
- mr_piply-0.1.3/piply/core/models.py +462 -0
- mr_piply-0.1.3/piply/core/outputs.py +101 -0
- mr_piply-0.1.3/piply/core/retry.py +67 -0
- mr_piply-0.1.3/piply/core/scheduler.py +61 -0
- mr_piply-0.1.3/piply/core/scheduling.py +166 -0
- mr_piply-0.1.3/piply/core/secrets.py +159 -0
- mr_piply-0.1.3/piply/core/sensors.py +335 -0
- mr_piply-0.1.3/piply/core/service.py +1097 -0
- mr_piply-0.1.3/piply/core/sql_adapters.py +112 -0
- mr_piply-0.1.3/piply/core/store.py +1301 -0
- mr_piply-0.1.3/piply/engine/base.py +37 -0
- mr_piply-0.1.3/piply/engine/heartbeat.py +42 -0
- mr_piply-0.1.3/piply/engine/local_engine.py +478 -0
- mr_piply-0.1.3/piply/engine/task_runner.py +414 -0
- mr_piply-0.1.3/piply/models/__init__.py +3 -0
- mr_piply-0.1.3/piply/pipeline/__init__.py +14 -0
- mr_piply-0.1.3/piply/plugins/__init__.py +3 -0
- mr_piply-0.1.3/piply/scheduler/__init__.py +5 -0
- mr_piply-0.1.3/piply/services/__init__.py +5 -0
- mr_piply-0.1.3/piply/services/pipeline_service.py +5 -0
- mr_piply-0.1.3/piply/settings.py +158 -0
- mr_piply-0.1.3/piply/tasks/__init__.py +6 -0
- mr_piply-0.1.3/piply/ui/static/app.js +172 -0
- mr_piply-0.1.3/piply/ui/static/dag.js +450 -0
- mr_piply-0.1.3/piply/ui/static/styles.css +1303 -0
- mr_piply-0.1.3/piply/ui/templates/base.html +45 -0
- mr_piply-0.1.3/piply/ui/templates/dashboard.html +252 -0
- mr_piply-0.1.3/piply/ui/templates/execution_matrix.html +163 -0
- mr_piply-0.1.3/piply/ui/templates/logs.html +48 -0
- mr_piply-0.1.3/piply/ui/templates/pipeline_detail.html +364 -0
- mr_piply-0.1.3/piply/ui/templates/pipelines.html +88 -0
- mr_piply-0.1.3/piply/ui/templates/run_detail.html +435 -0
- mr_piply-0.1.3/piply/ui/templates/runs.html +72 -0
- mr_piply-0.1.3/piply/ui/templates/settings.html +118 -0
- mr_piply-0.1.3/piply/utils/__init__.py +5 -0
- mr_piply-0.1.3/pyproject.toml +120 -0
- mr_piply-0.1.3/setup.cfg +4 -0
- mr_piply-0.1.3/tests/test_cli.py +108 -0
- mr_piply-0.1.3/tests/test_context_outputs.py +173 -0
- mr_piply-0.1.3/tests/test_core.py +285 -0
- mr_piply-0.1.3/tests/test_helpers.py +503 -0
- mr_piply-0.1.3/tests/test_plugins.py +199 -0
- mr_piply-0.1.3/tests/test_runtime.py +301 -0
- mr_piply-0.1.3/tests/test_scheduler.py +207 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
recursive-include piply/ui *
|
mr_piply-0.1.3/PKG-INFO
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mr-piply
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: Lightweight Python workflow orchestration platform
|
|
5
|
+
Author: Medrcm Piply Team
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/gurudevkumar51/piply
|
|
8
|
+
Project-URL: Repository, https://github.com/gurudevkumar51/piply
|
|
9
|
+
Project-URL: Issues, https://github.com/gurudevkumar51/piply/issues
|
|
10
|
+
Keywords: workflow,scheduler,orchestration,automation,pipeline
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: fastapi<1.0,>=0.110
|
|
23
|
+
Requires-Dist: uvicorn<1.0,>=0.29
|
|
24
|
+
Requires-Dist: pydantic<3,>=2
|
|
25
|
+
Requires-Dist: jinja2<4,>=3.1
|
|
26
|
+
Requires-Dist: pyyaml<7,>=6
|
|
27
|
+
Requires-Dist: typer<1,>=0.12
|
|
28
|
+
Requires-Dist: httpx<1,>=0.27
|
|
29
|
+
Requires-Dist: python-dotenv<2,>=1
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: ruff<1,>=0.6; extra == "dev"
|
|
32
|
+
Requires-Dist: pre-commit<4,>=3; extra == "dev"
|
|
33
|
+
Provides-Extra: test
|
|
34
|
+
Requires-Dist: pytest<9,>=8; extra == "test"
|
|
35
|
+
Requires-Dist: pytest-cov<6,>=5; extra == "test"
|
|
36
|
+
Provides-Extra: types
|
|
37
|
+
Requires-Dist: mypy<2,>=1; extra == "types"
|
|
38
|
+
Provides-Extra: build
|
|
39
|
+
Requires-Dist: build<2,>=1; extra == "build"
|
|
40
|
+
Requires-Dist: twine<7,>=6.2; extra == "build"
|
|
41
|
+
Requires-Dist: pkginfo>=1.12; extra == "build"
|
|
42
|
+
|
|
43
|
+
# Piply
|
|
44
|
+
|
|
45
|
+
Piply is a lightweight Python pipeline framework for teams that want script orchestration, schedules, retries, logs, sensors, and a usable operations UI without adopting a heavy orchestration stack.
|
|
46
|
+
|
|
47
|
+
It is intentionally small:
|
|
48
|
+
|
|
49
|
+
- YAML-first pipeline definitions
|
|
50
|
+
- local execution with dependency-aware DAG scheduling
|
|
51
|
+
- SQLite for runs, logs, task outputs, queue state, sensors, and pause overrides
|
|
52
|
+
- FastAPI + server-rendered UI
|
|
53
|
+
- no Redis, Celery, Prefect, Airflow, or external queue required
|
|
54
|
+
|
|
55
|
+
## What You Get
|
|
56
|
+
|
|
57
|
+
- Multi-task pipelines with `depends_on`
|
|
58
|
+
- Sequential or parallel execution inferred from the DAG
|
|
59
|
+
- Python script and Python callable tasks
|
|
60
|
+
- CLI, API, webhook, email, and SSH task types
|
|
61
|
+
- Task output passing with `context["task_id"]`
|
|
62
|
+
- Pipeline-to-pipeline JSON output passing
|
|
63
|
+
- Per-task upstream failure behavior: `skip`, `fail`, or `continue`
|
|
64
|
+
- Schedule backfill through an internal SQLite queue
|
|
65
|
+
- File, SQL, and API sensors
|
|
66
|
+
- Reusable SQL connections and explicit secret references
|
|
67
|
+
- Retries, resume-from-failure, cancellation, and logs
|
|
68
|
+
- Queue and local worker metrics
|
|
69
|
+
- Dashboard, Pipelines, Execution Matrix, Logs, Settings, and run detail pages
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install -e .
|
|
75
|
+
copy .env.example .env
|
|
76
|
+
piply validate --config piply-demo/piply.yaml
|
|
77
|
+
piply start --config piply-demo/piply.yaml
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Open `http://127.0.0.1:8000`.
|
|
81
|
+
|
|
82
|
+
Create a starter project:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
piply init my-piply-project
|
|
86
|
+
piply validate --config my-piply-project/piply.yaml
|
|
87
|
+
piply start --config my-piply-project/piply.yaml
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The generated starter includes a runnable `extract_flow -> report_flow` chain plus disabled reference pipelines for optional operators and sensors.
|
|
91
|
+
|
|
92
|
+
## Example YAML
|
|
93
|
+
|
|
94
|
+
```yaml
|
|
95
|
+
version: "1"
|
|
96
|
+
title: Piply Workspace
|
|
97
|
+
workspace: .
|
|
98
|
+
|
|
99
|
+
secrets:
|
|
100
|
+
backend: env
|
|
101
|
+
prefix: PIPLY_SECRET_
|
|
102
|
+
|
|
103
|
+
connections:
|
|
104
|
+
app_db: sqlite:///sensor_demo.db
|
|
105
|
+
|
|
106
|
+
pipelines:
|
|
107
|
+
extract_flow:
|
|
108
|
+
schedule:
|
|
109
|
+
every: 15m
|
|
110
|
+
retry:
|
|
111
|
+
attempts: 2
|
|
112
|
+
mode: resume
|
|
113
|
+
delay_seconds: 10
|
|
114
|
+
max_parallel_tasks: 2
|
|
115
|
+
triggers_on_success:
|
|
116
|
+
- report_flow
|
|
117
|
+
sensors:
|
|
118
|
+
inbound_rows:
|
|
119
|
+
type: sql_sensor
|
|
120
|
+
connection_ref: app_db
|
|
121
|
+
table: inbound_events
|
|
122
|
+
cursor_column: id
|
|
123
|
+
tasks:
|
|
124
|
+
extract:
|
|
125
|
+
type: python
|
|
126
|
+
path: pipelines/extract.py
|
|
127
|
+
function: extract_data
|
|
128
|
+
kwargs:
|
|
129
|
+
records: 120
|
|
130
|
+
|
|
131
|
+
transform:
|
|
132
|
+
type: python
|
|
133
|
+
path: pipelines/extract.py
|
|
134
|
+
function: transform_data
|
|
135
|
+
depends_on: [extract]
|
|
136
|
+
|
|
137
|
+
validate:
|
|
138
|
+
type: cli
|
|
139
|
+
command: python -c "print('validated')"
|
|
140
|
+
depends_on: [transform]
|
|
141
|
+
|
|
142
|
+
publish_manifest:
|
|
143
|
+
type: cli
|
|
144
|
+
command: python -c "print('published')"
|
|
145
|
+
depends_on: [transform]
|
|
146
|
+
on_upstream_failure: skip
|
|
147
|
+
|
|
148
|
+
report_flow:
|
|
149
|
+
tasks:
|
|
150
|
+
build_report:
|
|
151
|
+
type: python
|
|
152
|
+
path: pipelines/report.py
|
|
153
|
+
function: build_report
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Python callable tasks can consume upstream outputs:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
def transform_data(context):
|
|
160
|
+
extracted = context["extract"]
|
|
161
|
+
return {"records": extracted["records"] + 1}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
When `extract_flow` triggers `report_flow`, JSON outputs are also passed into the downstream context.
|
|
165
|
+
|
|
166
|
+
## CLI
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
piply init
|
|
170
|
+
piply validate --config piply-demo/piply.yaml
|
|
171
|
+
piply list --config piply-demo/piply.yaml
|
|
172
|
+
piply run extract_flow --config piply-demo/piply.yaml --wait
|
|
173
|
+
piply tasks list extract_flow --config piply-demo/piply.yaml
|
|
174
|
+
piply tasks run extract_flow publish_manifest --config piply-demo/piply.yaml
|
|
175
|
+
piply tasks retry <run_id> <task_id> --mode resume --config piply-demo/piply.yaml
|
|
176
|
+
piply runs --config piply-demo/piply.yaml
|
|
177
|
+
piply logs <run_id> --config piply-demo/piply.yaml
|
|
178
|
+
piply pause extract_flow --config piply-demo/piply.yaml
|
|
179
|
+
piply resume extract_flow --config piply-demo/piply.yaml
|
|
180
|
+
piply start --config piply-demo/piply.yaml
|
|
181
|
+
piply stop --config piply-demo/piply.yaml
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## API Highlights
|
|
185
|
+
|
|
186
|
+
- `GET /api/dashboard`
|
|
187
|
+
- `GET /api/pipelines`
|
|
188
|
+
- `GET /api/pipelines/{pipeline_id}`
|
|
189
|
+
- `POST /api/pipelines/{pipeline_id}/run`
|
|
190
|
+
- `POST /api/pipelines/{pipeline_id}/tasks/{task_id}/run`
|
|
191
|
+
- `POST /api/pipelines/{pipeline_id}/chain/{target_pipeline_id}`
|
|
192
|
+
- `GET /api/runs`
|
|
193
|
+
- `GET /api/runs/{run_id}`
|
|
194
|
+
- `GET /api/runs/{run_id}/tasks/{task_id}`
|
|
195
|
+
- `GET /api/runs/{run_id}/tasks/{task_id}/output`
|
|
196
|
+
- `POST /api/runs/{run_id}/retry`
|
|
197
|
+
- `POST /api/runs/{run_id}/tasks/{task_id}/retry`
|
|
198
|
+
- `GET /api/metrics`
|
|
199
|
+
- `GET /api/execution-matrix`
|
|
200
|
+
- `GET /api/logs`
|
|
201
|
+
|
|
202
|
+
## Runtime Model
|
|
203
|
+
|
|
204
|
+
Piply runs locally and keeps state in SQLite. The scheduler materializes due schedules and sensor events into an internal queue, then dispatches work with per-pipeline backpressure. The engine executes tasks through lightweight local workers and records task runs, logs, output metadata, retries, lineage, and parent/child pipeline relationships. CLI `--wait` runs complete downstream pipeline triggers inline so chained smoke tests finish deterministically.
|
|
205
|
+
|
|
206
|
+
## Roadmap
|
|
207
|
+
|
|
208
|
+
Planned features:
|
|
209
|
+
|
|
210
|
+
- `piply logs --follow`
|
|
211
|
+
- reusable task templates / profiles
|
|
212
|
+
- plugin hooks for custom operators
|
|
213
|
+
- UI controls for editing pipeline definitions safely
|
|
214
|
+
- artifact retention policies for large outputs
|
|
215
|
+
- optional distributed runner while keeping local mode as the default
|
|
216
|
+
|
|
217
|
+
## More Docs
|
|
218
|
+
|
|
219
|
+
- `wiki/USAGE_GUIDE.md`
|
|
220
|
+
- `wiki/README.md`
|
|
221
|
+
- `wiki/UI_API_GUIDE.md`
|
|
222
|
+
- `wiki/IMPLEMENTATION_SUMMARY.md`
|
mr_piply-0.1.3/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Piply
|
|
2
|
+
|
|
3
|
+
Piply is a lightweight Python pipeline framework for teams that want script orchestration, schedules, retries, logs, sensors, and a usable operations UI without adopting a heavy orchestration stack.
|
|
4
|
+
|
|
5
|
+
It is intentionally small:
|
|
6
|
+
|
|
7
|
+
- YAML-first pipeline definitions
|
|
8
|
+
- local execution with dependency-aware DAG scheduling
|
|
9
|
+
- SQLite for runs, logs, task outputs, queue state, sensors, and pause overrides
|
|
10
|
+
- FastAPI + server-rendered UI
|
|
11
|
+
- no Redis, Celery, Prefect, Airflow, or external queue required
|
|
12
|
+
|
|
13
|
+
## What You Get
|
|
14
|
+
|
|
15
|
+
- Multi-task pipelines with `depends_on`
|
|
16
|
+
- Sequential or parallel execution inferred from the DAG
|
|
17
|
+
- Python script and Python callable tasks
|
|
18
|
+
- CLI, API, webhook, email, and SSH task types
|
|
19
|
+
- Task output passing with `context["task_id"]`
|
|
20
|
+
- Pipeline-to-pipeline JSON output passing
|
|
21
|
+
- Per-task upstream failure behavior: `skip`, `fail`, or `continue`
|
|
22
|
+
- Schedule backfill through an internal SQLite queue
|
|
23
|
+
- File, SQL, and API sensors
|
|
24
|
+
- Reusable SQL connections and explicit secret references
|
|
25
|
+
- Retries, resume-from-failure, cancellation, and logs
|
|
26
|
+
- Queue and local worker metrics
|
|
27
|
+
- Dashboard, Pipelines, Execution Matrix, Logs, Settings, and run detail pages
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install -e .
|
|
33
|
+
copy .env.example .env
|
|
34
|
+
piply validate --config piply-demo/piply.yaml
|
|
35
|
+
piply start --config piply-demo/piply.yaml
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Open `http://127.0.0.1:8000`.
|
|
39
|
+
|
|
40
|
+
Create a starter project:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
piply init my-piply-project
|
|
44
|
+
piply validate --config my-piply-project/piply.yaml
|
|
45
|
+
piply start --config my-piply-project/piply.yaml
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The generated starter includes a runnable `extract_flow -> report_flow` chain plus disabled reference pipelines for optional operators and sensors.
|
|
49
|
+
|
|
50
|
+
## Example YAML
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
version: "1"
|
|
54
|
+
title: Piply Workspace
|
|
55
|
+
workspace: .
|
|
56
|
+
|
|
57
|
+
secrets:
|
|
58
|
+
backend: env
|
|
59
|
+
prefix: PIPLY_SECRET_
|
|
60
|
+
|
|
61
|
+
connections:
|
|
62
|
+
app_db: sqlite:///sensor_demo.db
|
|
63
|
+
|
|
64
|
+
pipelines:
|
|
65
|
+
extract_flow:
|
|
66
|
+
schedule:
|
|
67
|
+
every: 15m
|
|
68
|
+
retry:
|
|
69
|
+
attempts: 2
|
|
70
|
+
mode: resume
|
|
71
|
+
delay_seconds: 10
|
|
72
|
+
max_parallel_tasks: 2
|
|
73
|
+
triggers_on_success:
|
|
74
|
+
- report_flow
|
|
75
|
+
sensors:
|
|
76
|
+
inbound_rows:
|
|
77
|
+
type: sql_sensor
|
|
78
|
+
connection_ref: app_db
|
|
79
|
+
table: inbound_events
|
|
80
|
+
cursor_column: id
|
|
81
|
+
tasks:
|
|
82
|
+
extract:
|
|
83
|
+
type: python
|
|
84
|
+
path: pipelines/extract.py
|
|
85
|
+
function: extract_data
|
|
86
|
+
kwargs:
|
|
87
|
+
records: 120
|
|
88
|
+
|
|
89
|
+
transform:
|
|
90
|
+
type: python
|
|
91
|
+
path: pipelines/extract.py
|
|
92
|
+
function: transform_data
|
|
93
|
+
depends_on: [extract]
|
|
94
|
+
|
|
95
|
+
validate:
|
|
96
|
+
type: cli
|
|
97
|
+
command: python -c "print('validated')"
|
|
98
|
+
depends_on: [transform]
|
|
99
|
+
|
|
100
|
+
publish_manifest:
|
|
101
|
+
type: cli
|
|
102
|
+
command: python -c "print('published')"
|
|
103
|
+
depends_on: [transform]
|
|
104
|
+
on_upstream_failure: skip
|
|
105
|
+
|
|
106
|
+
report_flow:
|
|
107
|
+
tasks:
|
|
108
|
+
build_report:
|
|
109
|
+
type: python
|
|
110
|
+
path: pipelines/report.py
|
|
111
|
+
function: build_report
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Python callable tasks can consume upstream outputs:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
def transform_data(context):
|
|
118
|
+
extracted = context["extract"]
|
|
119
|
+
return {"records": extracted["records"] + 1}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
When `extract_flow` triggers `report_flow`, JSON outputs are also passed into the downstream context.
|
|
123
|
+
|
|
124
|
+
## CLI
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
piply init
|
|
128
|
+
piply validate --config piply-demo/piply.yaml
|
|
129
|
+
piply list --config piply-demo/piply.yaml
|
|
130
|
+
piply run extract_flow --config piply-demo/piply.yaml --wait
|
|
131
|
+
piply tasks list extract_flow --config piply-demo/piply.yaml
|
|
132
|
+
piply tasks run extract_flow publish_manifest --config piply-demo/piply.yaml
|
|
133
|
+
piply tasks retry <run_id> <task_id> --mode resume --config piply-demo/piply.yaml
|
|
134
|
+
piply runs --config piply-demo/piply.yaml
|
|
135
|
+
piply logs <run_id> --config piply-demo/piply.yaml
|
|
136
|
+
piply pause extract_flow --config piply-demo/piply.yaml
|
|
137
|
+
piply resume extract_flow --config piply-demo/piply.yaml
|
|
138
|
+
piply start --config piply-demo/piply.yaml
|
|
139
|
+
piply stop --config piply-demo/piply.yaml
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## API Highlights
|
|
143
|
+
|
|
144
|
+
- `GET /api/dashboard`
|
|
145
|
+
- `GET /api/pipelines`
|
|
146
|
+
- `GET /api/pipelines/{pipeline_id}`
|
|
147
|
+
- `POST /api/pipelines/{pipeline_id}/run`
|
|
148
|
+
- `POST /api/pipelines/{pipeline_id}/tasks/{task_id}/run`
|
|
149
|
+
- `POST /api/pipelines/{pipeline_id}/chain/{target_pipeline_id}`
|
|
150
|
+
- `GET /api/runs`
|
|
151
|
+
- `GET /api/runs/{run_id}`
|
|
152
|
+
- `GET /api/runs/{run_id}/tasks/{task_id}`
|
|
153
|
+
- `GET /api/runs/{run_id}/tasks/{task_id}/output`
|
|
154
|
+
- `POST /api/runs/{run_id}/retry`
|
|
155
|
+
- `POST /api/runs/{run_id}/tasks/{task_id}/retry`
|
|
156
|
+
- `GET /api/metrics`
|
|
157
|
+
- `GET /api/execution-matrix`
|
|
158
|
+
- `GET /api/logs`
|
|
159
|
+
|
|
160
|
+
## Runtime Model
|
|
161
|
+
|
|
162
|
+
Piply runs locally and keeps state in SQLite. The scheduler materializes due schedules and sensor events into an internal queue, then dispatches work with per-pipeline backpressure. The engine executes tasks through lightweight local workers and records task runs, logs, output metadata, retries, lineage, and parent/child pipeline relationships. CLI `--wait` runs complete downstream pipeline triggers inline so chained smoke tests finish deterministically.
|
|
163
|
+
|
|
164
|
+
## Roadmap
|
|
165
|
+
|
|
166
|
+
Planned features:
|
|
167
|
+
|
|
168
|
+
- `piply logs --follow`
|
|
169
|
+
- reusable task templates / profiles
|
|
170
|
+
- plugin hooks for custom operators
|
|
171
|
+
- UI controls for editing pipeline definitions safely
|
|
172
|
+
- artifact retention policies for large outputs
|
|
173
|
+
- optional distributed runner while keeping local mode as the default
|
|
174
|
+
|
|
175
|
+
## More Docs
|
|
176
|
+
|
|
177
|
+
- `wiki/USAGE_GUIDE.md`
|
|
178
|
+
- `wiki/README.md`
|
|
179
|
+
- `wiki/UI_API_GUIDE.md`
|
|
180
|
+
- `wiki/IMPLEMENTATION_SUMMARY.md`
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mr-piply
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: Lightweight Python workflow orchestration platform
|
|
5
|
+
Author: Medrcm Piply Team
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/gurudevkumar51/piply
|
|
8
|
+
Project-URL: Repository, https://github.com/gurudevkumar51/piply
|
|
9
|
+
Project-URL: Issues, https://github.com/gurudevkumar51/piply/issues
|
|
10
|
+
Keywords: workflow,scheduler,orchestration,automation,pipeline
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: fastapi<1.0,>=0.110
|
|
23
|
+
Requires-Dist: uvicorn<1.0,>=0.29
|
|
24
|
+
Requires-Dist: pydantic<3,>=2
|
|
25
|
+
Requires-Dist: jinja2<4,>=3.1
|
|
26
|
+
Requires-Dist: pyyaml<7,>=6
|
|
27
|
+
Requires-Dist: typer<1,>=0.12
|
|
28
|
+
Requires-Dist: httpx<1,>=0.27
|
|
29
|
+
Requires-Dist: python-dotenv<2,>=1
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: ruff<1,>=0.6; extra == "dev"
|
|
32
|
+
Requires-Dist: pre-commit<4,>=3; extra == "dev"
|
|
33
|
+
Provides-Extra: test
|
|
34
|
+
Requires-Dist: pytest<9,>=8; extra == "test"
|
|
35
|
+
Requires-Dist: pytest-cov<6,>=5; extra == "test"
|
|
36
|
+
Provides-Extra: types
|
|
37
|
+
Requires-Dist: mypy<2,>=1; extra == "types"
|
|
38
|
+
Provides-Extra: build
|
|
39
|
+
Requires-Dist: build<2,>=1; extra == "build"
|
|
40
|
+
Requires-Dist: twine<7,>=6.2; extra == "build"
|
|
41
|
+
Requires-Dist: pkginfo>=1.12; extra == "build"
|
|
42
|
+
|
|
43
|
+
# Piply
|
|
44
|
+
|
|
45
|
+
Piply is a lightweight Python pipeline framework for teams that want script orchestration, schedules, retries, logs, sensors, and a usable operations UI without adopting a heavy orchestration stack.
|
|
46
|
+
|
|
47
|
+
It is intentionally small:
|
|
48
|
+
|
|
49
|
+
- YAML-first pipeline definitions
|
|
50
|
+
- local execution with dependency-aware DAG scheduling
|
|
51
|
+
- SQLite for runs, logs, task outputs, queue state, sensors, and pause overrides
|
|
52
|
+
- FastAPI + server-rendered UI
|
|
53
|
+
- no Redis, Celery, Prefect, Airflow, or external queue required
|
|
54
|
+
|
|
55
|
+
## What You Get
|
|
56
|
+
|
|
57
|
+
- Multi-task pipelines with `depends_on`
|
|
58
|
+
- Sequential or parallel execution inferred from the DAG
|
|
59
|
+
- Python script and Python callable tasks
|
|
60
|
+
- CLI, API, webhook, email, and SSH task types
|
|
61
|
+
- Task output passing with `context["task_id"]`
|
|
62
|
+
- Pipeline-to-pipeline JSON output passing
|
|
63
|
+
- Per-task upstream failure behavior: `skip`, `fail`, or `continue`
|
|
64
|
+
- Schedule backfill through an internal SQLite queue
|
|
65
|
+
- File, SQL, and API sensors
|
|
66
|
+
- Reusable SQL connections and explicit secret references
|
|
67
|
+
- Retries, resume-from-failure, cancellation, and logs
|
|
68
|
+
- Queue and local worker metrics
|
|
69
|
+
- Dashboard, Pipelines, Execution Matrix, Logs, Settings, and run detail pages
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install -e .
|
|
75
|
+
copy .env.example .env
|
|
76
|
+
piply validate --config piply-demo/piply.yaml
|
|
77
|
+
piply start --config piply-demo/piply.yaml
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Open `http://127.0.0.1:8000`.
|
|
81
|
+
|
|
82
|
+
Create a starter project:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
piply init my-piply-project
|
|
86
|
+
piply validate --config my-piply-project/piply.yaml
|
|
87
|
+
piply start --config my-piply-project/piply.yaml
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The generated starter includes a runnable `extract_flow -> report_flow` chain plus disabled reference pipelines for optional operators and sensors.
|
|
91
|
+
|
|
92
|
+
## Example YAML
|
|
93
|
+
|
|
94
|
+
```yaml
|
|
95
|
+
version: "1"
|
|
96
|
+
title: Piply Workspace
|
|
97
|
+
workspace: .
|
|
98
|
+
|
|
99
|
+
secrets:
|
|
100
|
+
backend: env
|
|
101
|
+
prefix: PIPLY_SECRET_
|
|
102
|
+
|
|
103
|
+
connections:
|
|
104
|
+
app_db: sqlite:///sensor_demo.db
|
|
105
|
+
|
|
106
|
+
pipelines:
|
|
107
|
+
extract_flow:
|
|
108
|
+
schedule:
|
|
109
|
+
every: 15m
|
|
110
|
+
retry:
|
|
111
|
+
attempts: 2
|
|
112
|
+
mode: resume
|
|
113
|
+
delay_seconds: 10
|
|
114
|
+
max_parallel_tasks: 2
|
|
115
|
+
triggers_on_success:
|
|
116
|
+
- report_flow
|
|
117
|
+
sensors:
|
|
118
|
+
inbound_rows:
|
|
119
|
+
type: sql_sensor
|
|
120
|
+
connection_ref: app_db
|
|
121
|
+
table: inbound_events
|
|
122
|
+
cursor_column: id
|
|
123
|
+
tasks:
|
|
124
|
+
extract:
|
|
125
|
+
type: python
|
|
126
|
+
path: pipelines/extract.py
|
|
127
|
+
function: extract_data
|
|
128
|
+
kwargs:
|
|
129
|
+
records: 120
|
|
130
|
+
|
|
131
|
+
transform:
|
|
132
|
+
type: python
|
|
133
|
+
path: pipelines/extract.py
|
|
134
|
+
function: transform_data
|
|
135
|
+
depends_on: [extract]
|
|
136
|
+
|
|
137
|
+
validate:
|
|
138
|
+
type: cli
|
|
139
|
+
command: python -c "print('validated')"
|
|
140
|
+
depends_on: [transform]
|
|
141
|
+
|
|
142
|
+
publish_manifest:
|
|
143
|
+
type: cli
|
|
144
|
+
command: python -c "print('published')"
|
|
145
|
+
depends_on: [transform]
|
|
146
|
+
on_upstream_failure: skip
|
|
147
|
+
|
|
148
|
+
report_flow:
|
|
149
|
+
tasks:
|
|
150
|
+
build_report:
|
|
151
|
+
type: python
|
|
152
|
+
path: pipelines/report.py
|
|
153
|
+
function: build_report
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Python callable tasks can consume upstream outputs:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
def transform_data(context):
|
|
160
|
+
extracted = context["extract"]
|
|
161
|
+
return {"records": extracted["records"] + 1}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
When `extract_flow` triggers `report_flow`, JSON outputs are also passed into the downstream context.
|
|
165
|
+
|
|
166
|
+
## CLI
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
piply init
|
|
170
|
+
piply validate --config piply-demo/piply.yaml
|
|
171
|
+
piply list --config piply-demo/piply.yaml
|
|
172
|
+
piply run extract_flow --config piply-demo/piply.yaml --wait
|
|
173
|
+
piply tasks list extract_flow --config piply-demo/piply.yaml
|
|
174
|
+
piply tasks run extract_flow publish_manifest --config piply-demo/piply.yaml
|
|
175
|
+
piply tasks retry <run_id> <task_id> --mode resume --config piply-demo/piply.yaml
|
|
176
|
+
piply runs --config piply-demo/piply.yaml
|
|
177
|
+
piply logs <run_id> --config piply-demo/piply.yaml
|
|
178
|
+
piply pause extract_flow --config piply-demo/piply.yaml
|
|
179
|
+
piply resume extract_flow --config piply-demo/piply.yaml
|
|
180
|
+
piply start --config piply-demo/piply.yaml
|
|
181
|
+
piply stop --config piply-demo/piply.yaml
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## API Highlights
|
|
185
|
+
|
|
186
|
+
- `GET /api/dashboard`
|
|
187
|
+
- `GET /api/pipelines`
|
|
188
|
+
- `GET /api/pipelines/{pipeline_id}`
|
|
189
|
+
- `POST /api/pipelines/{pipeline_id}/run`
|
|
190
|
+
- `POST /api/pipelines/{pipeline_id}/tasks/{task_id}/run`
|
|
191
|
+
- `POST /api/pipelines/{pipeline_id}/chain/{target_pipeline_id}`
|
|
192
|
+
- `GET /api/runs`
|
|
193
|
+
- `GET /api/runs/{run_id}`
|
|
194
|
+
- `GET /api/runs/{run_id}/tasks/{task_id}`
|
|
195
|
+
- `GET /api/runs/{run_id}/tasks/{task_id}/output`
|
|
196
|
+
- `POST /api/runs/{run_id}/retry`
|
|
197
|
+
- `POST /api/runs/{run_id}/tasks/{task_id}/retry`
|
|
198
|
+
- `GET /api/metrics`
|
|
199
|
+
- `GET /api/execution-matrix`
|
|
200
|
+
- `GET /api/logs`
|
|
201
|
+
|
|
202
|
+
## Runtime Model
|
|
203
|
+
|
|
204
|
+
Piply runs locally and keeps state in SQLite. The scheduler materializes due schedules and sensor events into an internal queue, then dispatches work with per-pipeline backpressure. The engine executes tasks through lightweight local workers and records task runs, logs, output metadata, retries, lineage, and parent/child pipeline relationships. CLI `--wait` runs complete downstream pipeline triggers inline so chained smoke tests finish deterministically.
|
|
205
|
+
|
|
206
|
+
## Roadmap
|
|
207
|
+
|
|
208
|
+
Planned features:
|
|
209
|
+
|
|
210
|
+
- `piply logs --follow`
|
|
211
|
+
- reusable task templates / profiles
|
|
212
|
+
- plugin hooks for custom operators
|
|
213
|
+
- UI controls for editing pipeline definitions safely
|
|
214
|
+
- artifact retention policies for large outputs
|
|
215
|
+
- optional distributed runner while keeping local mode as the default
|
|
216
|
+
|
|
217
|
+
## More Docs
|
|
218
|
+
|
|
219
|
+
- `wiki/USAGE_GUIDE.md`
|
|
220
|
+
- `wiki/README.md`
|
|
221
|
+
- `wiki/UI_API_GUIDE.md`
|
|
222
|
+
- `wiki/IMPLEMENTATION_SUMMARY.md`
|