pyoco 0.1.0__tar.gz → 0.5.0__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.
Files changed (56) hide show
  1. pyoco-0.5.0/PKG-INFO +159 -0
  2. pyoco-0.5.0/README.md +147 -0
  3. pyoco-0.5.0/pyproject.toml +20 -0
  4. pyoco-0.5.0/src/pyoco/cli/main.py +396 -0
  5. pyoco-0.5.0/src/pyoco/client.py +89 -0
  6. {pyoco-0.1.0 → pyoco-0.5.0}/src/pyoco/core/context.py +100 -4
  7. pyoco-0.5.0/src/pyoco/core/engine.py +531 -0
  8. pyoco-0.5.0/src/pyoco/core/exceptions.py +15 -0
  9. pyoco-0.5.0/src/pyoco/core/models.py +286 -0
  10. {pyoco-0.1.0 → pyoco-0.5.0}/src/pyoco/discovery/loader.py +29 -3
  11. pyoco-0.5.0/src/pyoco/discovery/plugins.py +92 -0
  12. pyoco-0.5.0/src/pyoco/dsl/expressions.py +160 -0
  13. pyoco-0.5.0/src/pyoco/dsl/nodes.py +56 -0
  14. pyoco-0.5.0/src/pyoco/dsl/syntax.py +268 -0
  15. pyoco-0.5.0/src/pyoco/dsl/validator.py +104 -0
  16. pyoco-0.5.0/src/pyoco/server/api.py +112 -0
  17. pyoco-0.5.0/src/pyoco/server/metrics.py +113 -0
  18. pyoco-0.5.0/src/pyoco/server/models.py +30 -0
  19. pyoco-0.5.0/src/pyoco/server/store.py +219 -0
  20. pyoco-0.5.0/src/pyoco/server/webhook.py +108 -0
  21. pyoco-0.5.0/src/pyoco/socketless_reset.py +7 -0
  22. {pyoco-0.1.0 → pyoco-0.5.0}/src/pyoco/trace/backend.py +1 -1
  23. {pyoco-0.1.0 → pyoco-0.5.0}/src/pyoco/trace/console.py +12 -4
  24. pyoco-0.5.0/src/pyoco/worker/__init__.py +0 -0
  25. pyoco-0.5.0/src/pyoco/worker/client.py +43 -0
  26. pyoco-0.5.0/src/pyoco/worker/runner.py +166 -0
  27. pyoco-0.5.0/src/pyoco.egg-info/PKG-INFO +159 -0
  28. pyoco-0.5.0/src/pyoco.egg-info/SOURCES.txt +45 -0
  29. pyoco-0.5.0/src/pyoco.egg-info/requires.txt +5 -0
  30. pyoco-0.5.0/tests/test_cancellation.py +82 -0
  31. pyoco-0.5.0/tests/test_cli_cancellation.py +101 -0
  32. pyoco-0.5.0/tests/test_e2e_socketless.py +79 -0
  33. pyoco-0.5.0/tests/test_engine_state.py +68 -0
  34. pyoco-0.5.0/tests/test_integration_v030.py +138 -0
  35. pyoco-0.5.0/tests/test_socketless_basic.py +29 -0
  36. pyoco-0.5.0/tests/test_state_models.py +43 -0
  37. pyoco-0.1.0/PKG-INFO +0 -7
  38. pyoco-0.1.0/pyproject.toml +0 -9
  39. pyoco-0.1.0/src/pyoco/cli/main.py +0 -177
  40. pyoco-0.1.0/src/pyoco/core/engine.py +0 -249
  41. pyoco-0.1.0/src/pyoco/core/models.py +0 -116
  42. pyoco-0.1.0/src/pyoco/dsl/syntax.py +0 -122
  43. pyoco-0.1.0/src/pyoco.egg-info/PKG-INFO +0 -7
  44. pyoco-0.1.0/src/pyoco.egg-info/SOURCES.txt +0 -22
  45. pyoco-0.1.0/src/pyoco.egg-info/requires.txt +0 -1
  46. {pyoco-0.1.0 → pyoco-0.5.0}/setup.cfg +0 -0
  47. {pyoco-0.1.0 → pyoco-0.5.0}/src/pyoco/__init__.py +0 -0
  48. {pyoco-0.1.0 → pyoco-0.5.0}/src/pyoco/cli/entry.py +0 -0
  49. {pyoco-0.1.0 → pyoco-0.5.0}/src/pyoco/core/base_task.py +0 -0
  50. {pyoco-0.1.0 → pyoco-0.5.0}/src/pyoco/dsl/__init__.py +0 -0
  51. {pyoco-0.1.0 → pyoco-0.5.0}/src/pyoco/schemas/config.py +0 -0
  52. /pyoco-0.1.0/README.md → /pyoco-0.5.0/src/pyoco/server/__init__.py +0 -0
  53. {pyoco-0.1.0 → pyoco-0.5.0}/src/pyoco.egg-info/dependency_links.txt +0 -0
  54. {pyoco-0.1.0 → pyoco-0.5.0}/src/pyoco.egg-info/top_level.txt +0 -0
  55. {pyoco-0.1.0 → pyoco-0.5.0}/tests/test_dsl.py +0 -0
  56. {pyoco-0.1.0 → pyoco-0.5.0}/tests/test_engine.py +0 -0
pyoco-0.5.0/PKG-INFO ADDED
@@ -0,0 +1,159 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyoco
3
+ Version: 0.5.0
4
+ Summary: A workflow engine with sugar syntax
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: pyyaml>=6.0.3
8
+ Requires-Dist: fastapi>=0.100.0
9
+ Requires-Dist: uvicorn>=0.20.0
10
+ Requires-Dist: httpx>=0.24.0
11
+ Requires-Dist: prometheus-client>=0.20.0
12
+
13
+ # 🐇 Pyoco
14
+
15
+ **pyoco is a minimal, pure-Python DAG engine for defining and running simple task-based workflows.**
16
+
17
+ ## Overview
18
+
19
+ Pyoco is designed to be significantly smaller, lighter, and have fewer dependencies than full-scale workflow engines like Airflow. It is optimized for local development and single-machine execution.
20
+
21
+ You can define tasks and their dependencies entirely in Python code using decorators and a simple API. There is no need for complex configuration files or external databases.
22
+
23
+ It is ideal for small jobs, development environments, and personal projects where a full-stack workflow engine would be overkill.
24
+
25
+ ## ✨ Features
26
+
27
+ - **Pure Python**: No external services or heavy dependencies required.
28
+ - **Minimal DAG model**: Tasks and dependencies are defined directly in code.
29
+ - **Task-oriented**: Focus on "small workflows" that should be easy to read and maintain.
30
+ - **Friendly trace logs**: Runs can be traced step by step from the terminal with cute (or plain) logs.
31
+ - **Parallel Execution**: Automatically runs independent tasks in parallel.
32
+ - **Artifact Management**: Easily save and manage task outputs and files.
33
+ - **Observability**: Track execution with unique Run IDs and detailed state transitions.
34
+ - **Control**: Cancel running workflows gracefully with `Ctrl+C`.
35
+
36
+ ## 📦 Installation
37
+
38
+ ```bash
39
+ pip install pyoco
40
+ ```
41
+
42
+ ## 🚀 Usage
43
+
44
+ Here is a minimal example of a pure-Python workflow.
45
+
46
+ ```python
47
+ from pyoco import task
48
+ from pyoco.core.models import Flow
49
+ from pyoco.core.engine import Engine
50
+
51
+ @task
52
+ def fetch_data(ctx):
53
+ print("🐰 Fetching data...")
54
+ return {"id": 1, "value": "carrot"}
55
+
56
+ @task
57
+ def process_data(ctx, data):
58
+ print(f"🥕 Processing: {data['value']}")
59
+ return data['value'].upper()
60
+
61
+ @task
62
+ def save_result(ctx, result):
63
+ print(f"✨ Saved: {result}")
64
+
65
+ # Define the flow
66
+ flow = Flow(name="hello_pyoco")
67
+ flow >> fetch_data >> process_data >> save_result
68
+
69
+ # Wire inputs (explicitly for this example)
70
+ process_data.task.inputs = {"data": "$node.fetch_data.output"}
71
+ save_result.task.inputs = {"result": "$node.process_data.output"}
72
+
73
+ if __name__ == "__main__":
74
+ engine = Engine()
75
+ engine.run(flow)
76
+ ```
77
+
78
+ Run it:
79
+
80
+ ```bash
81
+ python examples/hello_pyoco.py
82
+ ```
83
+
84
+ Output:
85
+
86
+ ```
87
+ 🐇 pyoco > start flow=hello_pyoco
88
+ 🏃 start node=fetch_data
89
+ 🐰 Fetching data...
90
+ ✅ done node=fetch_data (0.30 ms)
91
+ 🏃 start node=process_data
92
+ 🥕 Processing: carrot
93
+ ✅ done node=process_data (0.23 ms)
94
+ 🏃 start node=save_result
95
+ ✨ Saved: CARROT
96
+ ✅ done node=save_result (0.30 ms)
97
+ 🥕 done flow=hello_pyoco
98
+ ```
99
+
100
+ See [examples/hello_pyoco.py](examples/hello_pyoco.py) for the full code.
101
+
102
+ ## 🏗️ Architecture
103
+
104
+ Pyoco is designed with a simple flow:
105
+
106
+ ```
107
+ +-----------+ +------------------+ +-----------------+
108
+ | User Code | ---> | pyoco.core.Flow | ---> | trace/logger |
109
+ | (Tasks) | | (Engine) | | (Console/File) |
110
+ +-----------+ +------------------+ +-----------------+
111
+ ```
112
+
113
+ 1. **User Code**: You define tasks and flows using Python decorators.
114
+ 2. **Core Engine**: The engine resolves dependencies and executes tasks (in parallel where possible).
115
+ 3. **Trace**: Execution events are sent to the trace backend for logging (cute or plain).
116
+
117
+ ## 🎭 Modes
118
+
119
+ Pyoco has two output modes:
120
+
121
+ - **Cute Mode** (Default): Uses emojis and friendly messages. Best for local development and learning.
122
+ - **Non-Cute Mode**: Plain text logs. Best for CI/CD and production monitoring.
123
+
124
+ You can switch modes using an environment variable:
125
+
126
+ ```bash
127
+ export PYOCO_CUTE=0 # Disable cute mode
128
+ ```
129
+
130
+ Or via CLI flag:
131
+
132
+ ```bash
133
+ pyoco run --non-cute ...
134
+ ```
135
+
136
+ ## 🔭 Observability Bridge (v0.5)
137
+
138
+ - `/metrics` exposes Prometheus counters (`pyoco_runs_total`, `pyoco_runs_in_progress`) and histograms (`pyoco_task_duration_seconds`, `pyoco_run_duration_seconds`). Point Grafana/Prometheus at it to watch pipelines without opening sockets.
139
+ - `/runs` now accepts `status`, `flow`, `limit` query params; `/runs/{id}/logs?tail=100` fetches only the latest snippets for dashboards.
140
+ - Webhook notifications fire when runs COMPLETE/FAIL—configure via `PYOCO_WEBHOOK_*` env vars and forward to Slack or your alerting stack.
141
+ - Import `docs/grafana_pyoco_cute.json` for a lavender/orange starter dashboard (3 panels: in-progress count, completion trend, per-flow latency).
142
+ - 詳細な手順は [docs/observability.md](docs/observability.md) を参照してください。
143
+
144
+ ## 🧩 Plug-ins
145
+
146
+ Need to share domain-specific tasks? Publish an entry point under `pyoco.tasks` and pyoco will auto-load it. See [docs/plugins.md](docs/plugins.md) for the `PluginRegistry` decorator, example `pyproject.toml`, and `pyoco plugins list` CLI helper.
147
+
148
+ ## 📚 Documentation
149
+
150
+ - [Tutorials](docs/tutorial/index.md)
151
+ - [Roadmap](docs/roadmap.md)
152
+
153
+ ## 💖 Contributing
154
+
155
+ We love contributions! Please feel free to submit a Pull Request.
156
+
157
+ ---
158
+
159
+ *Made with 🥕 by the Pyoco Team.*
pyoco-0.5.0/README.md ADDED
@@ -0,0 +1,147 @@
1
+ # 🐇 Pyoco
2
+
3
+ **pyoco is a minimal, pure-Python DAG engine for defining and running simple task-based workflows.**
4
+
5
+ ## Overview
6
+
7
+ Pyoco is designed to be significantly smaller, lighter, and have fewer dependencies than full-scale workflow engines like Airflow. It is optimized for local development and single-machine execution.
8
+
9
+ You can define tasks and their dependencies entirely in Python code using decorators and a simple API. There is no need for complex configuration files or external databases.
10
+
11
+ It is ideal for small jobs, development environments, and personal projects where a full-stack workflow engine would be overkill.
12
+
13
+ ## ✨ Features
14
+
15
+ - **Pure Python**: No external services or heavy dependencies required.
16
+ - **Minimal DAG model**: Tasks and dependencies are defined directly in code.
17
+ - **Task-oriented**: Focus on "small workflows" that should be easy to read and maintain.
18
+ - **Friendly trace logs**: Runs can be traced step by step from the terminal with cute (or plain) logs.
19
+ - **Parallel Execution**: Automatically runs independent tasks in parallel.
20
+ - **Artifact Management**: Easily save and manage task outputs and files.
21
+ - **Observability**: Track execution with unique Run IDs and detailed state transitions.
22
+ - **Control**: Cancel running workflows gracefully with `Ctrl+C`.
23
+
24
+ ## 📦 Installation
25
+
26
+ ```bash
27
+ pip install pyoco
28
+ ```
29
+
30
+ ## 🚀 Usage
31
+
32
+ Here is a minimal example of a pure-Python workflow.
33
+
34
+ ```python
35
+ from pyoco import task
36
+ from pyoco.core.models import Flow
37
+ from pyoco.core.engine import Engine
38
+
39
+ @task
40
+ def fetch_data(ctx):
41
+ print("🐰 Fetching data...")
42
+ return {"id": 1, "value": "carrot"}
43
+
44
+ @task
45
+ def process_data(ctx, data):
46
+ print(f"🥕 Processing: {data['value']}")
47
+ return data['value'].upper()
48
+
49
+ @task
50
+ def save_result(ctx, result):
51
+ print(f"✨ Saved: {result}")
52
+
53
+ # Define the flow
54
+ flow = Flow(name="hello_pyoco")
55
+ flow >> fetch_data >> process_data >> save_result
56
+
57
+ # Wire inputs (explicitly for this example)
58
+ process_data.task.inputs = {"data": "$node.fetch_data.output"}
59
+ save_result.task.inputs = {"result": "$node.process_data.output"}
60
+
61
+ if __name__ == "__main__":
62
+ engine = Engine()
63
+ engine.run(flow)
64
+ ```
65
+
66
+ Run it:
67
+
68
+ ```bash
69
+ python examples/hello_pyoco.py
70
+ ```
71
+
72
+ Output:
73
+
74
+ ```
75
+ 🐇 pyoco > start flow=hello_pyoco
76
+ 🏃 start node=fetch_data
77
+ 🐰 Fetching data...
78
+ ✅ done node=fetch_data (0.30 ms)
79
+ 🏃 start node=process_data
80
+ 🥕 Processing: carrot
81
+ ✅ done node=process_data (0.23 ms)
82
+ 🏃 start node=save_result
83
+ ✨ Saved: CARROT
84
+ ✅ done node=save_result (0.30 ms)
85
+ 🥕 done flow=hello_pyoco
86
+ ```
87
+
88
+ See [examples/hello_pyoco.py](examples/hello_pyoco.py) for the full code.
89
+
90
+ ## 🏗️ Architecture
91
+
92
+ Pyoco is designed with a simple flow:
93
+
94
+ ```
95
+ +-----------+ +------------------+ +-----------------+
96
+ | User Code | ---> | pyoco.core.Flow | ---> | trace/logger |
97
+ | (Tasks) | | (Engine) | | (Console/File) |
98
+ +-----------+ +------------------+ +-----------------+
99
+ ```
100
+
101
+ 1. **User Code**: You define tasks and flows using Python decorators.
102
+ 2. **Core Engine**: The engine resolves dependencies and executes tasks (in parallel where possible).
103
+ 3. **Trace**: Execution events are sent to the trace backend for logging (cute or plain).
104
+
105
+ ## 🎭 Modes
106
+
107
+ Pyoco has two output modes:
108
+
109
+ - **Cute Mode** (Default): Uses emojis and friendly messages. Best for local development and learning.
110
+ - **Non-Cute Mode**: Plain text logs. Best for CI/CD and production monitoring.
111
+
112
+ You can switch modes using an environment variable:
113
+
114
+ ```bash
115
+ export PYOCO_CUTE=0 # Disable cute mode
116
+ ```
117
+
118
+ Or via CLI flag:
119
+
120
+ ```bash
121
+ pyoco run --non-cute ...
122
+ ```
123
+
124
+ ## 🔭 Observability Bridge (v0.5)
125
+
126
+ - `/metrics` exposes Prometheus counters (`pyoco_runs_total`, `pyoco_runs_in_progress`) and histograms (`pyoco_task_duration_seconds`, `pyoco_run_duration_seconds`). Point Grafana/Prometheus at it to watch pipelines without opening sockets.
127
+ - `/runs` now accepts `status`, `flow`, `limit` query params; `/runs/{id}/logs?tail=100` fetches only the latest snippets for dashboards.
128
+ - Webhook notifications fire when runs COMPLETE/FAIL—configure via `PYOCO_WEBHOOK_*` env vars and forward to Slack or your alerting stack.
129
+ - Import `docs/grafana_pyoco_cute.json` for a lavender/orange starter dashboard (3 panels: in-progress count, completion trend, per-flow latency).
130
+ - 詳細な手順は [docs/observability.md](docs/observability.md) を参照してください。
131
+
132
+ ## 🧩 Plug-ins
133
+
134
+ Need to share domain-specific tasks? Publish an entry point under `pyoco.tasks` and pyoco will auto-load it. See [docs/plugins.md](docs/plugins.md) for the `PluginRegistry` decorator, example `pyproject.toml`, and `pyoco plugins list` CLI helper.
135
+
136
+ ## 📚 Documentation
137
+
138
+ - [Tutorials](docs/tutorial/index.md)
139
+ - [Roadmap](docs/roadmap.md)
140
+
141
+ ## 💖 Contributing
142
+
143
+ We love contributions! Please feel free to submit a Pull Request.
144
+
145
+ ---
146
+
147
+ *Made with 🥕 by the Pyoco Team.*
@@ -0,0 +1,20 @@
1
+ [project]
2
+ name = "pyoco"
3
+ version = "0.5.0"
4
+ description = "A workflow engine with sugar syntax"
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ dependencies = [
8
+ "pyyaml>=6.0.3",
9
+ "fastapi>=0.100.0",
10
+ "uvicorn>=0.20.0",
11
+ "httpx>=0.24.0",
12
+ "prometheus-client>=0.20.0",
13
+ ]
14
+
15
+ [dependency-groups]
16
+ dev = [
17
+ "pytest>=9.0.1",
18
+ "socketless-http>=0.1.0",
19
+ "pytest-asyncio>=0.23.0",
20
+ ]