auto-workflow 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,423 @@
1
+ Metadata-Version: 2.1
2
+ Name: auto-workflow
3
+ Version: 0.1.0
4
+ Summary: A lightweight, developer-first workflow & task orchestration engine for Python.
5
+ Home-page: https://github.com/stoiandl/auto-workflow
6
+ License: GPL-3.0-or-later
7
+ Author: andreistoica
8
+ Author-email: andreilst@yahoo.ro
9
+ Requires-Python: >=3.12,<4.0
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
14
+ Classifier: Programming Language :: Python
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Topic :: Software Development :: Libraries
19
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
20
+ Classifier: Typing :: Typed
21
+ Requires-Dist: cloudpickle (>=3.0.0,<4.0.0)
22
+ Project-URL: Documentation, https://stoiandl.github.io/auto-workflow/
23
+ Project-URL: Repository, https://github.com/stoiandl/auto-workflow
24
+ Description-Content-Type: text/markdown
25
+
26
+ <div align="center">
27
+
28
+ <picture>
29
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/stoiandl/auto-workflow/main/assets/logo.svg" />
30
+ <img alt="auto-workflow" src="https://raw.githubusercontent.com/stoiandl/auto-workflow/main/assets/logo.svg" width="560" />
31
+ </picture>
32
+
33
+ # auto-workflow
34
+
35
+ [![CI](https://github.com/stoiandl/auto-workflow/actions/workflows/ci.yml/badge.svg?branch=main&event=push)](https://github.com/stoiandl/auto-workflow/actions/workflows/ci.yml)
36
+ [![Docs build](https://github.com/stoiandl/auto-workflow/actions/workflows/docs.yml/badge.svg?branch=main&event=push)](https://github.com/stoiandl/auto-workflow/actions/workflows/docs.yml)
37
+ [![Coverage Status](https://img.shields.io/codecov/c/github/stoiandl/auto-workflow/main?logo=codecov&label=coverage)](https://app.codecov.io/gh/stoiandl/auto-workflow)
38
+ [![PyPI](https://img.shields.io/pypi/v/auto-workflow.svg?logo=pypi&label=PyPI)](https://pypi.org/project/auto-workflow/)
39
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/auto-workflow.svg?label=downloads)](https://pypi.org/project/auto-workflow/)
40
+ [![Docs](https://img.shields.io/badge/docs-GitHub%20Pages-blue)](https://stoiandl.github.io/auto-workflow/) [![License: GPLv3](https://img.shields.io/badge/License-GPLv3-blue.svg)](LICENSE)
41
+
42
+ _A lightweight, zero-bloat, developer‑first workflow & task orchestration engine for Python._
43
+
44
+ **Status:** Alpha (APIs stabilizing). **Goal:** Production‑grade minimal core with pluggable power features.
45
+
46
+ </div>
47
+
48
+ ## Quick links
49
+
50
+ - Docs (GitHub Pages): https://stoiandl.github.io/auto-workflow/
51
+ - Repository: https://github.com/stoiandl/auto-workflow
52
+
53
+
54
+ ## Table of Contents
55
+ 1. [Why Another Orchestrator?](#why-another-orchestrator)
56
+ 2. [Philosophy & Design Principles](#philosophy--design-principles)
57
+ 3. [Feature Overview](#feature-overview)
58
+ 4. [Quick Start](#quick-start)
59
+ 5. [Core Concepts](#core-concepts)
60
+ 6. [Execution Modes](#execution-modes)
61
+ 7. [Building Flows & DAGs](#building-flows--dags)
62
+ 8. [Dynamic Fan‑Out / Conditional Branching](#dynamic-fan-out--conditional-branching)
63
+ 9. [Result Handling, Caching & Idempotency](#result-handling-caching--idempotency)
64
+ 10. [Retries, Timeouts & Failure Semantics](#retries-timeouts--failure-semantics)
65
+ 11. [Hooks, Events & Middleware](#hooks-events--middleware)
66
+ 12. [Configuration & Environment](#configuration--environment)
67
+ 13. [Observability (Logging, Metrics, Tracing)](#observability-logging-metrics-tracing)
68
+ 14. [Extensibility Roadmap](#extensibility-roadmap)
69
+ 15. [Security & Isolation Considerations](#security--isolation-considerations)
70
+ 16. [Comparison with Airflow & Prefect](#comparison-with-airflow--prefect)
71
+ 17. [Project Structure (Proposed)](#project-structure-proposed)
72
+ 18. [FAQ](#faq)
73
+ 19. [Roadmap](#roadmap)
74
+ 20. [Contributing](#contributing)
75
+ 21. [Versioning & Stability](#versioning--stability)
76
+ 22. [License](#license)
77
+ 23. [Examples Overview](#examples-overview)
78
+
79
+
80
+ ## Why Another Orchestrator?
81
+ Existing platforms (Airflow, Prefect, Dagster, Luigi) solve orchestration at scale—but often at the cost of:
82
+
83
+
84
+ `auto-workflow` targets a different sweet spot:
85
+
86
+ > **Be the simplest way to express, execute and evolve complex, dynamic task graphs directly in Python—locally first—while remaining extensible to production constraints.**
87
+
88
+ Core values: **No mandatory DB**, **no daemon**, **no CLI bureaucracy**, **opt‑in persistence**, **first-class async**, **predictable concurrency**, **explicit data flow**.
89
+
90
+
91
+ ## Philosophy & Design Principles
92
+ | Principle | Description |
93
+ |-----------|-------------|
94
+ | Minimal Core | Ship only primitives: Task, Flow (DAG), Executor, Runtime. Everything else is a plugin or optional layer. |
95
+ | Python Native | Flows are plain Python; no YAML DSL or templating required. |
96
+ | Deterministic by Default | Task graph shape should be reproducible given the same inputs. Explicit APIs for dynamic fan‑out. |
97
+ | Composable | Tasks are small units; flows can nest; subgraphs are reusable. |
98
+ | Extensible | Storage adapters, retry policies, and event sinks are pluggable via clean interfaces. |
99
+ | Progressive Adoption | Use it as a simple task runner first; layer complexity only when needed. |
100
+ | Observability Hooks | Logging / metrics / tracing surfaces are unified and optional. |
101
+ | Zero Hidden State | No implicit global registry; registration is explicit or decorator‑driven with clear import semantics. |
102
+ | Performance Conscious | Support high‑throughput local pipelines via async & thread/process pools with minimal overhead. |
103
+
104
+
105
+ ## Feature Overview
106
+ Planned / partially implemented capabilities:
107
+
108
+
109
+
110
+ ## Quick Start
111
+ Install from PyPI:
112
+
113
+ ```bash
114
+ pip install auto-workflow
115
+ ```
116
+
117
+ Or for local development with Poetry:
118
+
119
+ Run tests locally:
120
+
121
+ ```bash
122
+ poetry run pytest --cov=auto_workflow --cov-report=term-missing
123
+ ```
124
+
125
+ ### Define Tasks
126
+ ```python
127
+ from auto_workflow import task, flow
128
+
129
+ @task
130
+ def load_numbers() -> list[int]:
131
+ return [1, 2, 3, 4]
132
+
133
+ @task
134
+ def square(x: int) -> int:
135
+ return x * x
136
+
137
+ @task
138
+ def aggregate(values: list[int]) -> int:
139
+ return sum(values)
140
+
141
+ @flow
142
+ def pipeline():
143
+ nums = load_numbers()
144
+ # Fan-out map (dynamic child tasks)
145
+ squared = [square(n) for n in nums] # Under the hood becomes dynamic tasks
146
+ return aggregate(squared)
147
+
148
+ if __name__ == "__main__":
149
+ result = pipeline.run()
150
+ print(result)
151
+ ```
152
+
153
+ ### CLI
154
+ ```bash
155
+ python -m auto_workflow run path.to.pipeline:pipeline
156
+ ```
157
+
158
+ List and describe flows:
159
+
160
+ ```bash
161
+ python -m auto_workflow list path.to.module
162
+ python -m auto_workflow describe path.to.pipeline:pipeline
163
+ ```
164
+
165
+ If installed via pip, a console script is also available:
166
+
167
+ ```bash
168
+ auto-workflow run path.to.pipeline:pipeline
169
+ ```
170
+
171
+
172
+ ## Core Concepts
173
+ ### Task
174
+ Unit of work: a pure (or side-effecting) Python callable that declares inputs & returns outputs. Decorated with `@task` for metadata: name, retries, timeout, tags, cache key fn.
175
+
176
+ ### Flow (or Pipeline)
177
+ Container for a DAG of tasks. May be defined with `@flow` decorator wrapping a function whose body builds the dependency graph during invocation. Supports nested flows.
178
+
179
+ ### DAG
180
+ Directed acyclic graph where edges represent data or control dependencies. Construction is implicit via using outputs of tasks as inputs to other tasks (like Prefect) but without global mutable state.
181
+
182
+ ### Execution Context
183
+ Available via `from auto_workflow.context import get_context()` inside a task for run metadata, logger, parameters.
184
+
185
+ ### Parameters
186
+ Flow-level runtime parameters passed at `.run(params={...})` enabling configurability without environment variables.
187
+
188
+ ### Artifacts
189
+ Structured results (maybe large) that can optionally be stored externally; default is in‑memory pass‑through.
190
+
191
+
192
+ ## Execution Modes
193
+ Tasks run using one of three simple modes:
194
+
195
+ Mode selection:
196
+
197
+
198
+ ## Building Flows & DAGs
199
+ Two equivalent approaches (both may be supported):
200
+
201
+ 1. **Imperative Functional** (Python execution builds nodes):
202
+ ```python
203
+ @flow
204
+ def my_flow():
205
+ a = task_a()
206
+ b = task_b(a)
207
+ c = task_c(a, b)
208
+ return c
209
+ ```
210
+ 2. **Explicit Builder** (defer evaluation):
211
+ ```python
212
+ from auto_workflow import FlowBuilder
213
+ fb = FlowBuilder(name="my_flow")
214
+ a = fb.task(task_a)
215
+ b = fb.task(task_b, a)
216
+ c = fb.task(task_c, a, b)
217
+ flow = fb.build()
218
+ flow.run()
219
+ ```
220
+
221
+
222
+ ## Dynamic Fan-Out / Conditional Branching
223
+ Dynamic forks are explicit to preserve introspection & safety:
224
+ ```python
225
+ @task
226
+ def split_batches(data: list[int]) -> list[list[int]]: ...
227
+
228
+ @task
229
+ def process_batch(batch: list[int]) -> int: ...
230
+
231
+ @task
232
+ def combine(results: list[int]) -> int: return sum(results)
233
+
234
+ @flow
235
+ def batch_flow(data: list[int]):
236
+ batches = split_batches(data)
237
+ results = fan_out(process_batch, iterable=batches, max_concurrency=8)
238
+ return combine(results)
239
+
240
+ @flow
241
+ def conditional_flow(flag: bool):
242
+ a = task_a()
243
+ if flag:
244
+ b = task_b(a)
245
+ else:
246
+ b = task_c(a)
247
+ return b
248
+ ```
249
+ `fan_out` constructs a bounded dynamic subgraph; a future `fan_in` utility may allow explicit barrier semantics.
250
+
251
+
252
+ ## Result Handling, Caching & Idempotency
253
+ Strategies (planned):
254
+
255
+ Example (concept):
256
+ ```python
257
+ @task(cache_ttl=3600)
258
+ def expensive(x: int) -> int:
259
+ return do_work(x)
260
+ ```
261
+
262
+
263
+ ## Retries, Timeouts & Failure Semantics
264
+ Per-task configuration:
265
+ ```python
266
+ @task(retries=3, retry_backoff=2.0, retry_jitter=0.3, timeout=30)
267
+ def flaky(): ...
268
+ ```
269
+ Failure policy options (proposed):
270
+
271
+
272
+ ## Hooks, Events & Middleware
273
+ Lifecycle hook points:
274
+
275
+ Middleware chain (similar to ASGI / HTTP frameworks):
276
+ ```python
277
+ def timing_middleware(next_call):
278
+ async def wrapper(task_ctx):
279
+ start = monotonic()
280
+ try:
281
+ return await next_call(task_ctx)
282
+ finally:
283
+ duration = monotonic() - start
284
+ task_ctx.logger.debug("task.duration", extra={"ms": duration*1000})
285
+ return wrapper
286
+ ```
287
+
288
+ Event bus emission (planned): structured events -> pluggable sinks (stdout logger, OTLP exporter, WebSocket UI).
289
+
290
+
291
+ ## Configuration & Environment
292
+ Minimal first-class configuration (future `pyproject.toml` block):
293
+ ```toml
294
+ [tool.auto_workflow]
295
+ default-executor = "async"
296
+ log-level = "INFO"
297
+ max-dynamic-tasks = 2048
298
+ ```
299
+ Environment overrides are available for documented keys (see docs/configuration.md).
300
+
301
+
302
+ ## Observability (Logging, Metrics, Tracing)
303
+ Implemented surface + extensions you can plug in:
304
+
305
+
306
+ ## Extensibility Roadmap
307
+ | Extension | Interface | Status |
308
+ |-----------|-----------|--------|
309
+ | Executor plugins | `BaseExecutor` | Planned |
310
+ | Storage backend | `ArtifactStore` | Planned |
311
+ | Cache backend | `ResultCache` | Planned |
312
+ | Metrics provider | `MetricsProvider` | Planned |
313
+ | Tracing adapter | `Tracer` | Planned |
314
+ | Retry policy | Strategy object | Planned |
315
+ | Scheduling layer | External module | Backlog |
316
+ | UI / API | Optional service | Backlog |
317
+
318
+
319
+ ## Security & Isolation Considerations
320
+
321
+
322
+ ## Comparison with Airflow & Prefect
323
+ | Aspect | auto-workflow | Airflow | Prefect |
324
+ |--------|---------------|---------|---------|
325
+ | Requires DB / Scheduler | No (local in-process) | Yes | No (cloud optional) |
326
+ | First-class async | Yes (core) | Limited | Yes |
327
+ | Dynamic DAG at runtime | Explicit fan-out | Limited / brittle | Supported |
328
+ | Footprint | Minimal deps | Heavy | Moderate |
329
+ | UI bundled | No (optional) | Yes | Yes |
330
+ | Plugin surface | Lean, Pythonic | Large | Large |
331
+ | Setup time | Seconds | Minutes+ | Minutes |
332
+
333
+
334
+ ## Project Structure (Proposed)
335
+ ```
336
+ auto_workflow/
337
+ __init__.py
338
+ tasks.py # @task decorator & Task definition
339
+ flow.py # Flow abstraction & @flow decorator
340
+ dag.py # Internal DAG model
341
+ execution.py
342
+ base.py
343
+ async_executor.py
344
+ thread_executor.py
345
+ runtime/
346
+ context.py
347
+ scheduler.py # Lightweight topological / async scheduler
348
+ middleware/
349
+ events/
350
+ caching/
351
+ storage/
352
+ observability/
353
+ tests/
354
+ examples/
355
+ docs/
356
+ ```
357
+
358
+
359
+ ## FAQ
360
+ **Q: Is persistence required?** No—default run is ephemeral in memory.
361
+
362
+ **Q: Can I dynamically create thousands of tasks?** Yes, but bounded; guardrails (`max-dynamic-tasks`) will protect runaway expansion.
363
+
364
+ **Q: How are circular dependencies prevented?** DAG builder performs cycle detection before execution.
365
+
366
+ **Q: Do I need decorators?** No; you can manually wrap callables into Tasks if you prefer pure functional style.
367
+
368
+ **Q: How does it serialize arguments across processes?** Planned fallback: cloudpickle; user can register custom serializer.
369
+
370
+ **Q: Scheduling / cron?** Out of core scope—provide a thin adapter so external schedulers (cron, systemd timers, GitHub Actions) can invoke flows.
371
+
372
+
373
+ ## Roadmap
374
+
375
+
376
+ ## Examples Overview
377
+ Explore runnable examples in `examples/` (also rendered in the online docs):
378
+
379
+ | File | Concept Highlights |
380
+ |------|--------------------|
381
+ | `data_pipeline.py` | Basic ETL flow with persistence & simple mapping |
382
+ | `concurrent_priority.py` | Priority scheduling & mixed async timings |
383
+ | `dynamic_fanout.py` | Runtime fan-out expansion and aggregation |
384
+ | `retries_timeouts.py` | Retry + timeout interplay demonstration |
385
+ | `secrets_and_artifacts.py` | Secrets provider & artifact persistence usage |
386
+ | `tracing_custom.py` | Custom tracer capturing spans & durations |
387
+
388
+ Run any example:
389
+ ```bash
390
+ python examples/tracing_custom.py
391
+ ```
392
+
393
+ For more narrative documentation see the [Examples page](https://stoiandl.github.io/auto-workflow/examples/).
394
+
395
+
396
+ ## Contributing
397
+ Contributions are welcome once the core API draft solidifies. Until then:
398
+ 1. Open an issue to discuss proposals.
399
+ 2. Keep changes atomic & well-tested.
400
+ 3. Adhere to Ruff formatting & lint rules (pre-commit enforced).
401
+ 4. Add or update examples & docs for new features.
402
+
403
+ Planned contribution guides: `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`.
404
+
405
+
406
+ ## Versioning & Stability
407
+ Pre-1.0: **Breaking changes can occur in minor releases**. After 1.0 we will follow [Semantic Versioning](https://semver.org/).
408
+
409
+ Migration notes will be maintained in `CHANGELOG.md` (to be added).
410
+
411
+
412
+ ## License
413
+ This project is licensed under the GNU General Public License v3.0. See `LICENSE` for details. If you need alternate licensing, open an issue to discuss.
414
+
415
+
416
+ ## Legal / Disclaimer
417
+ This project is experimental; do not deploy to critical production paths until a 1.0 release is tagged. Feedback welcomed to refine design decisions.
418
+
419
+
420
+ Happy orchestrating! 🚀
421
+
422
+ Note on releases: Publishing to PyPI is performed by CI when a tag `vX.Y.Z` is pushed to the repository. We use PyPI Trusted Publishing; no local uploads are required.
423
+
@@ -0,0 +1,31 @@
1
+ assets/logo.svg,sha256=rqCM-kp_z5gZOdUD4jXoVRNADYRx9oNhNPII6saGEgI,338305
2
+ auto_workflow/__init__.py,sha256=dIlETObkeObo--97_IltqY_a-SGiVZ1OsxMHS-AEKt8,1207
3
+ auto_workflow/__main__.py,sha256=2eElgytBmJuifQ4kycddgmZ-L9Bc5AL0xylbjaub_M0,219
4
+ auto_workflow/artifacts.py,sha256=r6QxfRDbZaakeNH1KnIeZ0Z0iSAqshhLZW9wz7hWurI,3519
5
+ auto_workflow/build.py,sha256=FDKWMACNeCU2oDeBHF5GkPZk_-CFmLbkfVXP9GIeMeI,5262
6
+ auto_workflow/cache.py,sha256=fOh2swSiFPUPcEAdoi6A3Kar5o_t_1Uiby-WxFcS0Zg,3534
7
+ auto_workflow/cli.py,sha256=JMocusDbL3m9T_z2PphjauaH7BCMmmxd4ObjZkH0AkM,2632
8
+ auto_workflow/config.py,sha256=tBGTs6QD32uQkrybnMxOM4b83PWIymO-pHGT4GVzIHQ,2377
9
+ auto_workflow/context.py,sha256=bkCzU9M-wMpM0yxcOj8U3FB4343fDYb-AWQUcjsT2L0,848
10
+ auto_workflow/dag.py,sha256=RNb8rUvModscqPmFhSastuyiQtkdpxPXsmWeZS1azQU,2668
11
+ auto_workflow/events.py,sha256=7rfLP5e0k3o2XcOe0F7BWRlqEZjxqK0hRflf2ggF__Q,650
12
+ auto_workflow/exceptions.py,sha256=mcMJfKfDXPDh2qtiamyr5q0VQAUWYenQ4A0iOVsr8Es,1187
13
+ auto_workflow/execution.py,sha256=_-BaznbjCCaMo5T7vCuXzlMtS_jYiMzi-AdVvJs-Z9U,1358
14
+ auto_workflow/fanout.py,sha256=s-9J5pDnV8fJV2pyzVcI7gyfPOwBHm210ZcHyuWGUF4,1943
15
+ auto_workflow/flow.py,sha256=TyIdJcBJ8FLNIl6BV75AqswpzGrUz6mYQW2uxP5WFxE,5918
16
+ auto_workflow/lifecycle.py,sha256=8zwmu9JoRzcndWSFu1TU_JOKIqlUieWo-rMq93p3NuI,413
17
+ auto_workflow/logging_middleware.py,sha256=os_Km_vMImlYwSfWISSErm0fgxJBmydDgvJynE5X9AA,5693
18
+ auto_workflow/metrics_provider.py,sha256=tZoleZumkvdjGdTWcRjiFADkc2i-45Z5AkLhQD2OyP4,1010
19
+ auto_workflow/middleware.py,sha256=_NAufUTDb_HG0Q-G6McCn8cvpB7Dcy1JR2rgRZxpmjM,1741
20
+ auto_workflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ auto_workflow/scheduler.py,sha256=OPlDHjWzak93H1lbomx22GhO-FlSQ6TOkzKEghk-00A,16474
22
+ auto_workflow/secrets.py,sha256=8_F7taMkT0yo4Ztl17m5YkSWAI7HJP70bfZt2Ai9Ry4,1168
23
+ auto_workflow/task.py,sha256=SWWOku4oN1pQU2hGHDlaU09wgsbGOnRifyO14ir5-EE,5562
24
+ auto_workflow/tracing.py,sha256=UH6pQbnrXJpF59XcvsRRiNPKzgtP9pkVeR9YKXD0Ihk,619
25
+ auto_workflow/types.py,sha256=2C-SBNG9YQNqw6nApOXatDsmkBRF0oBxm2jsSEbYAs8,538
26
+ auto_workflow/utils.py,sha256=sWu303zJR5vz6ncP-zXTxpR6q97N8dZRt22ZxhwRI0c,1186
27
+ auto_workflow-0.1.0.dist-info/LICENSE,sha256=0R_K7rXirniQSUGGNOLY97m7rCIyrb8C05mycpAV6FY,35072
28
+ auto_workflow-0.1.0.dist-info/METADATA,sha256=YEJ0L_henh9PEa5wj4dvxzvXKfEL4F_5FOAVqI4mk7Q,14411
29
+ auto_workflow-0.1.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
30
+ auto_workflow-0.1.0.dist-info/entry_points.txt,sha256=7De4UkwX05DfQ3E4b3qvB9m2ovW4mSsO1qRUcxjWERo,56
31
+ auto_workflow-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 1.9.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ auto-workflow=auto_workflow.cli:main
3
+