dataloom-engine 0.6.0__tar.gz → 0.7.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 (28) hide show
  1. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/PKG-INFO +47 -1
  2. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/README.md +45 -0
  3. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine.egg-info/PKG-INFO +47 -1
  4. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/pyproject.toml +7 -6
  5. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/LICENSE +0 -0
  6. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine/__init__.py +0 -0
  7. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine/_optional.py +0 -0
  8. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine/config.py +0 -0
  9. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine/exceptions.py +0 -0
  10. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine/hooks.py +0 -0
  11. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine/logs.py +0 -0
  12. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine/loom.py +0 -0
  13. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine/processors.py +0 -0
  14. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine/py.typed +0 -0
  15. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine/sinks.py +0 -0
  16. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine/sources.py +0 -0
  17. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine/types.py +0 -0
  18. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine/weaver.py +0 -0
  19. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine.egg-info/SOURCES.txt +0 -0
  20. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine.egg-info/dependency_links.txt +0 -0
  21. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine.egg-info/requires.txt +0 -0
  22. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/dataloom_engine.egg-info/top_level.txt +0 -0
  23. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/setup.cfg +0 -0
  24. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/tests/test_config.py +0 -0
  25. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/tests/test_core.py +0 -0
  26. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/tests/test_loom.py +0 -0
  27. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/tests/test_optional.py +0 -0
  28. {dataloom_engine-0.6.0 → dataloom_engine-0.7.0}/tests/test_sinks.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dataloom-engine
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: DataLoom: a lightweight and efficient thread orchestration engine for data pipelines.
5
5
  Author-email: Dioni Padilha <dionipdl@gmail.com>
6
6
  License: MIT
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.10
17
17
  Classifier: Programming Language :: Python :: 3.11
18
18
  Classifier: Programming Language :: Python :: 3.12
19
19
  Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
20
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
22
  Classifier: Typing :: Typed
22
23
  Requires-Python: >=3.9
@@ -188,6 +189,51 @@ DataLoom is built around a weaving metaphor:
188
189
  - **Processor:** the business logic. Turns raw data into information.
189
190
  - **Sink:** the final destination. Where the finished product is deposited (e.g. `JsonFileSink`, `CsvFileSink`, or any destination via `CallbackSink`).
190
191
 
192
+ ## 🧶 Threading model
193
+
194
+ Knowing which thread runs each extension point is what makes writing
195
+ safe Processors, Sinks and Hooks straightforward:
196
+
197
+ | Your code | Runs on |
198
+ | ---------------------------------------------- | ------------------------------------------------ |
199
+ | `Source.__iter__` | the thread that called `loom.start()` (producer) |
200
+ | `Processor.process` / `Sink.send` | the Weaver threads, **concurrently** |
201
+ | `hooks.on_error` / `hooks.on_batch_processed` | the Weaver threads, **concurrently** |
202
+ | `hooks.on_start` / `hooks.on_stop` / `Sink.close` | the thread that called `start()` / `stop()` |
203
+
204
+ Practical consequences:
205
+
206
+ - **Processors and Sinks must be thread-safe** if they touch shared
207
+ state (the built-in sinks are; `CallbackSink` callables must be).
208
+ - **Hooks run on the hot path**: keep `on_batch_processed` fast and
209
+ thread-safe.
210
+ - **Shutdown semantics:** `stop()` (or leaving the `with` block) drains
211
+ the items already queued, then joins the Weavers — pass
212
+ `stop(timeout=...)` to bound the wait. A pipeline whose source was
213
+ exhausted ends as `COMPLETED`; an interrupted one (external `stop()`,
214
+ `Ctrl+C`) ends as `STOPPED`; a source error ends as `FAILED`.
215
+
216
+ ## 📊 Benchmarks
217
+
218
+ Reproducible, zero-dependency benchmarks live in
219
+ [`benchmarks/throughput.py`](benchmarks/throughput.py):
220
+
221
+ ```bash
222
+ python benchmarks/throughput.py
223
+ ```
224
+
225
+ Reference numbers from a 4-vCPU Linux container (treat them as an order
226
+ of magnitude — run it on your own hardware):
227
+
228
+ | Scenario | Result |
229
+ | ------------------------------------------ | ---------------- |
230
+ | I/O-bound, 200 items × 10ms, 8 weavers | **7.8x** speedup over sequential |
231
+ | No-op processor (pure engine overhead) | ~51,000 items/s (~20µs per item) |
232
+
233
+ The rule of thumb the second number gives you: if your per-item work
234
+ costs less than ~20µs, a plain loop beats any orchestration — DataLoom
235
+ pays off when each item does real I/O or meaningful work.
236
+
191
237
  ## 🛠️ Development and Testing
192
238
 
193
239
  To contribute to the project or run the test suite:
@@ -154,6 +154,51 @@ DataLoom is built around a weaving metaphor:
154
154
  - **Processor:** the business logic. Turns raw data into information.
155
155
  - **Sink:** the final destination. Where the finished product is deposited (e.g. `JsonFileSink`, `CsvFileSink`, or any destination via `CallbackSink`).
156
156
 
157
+ ## 🧶 Threading model
158
+
159
+ Knowing which thread runs each extension point is what makes writing
160
+ safe Processors, Sinks and Hooks straightforward:
161
+
162
+ | Your code | Runs on |
163
+ | ---------------------------------------------- | ------------------------------------------------ |
164
+ | `Source.__iter__` | the thread that called `loom.start()` (producer) |
165
+ | `Processor.process` / `Sink.send` | the Weaver threads, **concurrently** |
166
+ | `hooks.on_error` / `hooks.on_batch_processed` | the Weaver threads, **concurrently** |
167
+ | `hooks.on_start` / `hooks.on_stop` / `Sink.close` | the thread that called `start()` / `stop()` |
168
+
169
+ Practical consequences:
170
+
171
+ - **Processors and Sinks must be thread-safe** if they touch shared
172
+ state (the built-in sinks are; `CallbackSink` callables must be).
173
+ - **Hooks run on the hot path**: keep `on_batch_processed` fast and
174
+ thread-safe.
175
+ - **Shutdown semantics:** `stop()` (or leaving the `with` block) drains
176
+ the items already queued, then joins the Weavers — pass
177
+ `stop(timeout=...)` to bound the wait. A pipeline whose source was
178
+ exhausted ends as `COMPLETED`; an interrupted one (external `stop()`,
179
+ `Ctrl+C`) ends as `STOPPED`; a source error ends as `FAILED`.
180
+
181
+ ## 📊 Benchmarks
182
+
183
+ Reproducible, zero-dependency benchmarks live in
184
+ [`benchmarks/throughput.py`](benchmarks/throughput.py):
185
+
186
+ ```bash
187
+ python benchmarks/throughput.py
188
+ ```
189
+
190
+ Reference numbers from a 4-vCPU Linux container (treat them as an order
191
+ of magnitude — run it on your own hardware):
192
+
193
+ | Scenario | Result |
194
+ | ------------------------------------------ | ---------------- |
195
+ | I/O-bound, 200 items × 10ms, 8 weavers | **7.8x** speedup over sequential |
196
+ | No-op processor (pure engine overhead) | ~51,000 items/s (~20µs per item) |
197
+
198
+ The rule of thumb the second number gives you: if your per-item work
199
+ costs less than ~20µs, a plain loop beats any orchestration — DataLoom
200
+ pays off when each item does real I/O or meaningful work.
201
+
157
202
  ## 🛠️ Development and Testing
158
203
 
159
204
  To contribute to the project or run the test suite:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dataloom-engine
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: DataLoom: a lightweight and efficient thread orchestration engine for data pipelines.
5
5
  Author-email: Dioni Padilha <dionipdl@gmail.com>
6
6
  License: MIT
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.10
17
17
  Classifier: Programming Language :: Python :: 3.11
18
18
  Classifier: Programming Language :: Python :: 3.12
19
19
  Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
20
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
22
  Classifier: Typing :: Typed
22
23
  Requires-Python: >=3.9
@@ -188,6 +189,51 @@ DataLoom is built around a weaving metaphor:
188
189
  - **Processor:** the business logic. Turns raw data into information.
189
190
  - **Sink:** the final destination. Where the finished product is deposited (e.g. `JsonFileSink`, `CsvFileSink`, or any destination via `CallbackSink`).
190
191
 
192
+ ## 🧶 Threading model
193
+
194
+ Knowing which thread runs each extension point is what makes writing
195
+ safe Processors, Sinks and Hooks straightforward:
196
+
197
+ | Your code | Runs on |
198
+ | ---------------------------------------------- | ------------------------------------------------ |
199
+ | `Source.__iter__` | the thread that called `loom.start()` (producer) |
200
+ | `Processor.process` / `Sink.send` | the Weaver threads, **concurrently** |
201
+ | `hooks.on_error` / `hooks.on_batch_processed` | the Weaver threads, **concurrently** |
202
+ | `hooks.on_start` / `hooks.on_stop` / `Sink.close` | the thread that called `start()` / `stop()` |
203
+
204
+ Practical consequences:
205
+
206
+ - **Processors and Sinks must be thread-safe** if they touch shared
207
+ state (the built-in sinks are; `CallbackSink` callables must be).
208
+ - **Hooks run on the hot path**: keep `on_batch_processed` fast and
209
+ thread-safe.
210
+ - **Shutdown semantics:** `stop()` (or leaving the `with` block) drains
211
+ the items already queued, then joins the Weavers — pass
212
+ `stop(timeout=...)` to bound the wait. A pipeline whose source was
213
+ exhausted ends as `COMPLETED`; an interrupted one (external `stop()`,
214
+ `Ctrl+C`) ends as `STOPPED`; a source error ends as `FAILED`.
215
+
216
+ ## 📊 Benchmarks
217
+
218
+ Reproducible, zero-dependency benchmarks live in
219
+ [`benchmarks/throughput.py`](benchmarks/throughput.py):
220
+
221
+ ```bash
222
+ python benchmarks/throughput.py
223
+ ```
224
+
225
+ Reference numbers from a 4-vCPU Linux container (treat them as an order
226
+ of magnitude — run it on your own hardware):
227
+
228
+ | Scenario | Result |
229
+ | ------------------------------------------ | ---------------- |
230
+ | I/O-bound, 200 items × 10ms, 8 weavers | **7.8x** speedup over sequential |
231
+ | No-op processor (pure engine overhead) | ~51,000 items/s (~20µs per item) |
232
+
233
+ The rule of thumb the second number gives you: if your per-item work
234
+ costs less than ~20µs, a plain loop beats any orchestration — DataLoom
235
+ pays off when each item does real I/O or meaningful work.
236
+
191
237
  ## 🛠️ Development and Testing
192
238
 
193
239
  To contribute to the project or run the test suite:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dataloom-engine"
7
- version = "0.6.0"
7
+ version = "0.7.0"
8
8
  description = "DataLoom: a lightweight and efficient thread orchestration engine for data pipelines."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -23,6 +23,7 @@ classifiers = [
23
23
  "Programming Language :: Python :: 3.11",
24
24
  "Programming Language :: Python :: 3.12",
25
25
  "Programming Language :: Python :: 3.13",
26
+ "Programming Language :: Python :: 3.14",
26
27
  "Topic :: Software Development :: Libraries :: Python Modules",
27
28
  "Typing :: Typed",
28
29
  ]
@@ -68,9 +69,9 @@ select = [
68
69
  "B", # flake8-bugbear
69
70
  ]
70
71
 
71
- # Sem python_version fixo: versões novas do mypy não aceitam mais alvo 3.9,
72
- # e os stubs do numpy exigem alvo >= 3.12. A compatibilidade com 3.9 é
73
- # garantida pela matriz de testes do CI, que executa nessa versão.
72
+ # No pinned python_version: recent mypy releases no longer accept a 3.9
73
+ # target, and the numpy stubs require >= 3.12. Compatibility with 3.9 is
74
+ # guaranteed by the CI test matrix, which runs on that version.
74
75
  [tool.mypy]
75
76
  files = ["dataloom_engine"]
76
77
  check_untyped_defs = true
@@ -78,7 +79,7 @@ warn_redundant_casts = true
78
79
  no_implicit_optional = true
79
80
 
80
81
  [[tool.mypy.overrides]]
81
- # numpy é usado apenas nas implementações de demonstração; ignorar stubs
82
- # ausentes mantém o check estável em ambientes sem os type stubs resolvidos
82
+ # numpy is only used by the demo implementations; ignoring missing stubs
83
+ # keeps the check stable in environments without resolved type stubs
83
84
  module = "numpy.*"
84
85
  ignore_missing_imports = true
File without changes