dataloom-engine 0.3.0__tar.gz → 0.4.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 (36) hide show
  1. dataloom_engine-0.4.0/PKG-INFO +214 -0
  2. dataloom_engine-0.4.0/README.md +180 -0
  3. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/dataloom_engine/__init__.py +4 -4
  4. dataloom_engine-0.4.0/dataloom_engine/_optional.py +25 -0
  5. dataloom_engine-0.4.0/dataloom_engine/config.py +52 -0
  6. dataloom_engine-0.4.0/dataloom_engine/exceptions.py +25 -0
  7. dataloom_engine-0.4.0/dataloom_engine/hooks.py +50 -0
  8. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/dataloom_engine/logs.py +6 -6
  9. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/dataloom_engine/loom.py +30 -30
  10. dataloom_engine-0.4.0/dataloom_engine/processors.py +53 -0
  11. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/dataloom_engine/sinks.py +35 -35
  12. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/dataloom_engine/sources.py +12 -7
  13. dataloom_engine-0.4.0/dataloom_engine/types.py +18 -0
  14. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/dataloom_engine/weaver.py +17 -16
  15. dataloom_engine-0.4.0/dataloom_engine.egg-info/PKG-INFO +214 -0
  16. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/dataloom_engine.egg-info/SOURCES.txt +2 -0
  17. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/dataloom_engine.egg-info/requires.txt +4 -1
  18. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/pyproject.toml +9 -5
  19. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/tests/test_core.py +29 -29
  20. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/tests/test_loom.py +27 -27
  21. dataloom_engine-0.4.0/tests/test_optional.py +82 -0
  22. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/tests/test_sinks.py +14 -14
  23. dataloom_engine-0.3.0/PKG-INFO +0 -196
  24. dataloom_engine-0.3.0/README.md +0 -164
  25. dataloom_engine-0.3.0/dataloom_engine/config.py +0 -52
  26. dataloom_engine-0.3.0/dataloom_engine/exceptions.py +0 -25
  27. dataloom_engine-0.3.0/dataloom_engine/hooks.py +0 -50
  28. dataloom_engine-0.3.0/dataloom_engine/processors.py +0 -43
  29. dataloom_engine-0.3.0/dataloom_engine/types.py +0 -18
  30. dataloom_engine-0.3.0/dataloom_engine.egg-info/PKG-INFO +0 -196
  31. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/LICENSE +0 -0
  32. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/dataloom_engine/py.typed +0 -0
  33. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/dataloom_engine.egg-info/dependency_links.txt +0 -0
  34. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/dataloom_engine.egg-info/top_level.txt +0 -0
  35. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/setup.cfg +0 -0
  36. {dataloom_engine-0.3.0 → dataloom_engine-0.4.0}/tests/test_config.py +0 -0
@@ -0,0 +1,214 @@
1
+ Metadata-Version: 2.4
2
+ Name: dataloom-engine
3
+ Version: 0.4.0
4
+ Summary: DataLoom: Um orquestrador de threads leve e eficiente para dados.
5
+ Author-email: Dioni Padilha <dionipdl@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/dionipadilha/dataloom
8
+ Project-URL: Changelog, https://github.com/dionipadilha/dataloom/blob/main/CHANGELOG.md
9
+ Project-URL: Issues, https://github.com/dionipadilha/dataloom/issues
10
+ Keywords: pipeline,data,threading,loom,concurrency
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
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
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Provides-Extra: numpy
26
+ Requires-Dist: numpy>=1.21.0; extra == "numpy"
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=7.0; extra == "dev"
29
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
30
+ Requires-Dist: ruff>=0.4; extra == "dev"
31
+ Requires-Dist: mypy>=1.8; extra == "dev"
32
+ Requires-Dist: numpy>=1.21.0; extra == "dev"
33
+ Dynamic: license-file
34
+
35
+ # 🧵 DataLoom
36
+
37
+ > A lightweight, efficient and safe multi-threaded orchestration engine for Python.
38
+
39
+ 🇧🇷 [Versão em português](README.pt-BR.md)
40
+
41
+ [![CI](https://github.com/dionipadilha/dataloom/actions/workflows/ci.yml/badge.svg)](https://github.com/dionipadilha/dataloom/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/dataloom-engine)](https://pypi.org/project/dataloom-engine/) [![Python](https://img.shields.io/pypi/pyversions/dataloom-engine)](https://pypi.org/project/dataloom-engine/) ![License](https://img.shields.io/badge/license-MIT-green)
42
+
43
+ <img width="2752" height="1536" alt="DataLoom: a lightweight, efficient and safe multi-threaded orchestration engine for Python." src="https://github.com/user-attachments/assets/c1f3fc98-5eaf-4add-a38c-2717ae699cd5" />
44
+
45
+ **DataLoom** is a library designed to process data streams using the **Producer-Consumer** pattern with multiple threads (Weavers). It abstracts away the complexity of queues, locks and lifecycle management, letting you focus purely on your data transformation logic.
46
+
47
+ ## Why DataLoom?
48
+ ⚡ Performance: real parallel processing for I/O-bound workloads.
49
+ 🧩 Simplicity: an intuitive API inspired by the weaving metaphor.
50
+ 🛡️ Safety: thread-safety guaranteed by design across the whole pipeline.
51
+ 📦 Lightweight: zero-dependency core, ready to run in any Python environment.
52
+
53
+ ### Why not just `ThreadPoolExecutor`?
54
+
55
+ Fair question — the stdlib solves the *parallelism*, but not the *pipeline*.
56
+ `concurrent.futures` gives you a thread pool; everything around it is on you:
57
+
58
+ | You need... | With the stdlib | With DataLoom |
59
+ | -------------------------------------------------- | --------------------------- | ----------------------------------- |
60
+ | A continuous producer-consumer flow | `Queue` + hand-rolled loops | `Loom` + `Source` |
61
+ | Backpressure (producer faster than consumers) | Manual `Queue(maxsize=...)` | Built-in, configurable |
62
+ | Clean shutdown (drain queue, close resources) | Manual sentinels and joins | `stop()` / `with Loom(...)` |
63
+ | Workers that survive errors and report them | try/except in every worker | Centralized `hooks.on_error` |
64
+ | Per-item processing metrics | Manual instrumentation | `hooks.on_batch_processed` |
65
+ | Safe concurrent file writes | Manual locking | Ready-made sinks (JSON, CSV, callback) |
66
+
67
+ If your use case is "apply a function to a list and collect the results",
68
+ use `ThreadPoolExecutor.map` — it is the right tool. DataLoom is for
69
+ **continuous or long-running flows** where lifecycle, resilience and
70
+ observability matter. And, like every thread-based solution on CPython,
71
+ the parallelism gains apply to **I/O-bound** workloads; for CPU-bound
72
+ work, prefer multiprocessing.
73
+
74
+ ## ✨ Features
75
+
76
+ - **Cohesive API:** aligned concepts (`Loom`, `Weaver`, `Sink`).
77
+ - **Concurrent:** automatically manages multiple _Weavers_ (threads) in parallel.
78
+ - **Safe:** built-in sinks are thread-safe and exceptions are typed (`LoomError`).
79
+ - **Resilient:** processing errors don't kill the Weavers and are reported through hooks.
80
+ - **Manageable:** `Loom` is a context manager — `with Loom(...) as loom:` guarantees automatic `stop()`.
81
+ - **Backpressure:** the task queue is bounded by default (`queue_maxsize`), preventing unbounded memory growth.
82
+ - **Observable:** lifecycle hooks and per-batch metrics (`on_batch_processed` with result and duration), plus built-in logging.
83
+
84
+ ## 📦 Installation
85
+
86
+ ```bash
87
+ pip install dataloom-engine
88
+ ```
89
+
90
+ The engine core has **zero dependencies**. The demo `RandomNumPySource` and
91
+ `StatisticsProcessor` (used in the quick start below) need NumPy, which
92
+ ships as an optional extra:
93
+
94
+ ```bash
95
+ pip install "dataloom-engine[numpy]"
96
+ ```
97
+
98
+ > ⚠️ **Mind the name:** the package installs the `dataloom_engine` module
99
+ > (`import dataloom_engine`). Don't confuse it with the `dataloom` package
100
+ > on PyPI, which is an ORM by another author and unrelated to this project.
101
+
102
+ To develop or use the latest version from the repository:
103
+
104
+ ```bash
105
+ git clone https://github.com/dionipadilha/dataloom.git
106
+ cd dataloom
107
+ pip install -e .
108
+ ```
109
+
110
+ ## 🚀 Quick Start
111
+
112
+ Here is a complete example of weaving a data pipeline:
113
+
114
+ ```python
115
+ from pathlib import Path
116
+ import numpy as np
117
+ from dataloom_engine import (
118
+ Loom,
119
+ LoomConfig,
120
+ LoomLogs,
121
+ Processor,
122
+ JsonFileSink,
123
+ ThreadedBufferedSink
124
+ )
125
+ from dataloom_engine.sources import RandomNumPySource
126
+
127
+ # 1. Define your processing logic (stateless)
128
+ class MyFilterProcessor(Processor):
129
+ def process(self, batch: np.ndarray) -> dict:
130
+ # 'batch' is a numpy array sized according to the config
131
+ avg = float(batch.mean())
132
+ return {
133
+ "processed_items": len(batch),
134
+ "average_value": avg,
135
+ "status": "high" if avg > 0.5 else "low"
136
+ }
137
+
138
+ # 2. Initial setup
139
+ if __name__ == "__main__":
140
+ # Configure console logging
141
+ LoomLogs.setup()
142
+
143
+ # Engine parameters
144
+ config = LoomConfig(
145
+ output_dir=Path("./data_out"),
146
+ batch_size=100, # Process 100 items at a time
147
+ interval_seconds=1 # Produce a new batch every second
148
+ )
149
+
150
+ # 3. Data source
151
+ # Decoupled from the engine, enabling custom sources (DB, CSV, S3)
152
+ source = RandomNumPySource(config)
153
+
154
+ # 4. Buffered file sink
155
+ # ThreadedBufferedSink keeps I/O from blocking the processing
156
+ file_sink = JsonFileSink(config.output_dir)
157
+ sink = ThreadedBufferedSink(file_sink)
158
+
159
+ # 5. Initialize the Loom (the orchestrator)
160
+ loom = Loom(
161
+ config=config,
162
+ processor=MyFilterProcessor(),
163
+ sink=sink,
164
+ source=source,
165
+ num_weavers=4 # 4 threads working in parallel
166
+ )
167
+
168
+ print("🧵 DataLoom started! Press Ctrl+C to stop.")
169
+ try:
170
+ # The context manager guarantees stop() and resource cleanup,
171
+ # even on exceptions or Ctrl+C
172
+ with loom:
173
+ loom.start()
174
+ except KeyboardInterrupt:
175
+ print("\n🛑 Loom stopped.")
176
+ ```
177
+
178
+ ## 🏗️ Architecture
179
+
180
+ DataLoom is built around a weaving metaphor:
181
+
182
+ - **Loom:** the main machine. Manages the task queue and the lifecycle.
183
+ - **Weaver:** the worker threads. They take the raw material (a batch), process it and deliver it.
184
+ - **Processor:** the business logic. Turns raw data into information.
185
+ - **Sink:** the final destination. Where the finished product is deposited (e.g. `JsonFileSink`, `CsvFileSink`, or any destination via `CallbackSink`).
186
+
187
+ ## 🛠️ Development and Testing
188
+
189
+ To contribute to the project or run the test suite:
190
+
191
+ 1. Install the development dependencies:
192
+
193
+ ```bash
194
+ pip install -e ".[dev]"
195
+ ```
196
+
197
+ 2. Run the test suite (via pytest):
198
+ ```bash
199
+ pytest
200
+ ```
201
+
202
+ 3. Run the linter and type checker:
203
+ ```bash
204
+ ruff check .
205
+ mypy
206
+ ```
207
+
208
+ ## 📄 License
209
+
210
+ This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
211
+
212
+ ## 🗒️ Version History
213
+
214
+ Changes in each release are documented in the [CHANGELOG](CHANGELOG.md).
@@ -0,0 +1,180 @@
1
+ # 🧵 DataLoom
2
+
3
+ > A lightweight, efficient and safe multi-threaded orchestration engine for Python.
4
+
5
+ 🇧🇷 [Versão em português](README.pt-BR.md)
6
+
7
+ [![CI](https://github.com/dionipadilha/dataloom/actions/workflows/ci.yml/badge.svg)](https://github.com/dionipadilha/dataloom/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/dataloom-engine)](https://pypi.org/project/dataloom-engine/) [![Python](https://img.shields.io/pypi/pyversions/dataloom-engine)](https://pypi.org/project/dataloom-engine/) ![License](https://img.shields.io/badge/license-MIT-green)
8
+
9
+ <img width="2752" height="1536" alt="DataLoom: a lightweight, efficient and safe multi-threaded orchestration engine for Python." src="https://github.com/user-attachments/assets/c1f3fc98-5eaf-4add-a38c-2717ae699cd5" />
10
+
11
+ **DataLoom** is a library designed to process data streams using the **Producer-Consumer** pattern with multiple threads (Weavers). It abstracts away the complexity of queues, locks and lifecycle management, letting you focus purely on your data transformation logic.
12
+
13
+ ## Why DataLoom?
14
+ ⚡ Performance: real parallel processing for I/O-bound workloads.
15
+ 🧩 Simplicity: an intuitive API inspired by the weaving metaphor.
16
+ 🛡️ Safety: thread-safety guaranteed by design across the whole pipeline.
17
+ 📦 Lightweight: zero-dependency core, ready to run in any Python environment.
18
+
19
+ ### Why not just `ThreadPoolExecutor`?
20
+
21
+ Fair question — the stdlib solves the *parallelism*, but not the *pipeline*.
22
+ `concurrent.futures` gives you a thread pool; everything around it is on you:
23
+
24
+ | You need... | With the stdlib | With DataLoom |
25
+ | -------------------------------------------------- | --------------------------- | ----------------------------------- |
26
+ | A continuous producer-consumer flow | `Queue` + hand-rolled loops | `Loom` + `Source` |
27
+ | Backpressure (producer faster than consumers) | Manual `Queue(maxsize=...)` | Built-in, configurable |
28
+ | Clean shutdown (drain queue, close resources) | Manual sentinels and joins | `stop()` / `with Loom(...)` |
29
+ | Workers that survive errors and report them | try/except in every worker | Centralized `hooks.on_error` |
30
+ | Per-item processing metrics | Manual instrumentation | `hooks.on_batch_processed` |
31
+ | Safe concurrent file writes | Manual locking | Ready-made sinks (JSON, CSV, callback) |
32
+
33
+ If your use case is "apply a function to a list and collect the results",
34
+ use `ThreadPoolExecutor.map` — it is the right tool. DataLoom is for
35
+ **continuous or long-running flows** where lifecycle, resilience and
36
+ observability matter. And, like every thread-based solution on CPython,
37
+ the parallelism gains apply to **I/O-bound** workloads; for CPU-bound
38
+ work, prefer multiprocessing.
39
+
40
+ ## ✨ Features
41
+
42
+ - **Cohesive API:** aligned concepts (`Loom`, `Weaver`, `Sink`).
43
+ - **Concurrent:** automatically manages multiple _Weavers_ (threads) in parallel.
44
+ - **Safe:** built-in sinks are thread-safe and exceptions are typed (`LoomError`).
45
+ - **Resilient:** processing errors don't kill the Weavers and are reported through hooks.
46
+ - **Manageable:** `Loom` is a context manager — `with Loom(...) as loom:` guarantees automatic `stop()`.
47
+ - **Backpressure:** the task queue is bounded by default (`queue_maxsize`), preventing unbounded memory growth.
48
+ - **Observable:** lifecycle hooks and per-batch metrics (`on_batch_processed` with result and duration), plus built-in logging.
49
+
50
+ ## 📦 Installation
51
+
52
+ ```bash
53
+ pip install dataloom-engine
54
+ ```
55
+
56
+ The engine core has **zero dependencies**. The demo `RandomNumPySource` and
57
+ `StatisticsProcessor` (used in the quick start below) need NumPy, which
58
+ ships as an optional extra:
59
+
60
+ ```bash
61
+ pip install "dataloom-engine[numpy]"
62
+ ```
63
+
64
+ > ⚠️ **Mind the name:** the package installs the `dataloom_engine` module
65
+ > (`import dataloom_engine`). Don't confuse it with the `dataloom` package
66
+ > on PyPI, which is an ORM by another author and unrelated to this project.
67
+
68
+ To develop or use the latest version from the repository:
69
+
70
+ ```bash
71
+ git clone https://github.com/dionipadilha/dataloom.git
72
+ cd dataloom
73
+ pip install -e .
74
+ ```
75
+
76
+ ## 🚀 Quick Start
77
+
78
+ Here is a complete example of weaving a data pipeline:
79
+
80
+ ```python
81
+ from pathlib import Path
82
+ import numpy as np
83
+ from dataloom_engine import (
84
+ Loom,
85
+ LoomConfig,
86
+ LoomLogs,
87
+ Processor,
88
+ JsonFileSink,
89
+ ThreadedBufferedSink
90
+ )
91
+ from dataloom_engine.sources import RandomNumPySource
92
+
93
+ # 1. Define your processing logic (stateless)
94
+ class MyFilterProcessor(Processor):
95
+ def process(self, batch: np.ndarray) -> dict:
96
+ # 'batch' is a numpy array sized according to the config
97
+ avg = float(batch.mean())
98
+ return {
99
+ "processed_items": len(batch),
100
+ "average_value": avg,
101
+ "status": "high" if avg > 0.5 else "low"
102
+ }
103
+
104
+ # 2. Initial setup
105
+ if __name__ == "__main__":
106
+ # Configure console logging
107
+ LoomLogs.setup()
108
+
109
+ # Engine parameters
110
+ config = LoomConfig(
111
+ output_dir=Path("./data_out"),
112
+ batch_size=100, # Process 100 items at a time
113
+ interval_seconds=1 # Produce a new batch every second
114
+ )
115
+
116
+ # 3. Data source
117
+ # Decoupled from the engine, enabling custom sources (DB, CSV, S3)
118
+ source = RandomNumPySource(config)
119
+
120
+ # 4. Buffered file sink
121
+ # ThreadedBufferedSink keeps I/O from blocking the processing
122
+ file_sink = JsonFileSink(config.output_dir)
123
+ sink = ThreadedBufferedSink(file_sink)
124
+
125
+ # 5. Initialize the Loom (the orchestrator)
126
+ loom = Loom(
127
+ config=config,
128
+ processor=MyFilterProcessor(),
129
+ sink=sink,
130
+ source=source,
131
+ num_weavers=4 # 4 threads working in parallel
132
+ )
133
+
134
+ print("🧵 DataLoom started! Press Ctrl+C to stop.")
135
+ try:
136
+ # The context manager guarantees stop() and resource cleanup,
137
+ # even on exceptions or Ctrl+C
138
+ with loom:
139
+ loom.start()
140
+ except KeyboardInterrupt:
141
+ print("\n🛑 Loom stopped.")
142
+ ```
143
+
144
+ ## 🏗️ Architecture
145
+
146
+ DataLoom is built around a weaving metaphor:
147
+
148
+ - **Loom:** the main machine. Manages the task queue and the lifecycle.
149
+ - **Weaver:** the worker threads. They take the raw material (a batch), process it and deliver it.
150
+ - **Processor:** the business logic. Turns raw data into information.
151
+ - **Sink:** the final destination. Where the finished product is deposited (e.g. `JsonFileSink`, `CsvFileSink`, or any destination via `CallbackSink`).
152
+
153
+ ## 🛠️ Development and Testing
154
+
155
+ To contribute to the project or run the test suite:
156
+
157
+ 1. Install the development dependencies:
158
+
159
+ ```bash
160
+ pip install -e ".[dev]"
161
+ ```
162
+
163
+ 2. Run the test suite (via pytest):
164
+ ```bash
165
+ pytest
166
+ ```
167
+
168
+ 3. Run the linter and type checker:
169
+ ```bash
170
+ ruff check .
171
+ mypy
172
+ ```
173
+
174
+ ## 📄 License
175
+
176
+ This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
177
+
178
+ ## 🗒️ Version History
179
+
180
+ Changes in each release are documented in the [CHANGELOG](CHANGELOG.md).
@@ -1,11 +1,11 @@
1
1
  # dataloom_engine/__init__.py
2
2
 
3
3
  """
4
- DataLoom: Um motor de orquestração multi-thread leve e eficiente.
4
+ DataLoom: a lightweight and efficient multi-threaded orchestration engine.
5
5
 
6
- Este módulo expõe a API pública do pacote. Observe que classes internas
7
- como 'Weaver' não são expostas propositalmente, mantendo a superfície
8
- de uso limpa e segura para o consumidor.
6
+ This module exposes the package's public API. Note that internal classes
7
+ such as 'Weaver' are deliberately not exposed, keeping the usage surface
8
+ clean and safe for consumers.
9
9
  """
10
10
 
11
11
  from dataloom_engine.config import LoomConfig
@@ -0,0 +1,25 @@
1
+ # dataloom_engine/_optional.py
2
+
3
+ """
4
+ Helpers for optional dependencies.
5
+ The engine core has no third-party requirements; the demo implementations
6
+ that need one import it lazily through these helpers, so that a missing
7
+ dependency fails fast with an actionable message.
8
+ """
9
+
10
+ from types import ModuleType
11
+
12
+
13
+ def require_numpy(feature: str) -> ModuleType:
14
+ """
15
+ Returns the numpy module, or raises an informative ImportError if the
16
+ optional dependency is not installed.
17
+ """
18
+ try:
19
+ import numpy
20
+ except ImportError as exc:
21
+ raise ImportError(
22
+ f"{feature} requires numpy, which is an optional dependency of "
23
+ 'dataloom-engine. Install it with: pip install "dataloom-engine[numpy]"'
24
+ ) from exc
25
+ return numpy
@@ -0,0 +1,52 @@
1
+ # dataloom_engine/config.py
2
+
3
+ """
4
+ Orchestrator configuration management.
5
+ Centralizes operational parameters such as directories and batch sizes.
6
+ """
7
+
8
+ from dataclasses import dataclass
9
+ from pathlib import Path
10
+ from typing import Optional, Union
11
+
12
+ from dataloom_engine.exceptions import ConfigurationError
13
+
14
+
15
+ @dataclass
16
+ class LoomConfig:
17
+ """
18
+ DataLoom's main configuration object.
19
+
20
+ Args:
21
+ output_dir (Path): Base directory where the built-in Sinks save data.
22
+ Strings are converted to Path automatically.
23
+ batch_size (int): Number of items produced per processing cycle.
24
+ interval_seconds (float): Time interval between task generations.
25
+ queue_maxsize (Optional[int]): Maximum capacity of the task queue
26
+ (backpressure). None uses the Loom default (num_weavers * 4);
27
+ 0 means an unbounded queue.
28
+
29
+ Raises:
30
+ ConfigurationError: if any parameter is invalid.
31
+ """
32
+
33
+ output_dir: Union[str, Path]
34
+ batch_size: int = 10
35
+ interval_seconds: float = 1.0
36
+ queue_maxsize: Optional[int] = None
37
+
38
+ def __post_init__(self) -> None:
39
+ self.output_dir = Path(self.output_dir)
40
+
41
+ if self.batch_size <= 0:
42
+ raise ConfigurationError(
43
+ f"batch_size must be greater than zero (got: {self.batch_size})."
44
+ )
45
+ if self.interval_seconds < 0:
46
+ raise ConfigurationError(
47
+ f"interval_seconds cannot be negative (got: {self.interval_seconds})."
48
+ )
49
+ if self.queue_maxsize is not None and self.queue_maxsize < 0:
50
+ raise ConfigurationError(
51
+ f"queue_maxsize cannot be negative (got: {self.queue_maxsize})."
52
+ )
@@ -0,0 +1,25 @@
1
+ # dataloom_engine/exceptions.py
2
+
3
+ """
4
+ Custom exceptions for DataLoom.
5
+ Lets consumers catch library-specific errors without relying on
6
+ generic Python exceptions.
7
+ """
8
+
9
+
10
+ class LoomError(Exception):
11
+ """Base exception for every DataLoom error."""
12
+
13
+ pass
14
+
15
+
16
+ class ConfigurationError(LoomError):
17
+ """Raised when LoomConfig validation fails."""
18
+
19
+ pass
20
+
21
+
22
+ class WeaverError(LoomError):
23
+ """Raised when a Weaver fails to process a batch."""
24
+
25
+ pass
@@ -0,0 +1,50 @@
1
+ # dataloom_engine/hooks.py
2
+
3
+ """
4
+ Observability extension points (Hooks).
5
+ Lets you inject monitoring logic without coupling it to the engine core.
6
+ """
7
+
8
+ from typing import Any, Dict
9
+
10
+
11
+ class LoomHooks:
12
+ """
13
+ Base class for lifecycle hooks.
14
+ Every method is optional and a no-op by default: override only the
15
+ points you care about. (Deliberately not an ABC — there is no method
16
+ you are required to implement.)
17
+ """
18
+
19
+ def on_start(self) -> None:
20
+ """Called right before the Weavers are started."""
21
+ pass
22
+
23
+ def on_stop(self) -> None:
24
+ """Called after the orchestrator shuts down gracefully."""
25
+ pass
26
+
27
+ def on_error(self, error: Exception) -> None:
28
+ """
29
+ Called when an exception occurs in the Loom's main loop or while
30
+ processing a batch inside a Weaver (WeaverError).
31
+
32
+ Note: it may be invoked from multiple Weaver threads at the same
33
+ time — implementations must be thread-safe.
34
+ """
35
+ pass
36
+
37
+ def on_batch_processed(self, result: Dict[str, Any], duration_seconds: float) -> None:
38
+ """
39
+ Called after each batch is processed and delivered to the Sink.
40
+
41
+ Args:
42
+ result: The dictionary produced by the Processor for the batch.
43
+ duration_seconds: Time spent in process() + send(), measured
44
+ with a monotonic clock.
45
+
46
+ Note: like on_error, this is invoked from the Weaver threads —
47
+ implementations must be thread-safe and fast, since they run on
48
+ the pipeline's hot path.
49
+ """
50
+ pass
@@ -1,8 +1,8 @@
1
1
  # dataloom_engine/logs.py
2
2
 
3
3
  """
4
- Utilitários de configuração de logging para o DataLoom.
5
- Fornece um namespace estático para configuração rápida.
4
+ Logging configuration utilities for DataLoom.
5
+ Provides a static namespace for quick setup.
6
6
  """
7
7
 
8
8
  import logging
@@ -10,16 +10,16 @@ import logging
10
10
 
11
11
  class LoomLogs:
12
12
  """
13
- Namespace utilitário para gerenciamento de logs do DataLoom.
14
- Não deve ser instanciado, apenas usado estaticamente.
13
+ Utility namespace for DataLoom log management.
14
+ Not meant to be instantiated use it statically.
15
15
  """
16
16
 
17
17
  @staticmethod
18
18
  def setup(level: int = logging.INFO) -> None:
19
19
  """
20
- Configura o logging básico para stdout.
20
+ Configures basic logging to stdout.
21
21
 
22
- Uso:
22
+ Usage:
23
23
  LoomLogs.setup(level=logging.DEBUG)
24
24
  """
25
25
  logging.basicConfig(