datacrease 1.0.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.
- datacrease-1.0.0/LICENSE +21 -0
- datacrease-1.0.0/PKG-INFO +251 -0
- datacrease-1.0.0/README.md +223 -0
- datacrease-1.0.0/pyproject.toml +63 -0
- datacrease-1.0.0/setup.cfg +4 -0
- datacrease-1.0.0/src/datacrease/__init__.py +58 -0
- datacrease-1.0.0/src/datacrease/audit.py +145 -0
- datacrease-1.0.0/src/datacrease/buffer.py +148 -0
- datacrease-1.0.0/src/datacrease/checker.py +156 -0
- datacrease-1.0.0/src/datacrease/cli.py +266 -0
- datacrease-1.0.0/src/datacrease/config.py +22 -0
- datacrease-1.0.0/src/datacrease/exceptions.py +59 -0
- datacrease-1.0.0/src/datacrease/hash_guard.py +134 -0
- datacrease-1.0.0/src/datacrease/iron.py +535 -0
- datacrease-1.0.0/src/datacrease/models.py +133 -0
- datacrease-1.0.0/src/datacrease/pipeline.py +226 -0
- datacrease-1.0.0/src/datacrease/stream.py +167 -0
- datacrease-1.0.0/src/datacrease.egg-info/PKG-INFO +251 -0
- datacrease-1.0.0/src/datacrease.egg-info/SOURCES.txt +31 -0
- datacrease-1.0.0/src/datacrease.egg-info/dependency_links.txt +1 -0
- datacrease-1.0.0/src/datacrease.egg-info/entry_points.txt +2 -0
- datacrease-1.0.0/src/datacrease.egg-info/requires.txt +4 -0
- datacrease-1.0.0/src/datacrease.egg-info/top_level.txt +1 -0
- datacrease-1.0.0/tests/test_audit.py +110 -0
- datacrease-1.0.0/tests/test_benchmarks.py +235 -0
- datacrease-1.0.0/tests/test_buffer.py +153 -0
- datacrease-1.0.0/tests/test_checker.py +130 -0
- datacrease-1.0.0/tests/test_cli.py +165 -0
- datacrease-1.0.0/tests/test_error_codes.py +158 -0
- datacrease-1.0.0/tests/test_hash_guard.py +125 -0
- datacrease-1.0.0/tests/test_iron.py +316 -0
- datacrease-1.0.0/tests/test_pipeline.py +128 -0
- datacrease-1.0.0/tests/test_stream.py +195 -0
datacrease-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DataCrease Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: datacrease
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Das deterministische Bügeleisen an Daten-Kupplungen: Sanitization, Hash-Guard, Pufferung und Audit-Trails.
|
|
5
|
+
Author: DataCrease Contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/datacrease/datacrease
|
|
8
|
+
Project-URL: Repository, https://github.com/datacrease/datacrease
|
|
9
|
+
Project-URL: Issues, https://github.com/datacrease/datacrease/issues
|
|
10
|
+
Keywords: data-quality,sanitization,data-cleansing,hash-guard,audit-trail,zero-dependency,streaming,data-pipeline
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
20
|
+
Classifier: Topic :: Utilities
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-benchmark>=4.0.0; extra == "dev"
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
# DataCrease 🧺⚡ (Das Daten-Bügeleisen)
|
|
30
|
+
|
|
31
|
+
> **"Lieber 2 Millisekunden Glättung an der Schnittstelle investieren, als ein gecrashtes Folgesystem im Nachgang."**
|
|
32
|
+
|
|
33
|
+
[](LICENSE)
|
|
34
|
+
[]()
|
|
35
|
+
[]()
|
|
36
|
+
[]()
|
|
37
|
+
[]()
|
|
38
|
+
[]()
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 🎯 Elevator Pitch
|
|
43
|
+
|
|
44
|
+
**DataCrease** ist ein kompromisslos schnelles, deterministisches Python-Toolkit für **Data-Sanitization, Ingestion-Pufferung, kryptografische Unveränderlichkeit und lückenlose Audit-Trails** direkt an Daten-Kupplungen (APIs, Webhooks, Microservices, LLM-Tools, IoT-Streams).
|
|
45
|
+
|
|
46
|
+
Herkömmliche Validatoren wie Pydantic werfen beim kleinsten Whitespace-Fehler oder Formatbruch sofort harte Exceptions (*Fail-Fast*), während Datenanalyse-Tools wie Pandas für Echtzeit-Kupplungen viel zu schwergewichtig sind.
|
|
47
|
+
|
|
48
|
+
**DataCrease wählt den dritten Weg:**
|
|
49
|
+
Anstatt Schnittstellen crashen zu lassen, bügelt DataCrease typischen Datenmüll (unsichtbare Steuerzeichen, chaotische Whitespaces, deutsche/US-Zahlenformate, unbereinigte Datumsangaben, Trennlinien) in **unter 0,2 Millisekunden** deterministisch glatt, prüft Schwellenwerte, versiegelt jeden Datensatz mit einem manipulationssicheren **SHA-256 Receipt** und absorbiert Lastspitzen über einen integrierten Ring-Puffer – **zu 100% in purem Python und ohne eine einzige externe Dependency**.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## ⚡ Kernfunktionen
|
|
54
|
+
|
|
55
|
+
- 🧺 **The Iron (Deterministischer Glätter):** Bereinigt Unicode-NFC, entfernt unsichtbare ASCII-Steuerzeichen (0–31, 127), normalisiert Zahlen (EU/US, Währungssymbole, Tausendertrenner), vereinheitlicht Datumsformate deterministisch auf ISO-8601 UTC und bügelt Trennmüll (`strip_decorations`).
|
|
56
|
+
- 🛡️ **The Checker & CreaseErrorCode:** Typisierte Integer-Fehlercodes (`CreaseErrorCode` 1xx–4xx) für intuitive IDE-Autovervollständigung (`if CreaseErrorCode.MISSING_REQUIRED_FIELD in result.error_codes`), Schwellenwerte, Whitelists und ReDoS-sichere Regex-Prüfungen.
|
|
57
|
+
- 🔒 **The Hash-Guard:** Kanonische deterministische JSON-Serialisierung und Ausstellung manipulationssicherer `Receipt`-Objekte mit SHA-256-Prüfsummen für Vorher/Nachher-Lineage und Latenz-Tracking.
|
|
58
|
+
- 🌊 **O(1) Memory Streaming:** Lazy Generator (`process_stream`, `process_file`) zur speicherschonenden Verarbeitung gigabytegroßer JSONL-Dateien inklusive automatischer Filterung von Strukturmüll (`DROPPED_JUNK_LINE`).
|
|
59
|
+
- 🔍 **Dry-Run & Inspect-Modus:** Risikofreie Datenprüfung via `iron.inspect()` oder `datacrease check --dry-run` ohne Mutation der Originaldaten.
|
|
60
|
+
- 🚨 **Präzise Diagnostik:** Typisierte `DataCreaseCorruptPayloadError`-Exceptions mit exakter Zeilennummer, Byte-Offset und Quellcode-Ausschnitt bei korruptem JSON.
|
|
61
|
+
- 🗄️ **Ring-Buffer & JSONL-Audit:** Thread-sicherer FIFO-Puffer mit konfigurierbaren Überlauf-Strategien (`DROP_OLDEST`, `REJECT_NEWEST`, `RAISE_ERROR`) und atomarer Append-Only JSONL-Audit-Logger.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 📊 Differenzierungsmatrix
|
|
66
|
+
|
|
67
|
+
| Kriterium | Pydantic / Marshmallow | Pandas / Polars | Great Expectations | **DataCrease** |
|
|
68
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
69
|
+
| **Philosophie bei Schmutz** | Wirft Exceptions (`ValidationError`) | Erfordert manuelle Vorbereinigung | Meldet Fehler ex-post im Batch | **Bügelt Schmutz deterministisch glatt** |
|
|
70
|
+
| **Audit-Trail & Lineage** | ❌ Nein | ❌ Nein | ⚠️ Nur Testberichte | ✅ **Kryptografischer Hash-Guard (SHA-256)** |
|
|
71
|
+
| **Burst-Pufferung** | ❌ Nein | ❌ Nein | ❌ Nein | ✅ **In-Memory Ring-Buffer integriert** |
|
|
72
|
+
| **Fehler-Diagnostik** | Textmeldungen | Index-Fehler | Suite-Reports | ✅ **Typisierte `CreaseErrorCode` (1xx–4xx)** |
|
|
73
|
+
| **Latenz pro Record** | Mikrosekunden | Hoch (>500ms Import/Batch) | Schwergewicht (Sekunden) | ✅ **P50: 193 µs / P99: 340 µs** |
|
|
74
|
+
| **Memory Footprint** | Mittel | Hoch (RAM-Kopien) | Hoch | ✅ **$O(1)$ Memory Streaming** |
|
|
75
|
+
| **Dependencies & Ballast** | Rust/C-Bindings | Schwer (>100 MB) | Sehr schwer (>50 Pakete) | ✅ **Zero External Dependencies** |
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 📈 Benchmark-Ergebnisse (10.000 Records E2E)
|
|
80
|
+
|
|
81
|
+
Gemessen auf dem vollständigen Durchlauf (`Iron` $\to$ `Checker` $\to$ `HashGuard` $\to$ atomarer `AuditLogger`):
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
=================================================================
|
|
85
|
+
--- DATACREASE BENCHMARK: 10.000 RECORDS DURCH DIE E2E-SCHLEUSE ---
|
|
86
|
+
=================================================================
|
|
87
|
+
Gesamtdauer: 5.323 Sekunden
|
|
88
|
+
Durchsatz: 1.879 Records / Sekunde
|
|
89
|
+
Ø Latenz: 201.3 µs (0.201 ms)
|
|
90
|
+
Median (P50): 193 µs (0.193 ms)
|
|
91
|
+
90. Perzentil (P90): 247 µs (0.247 ms)
|
|
92
|
+
99. Perzentil (P99): 340 µs (0.340 ms)
|
|
93
|
+
Budget-Limit: 2.000 µs (2.000 ms) --> 5,9x schneller als das Limit!
|
|
94
|
+
=================================================================
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
- **Fuzzing-Schredder:** 5.000 böswillig formatierte Datensätze (Zero-Width Spaces, unsichtbare ASCII-Steuerzeichen, extremes Whitespace-Chaos, ungültige Datumsangaben, NaN/Infinity-Strings) $\to$ **0 Crashes / 0 ungefangene Exceptions**.
|
|
98
|
+
- **Concurrency-Stresstest:** 3.000 Records über parallele Worker-Threads auf RingBuffer und Pipeline $\to$ **0 Deadlocks, 0 Race Conditions**.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 📦 Installation
|
|
103
|
+
|
|
104
|
+
DataCrease benötigt Python 3.10 oder höher und hat **keine externen Abhängigkeiten**:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
pip install datacrease
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Oder direkt aus dem Repository:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
git clone https://github.com/datacrease/datacrease.git
|
|
114
|
+
cd datacrease
|
|
115
|
+
pip install .
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 🚀 Quickstart: Python API
|
|
121
|
+
|
|
122
|
+
### 1. Grundlegende Pipeline-Schleuse
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
from datacrease import DataCrease, Iron, Checker, Status, CreaseErrorCode
|
|
126
|
+
|
|
127
|
+
# 1. Pipeline konfigurieren
|
|
128
|
+
pipeline = DataCrease(
|
|
129
|
+
iron=Iron(locale_hint="EU", collapse_whitespace=True),
|
|
130
|
+
checker=Checker(
|
|
131
|
+
required_fields=["id", "device_id"],
|
|
132
|
+
numeric_ranges={"temperature": (-40.0, 85.0)},
|
|
133
|
+
regex_rules={"device_id": r"^DEV-\d{3}$"}
|
|
134
|
+
),
|
|
135
|
+
schema_hints={"temperature": "number", "timestamp": "date"}
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
# 2. Unsauberer Rohdaten-Eingang
|
|
139
|
+
raw_record = {
|
|
140
|
+
"id": " 1001 ",
|
|
141
|
+
"device_id": " DEV-042 \n",
|
|
142
|
+
"temperature": " 21,50 °C ",
|
|
143
|
+
"timestamp": " 15.09.2026 18:02:47 ",
|
|
144
|
+
"notes": " N/A "
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
# 3. Durch die Schleuse schleusen
|
|
148
|
+
res = pipeline.process(raw_record)
|
|
149
|
+
|
|
150
|
+
print(res.status) # Status.CLEANED
|
|
151
|
+
print(res.cleaned)
|
|
152
|
+
# {
|
|
153
|
+
# "id": "1001",
|
|
154
|
+
# "device_id": "DEV-042",
|
|
155
|
+
# "temperature": 21.5,
|
|
156
|
+
# "timestamp": "2026-09-15T18:02:47Z",
|
|
157
|
+
# "notes": None
|
|
158
|
+
# }
|
|
159
|
+
|
|
160
|
+
# 4. Kryptografischen Beleg (Receipt) auswerten
|
|
161
|
+
print(res.receipt.sha256_raw) # SHA-256 Prüfsumme des Eingangs
|
|
162
|
+
print(res.receipt.sha256_clean) # SHA-256 Prüfsumme des geglätteten Outputs
|
|
163
|
+
print(f"Dauer: {res.receipt.latency_us} µs")
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### 2. Typisierte Fehlerbehandlung mit `CreaseErrorCode`
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
from datacrease import CreaseErrorCode
|
|
170
|
+
|
|
171
|
+
result = pipeline.process({"temperature": "ungültig"})
|
|
172
|
+
|
|
173
|
+
if result.status == Status.DROPPED:
|
|
174
|
+
if CreaseErrorCode.MISSING_REQUIRED_FIELD in result.error_codes:
|
|
175
|
+
print("Pflichtfeld fehlt!")
|
|
176
|
+
if CreaseErrorCode.UNPARSEABLE_NUMBER in result.error_codes:
|
|
177
|
+
print("Temperaturwert konnte nicht als Zahl interpretiert werden.")
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### 3. $O(1)$-Memory Streaming für große Dateien
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
# Verarbeitet Dateien zeilenweise ohne Speicher-Explosion
|
|
184
|
+
for result in pipeline.process_file("huge_dataset.jsonl", stop_on_first_drop=False):
|
|
185
|
+
if result.status != Status.DROPPED:
|
|
186
|
+
save_to_database(result.cleaned)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### 4. Risikofreier Dry-Run / Inspect-Modus
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
from datacrease import Iron
|
|
193
|
+
|
|
194
|
+
iron = Iron()
|
|
195
|
+
# Ermittelt Modifikationen und Hashes, ohne Daten zu mutieren
|
|
196
|
+
receipt = iron.inspect({"name": " Max Mustermann\r\n", "age": "42 "})
|
|
197
|
+
print(receipt.modifications_count) # 2
|
|
198
|
+
print(receipt.status) # Status.CLEANED
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 💻 CLI-Nutzung
|
|
204
|
+
|
|
205
|
+
DataCrease bietet ein vollwertiges Command-Line-Interface (`datacrease`):
|
|
206
|
+
|
|
207
|
+
### Standard-Verarbeitung
|
|
208
|
+
```bash
|
|
209
|
+
# JSONL-Datei glätten und Audit-Trail mitschreiben
|
|
210
|
+
datacrease input.jsonl -o cleaned.jsonl -a audit.jsonl --summary
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Dry-Run / Inspect
|
|
214
|
+
```bash
|
|
215
|
+
# Vorprüfung ohne Dateien zu verändern (Report über Glättungen & Fehler)
|
|
216
|
+
datacrease check input.jsonl --dry-run
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Unix Pipes & Streaming
|
|
220
|
+
```bash
|
|
221
|
+
# Reines Stdin/Stdout-Streaming mit eingebetteten Receipts
|
|
222
|
+
cat raw_stream.jsonl | datacrease --with-receipts > output.jsonl
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Legacy ASCII-Modus
|
|
226
|
+
```bash
|
|
227
|
+
# Umlaute und Sonderzeichen für Legacy-Systeme transliterieren (ä -> ae, € -> EUR)
|
|
228
|
+
datacrease input.jsonl -o ascii_cleaned.jsonl --ascii-only
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## 🛠️ Entwicklung & Testen
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# Schnelle Dev-Testsuite ausführen (80 Tests in ~0.34s)
|
|
237
|
+
pytest
|
|
238
|
+
|
|
239
|
+
# Isolierte Performance-Benchmarks ausführen (10.000 Records & Fuzzing)
|
|
240
|
+
pytest -m benchmark
|
|
241
|
+
|
|
242
|
+
# Alle Tests inklusive Benchmarks ausführen
|
|
243
|
+
pytest -o addopts=""
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## 📄 Lizenz
|
|
249
|
+
|
|
250
|
+
Lizenziert unter der [MIT-Lizenz](LICENSE) (Haftungsausschluss gemäß "AS IS").
|
|
251
|
+
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# DataCrease 🧺⚡ (Das Daten-Bügeleisen)
|
|
2
|
+
|
|
3
|
+
> **"Lieber 2 Millisekunden Glättung an der Schnittstelle investieren, als ein gecrashtes Folgesystem im Nachgang."**
|
|
4
|
+
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[]()
|
|
7
|
+
[]()
|
|
8
|
+
[]()
|
|
9
|
+
[]()
|
|
10
|
+
[]()
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 🎯 Elevator Pitch
|
|
15
|
+
|
|
16
|
+
**DataCrease** ist ein kompromisslos schnelles, deterministisches Python-Toolkit für **Data-Sanitization, Ingestion-Pufferung, kryptografische Unveränderlichkeit und lückenlose Audit-Trails** direkt an Daten-Kupplungen (APIs, Webhooks, Microservices, LLM-Tools, IoT-Streams).
|
|
17
|
+
|
|
18
|
+
Herkömmliche Validatoren wie Pydantic werfen beim kleinsten Whitespace-Fehler oder Formatbruch sofort harte Exceptions (*Fail-Fast*), während Datenanalyse-Tools wie Pandas für Echtzeit-Kupplungen viel zu schwergewichtig sind.
|
|
19
|
+
|
|
20
|
+
**DataCrease wählt den dritten Weg:**
|
|
21
|
+
Anstatt Schnittstellen crashen zu lassen, bügelt DataCrease typischen Datenmüll (unsichtbare Steuerzeichen, chaotische Whitespaces, deutsche/US-Zahlenformate, unbereinigte Datumsangaben, Trennlinien) in **unter 0,2 Millisekunden** deterministisch glatt, prüft Schwellenwerte, versiegelt jeden Datensatz mit einem manipulationssicheren **SHA-256 Receipt** und absorbiert Lastspitzen über einen integrierten Ring-Puffer – **zu 100% in purem Python und ohne eine einzige externe Dependency**.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## ⚡ Kernfunktionen
|
|
26
|
+
|
|
27
|
+
- 🧺 **The Iron (Deterministischer Glätter):** Bereinigt Unicode-NFC, entfernt unsichtbare ASCII-Steuerzeichen (0–31, 127), normalisiert Zahlen (EU/US, Währungssymbole, Tausendertrenner), vereinheitlicht Datumsformate deterministisch auf ISO-8601 UTC und bügelt Trennmüll (`strip_decorations`).
|
|
28
|
+
- 🛡️ **The Checker & CreaseErrorCode:** Typisierte Integer-Fehlercodes (`CreaseErrorCode` 1xx–4xx) für intuitive IDE-Autovervollständigung (`if CreaseErrorCode.MISSING_REQUIRED_FIELD in result.error_codes`), Schwellenwerte, Whitelists und ReDoS-sichere Regex-Prüfungen.
|
|
29
|
+
- 🔒 **The Hash-Guard:** Kanonische deterministische JSON-Serialisierung und Ausstellung manipulationssicherer `Receipt`-Objekte mit SHA-256-Prüfsummen für Vorher/Nachher-Lineage und Latenz-Tracking.
|
|
30
|
+
- 🌊 **O(1) Memory Streaming:** Lazy Generator (`process_stream`, `process_file`) zur speicherschonenden Verarbeitung gigabytegroßer JSONL-Dateien inklusive automatischer Filterung von Strukturmüll (`DROPPED_JUNK_LINE`).
|
|
31
|
+
- 🔍 **Dry-Run & Inspect-Modus:** Risikofreie Datenprüfung via `iron.inspect()` oder `datacrease check --dry-run` ohne Mutation der Originaldaten.
|
|
32
|
+
- 🚨 **Präzise Diagnostik:** Typisierte `DataCreaseCorruptPayloadError`-Exceptions mit exakter Zeilennummer, Byte-Offset und Quellcode-Ausschnitt bei korruptem JSON.
|
|
33
|
+
- 🗄️ **Ring-Buffer & JSONL-Audit:** Thread-sicherer FIFO-Puffer mit konfigurierbaren Überlauf-Strategien (`DROP_OLDEST`, `REJECT_NEWEST`, `RAISE_ERROR`) und atomarer Append-Only JSONL-Audit-Logger.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 📊 Differenzierungsmatrix
|
|
38
|
+
|
|
39
|
+
| Kriterium | Pydantic / Marshmallow | Pandas / Polars | Great Expectations | **DataCrease** |
|
|
40
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
41
|
+
| **Philosophie bei Schmutz** | Wirft Exceptions (`ValidationError`) | Erfordert manuelle Vorbereinigung | Meldet Fehler ex-post im Batch | **Bügelt Schmutz deterministisch glatt** |
|
|
42
|
+
| **Audit-Trail & Lineage** | ❌ Nein | ❌ Nein | ⚠️ Nur Testberichte | ✅ **Kryptografischer Hash-Guard (SHA-256)** |
|
|
43
|
+
| **Burst-Pufferung** | ❌ Nein | ❌ Nein | ❌ Nein | ✅ **In-Memory Ring-Buffer integriert** |
|
|
44
|
+
| **Fehler-Diagnostik** | Textmeldungen | Index-Fehler | Suite-Reports | ✅ **Typisierte `CreaseErrorCode` (1xx–4xx)** |
|
|
45
|
+
| **Latenz pro Record** | Mikrosekunden | Hoch (>500ms Import/Batch) | Schwergewicht (Sekunden) | ✅ **P50: 193 µs / P99: 340 µs** |
|
|
46
|
+
| **Memory Footprint** | Mittel | Hoch (RAM-Kopien) | Hoch | ✅ **$O(1)$ Memory Streaming** |
|
|
47
|
+
| **Dependencies & Ballast** | Rust/C-Bindings | Schwer (>100 MB) | Sehr schwer (>50 Pakete) | ✅ **Zero External Dependencies** |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 📈 Benchmark-Ergebnisse (10.000 Records E2E)
|
|
52
|
+
|
|
53
|
+
Gemessen auf dem vollständigen Durchlauf (`Iron` $\to$ `Checker` $\to$ `HashGuard` $\to$ atomarer `AuditLogger`):
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
=================================================================
|
|
57
|
+
--- DATACREASE BENCHMARK: 10.000 RECORDS DURCH DIE E2E-SCHLEUSE ---
|
|
58
|
+
=================================================================
|
|
59
|
+
Gesamtdauer: 5.323 Sekunden
|
|
60
|
+
Durchsatz: 1.879 Records / Sekunde
|
|
61
|
+
Ø Latenz: 201.3 µs (0.201 ms)
|
|
62
|
+
Median (P50): 193 µs (0.193 ms)
|
|
63
|
+
90. Perzentil (P90): 247 µs (0.247 ms)
|
|
64
|
+
99. Perzentil (P99): 340 µs (0.340 ms)
|
|
65
|
+
Budget-Limit: 2.000 µs (2.000 ms) --> 5,9x schneller als das Limit!
|
|
66
|
+
=================================================================
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- **Fuzzing-Schredder:** 5.000 böswillig formatierte Datensätze (Zero-Width Spaces, unsichtbare ASCII-Steuerzeichen, extremes Whitespace-Chaos, ungültige Datumsangaben, NaN/Infinity-Strings) $\to$ **0 Crashes / 0 ungefangene Exceptions**.
|
|
70
|
+
- **Concurrency-Stresstest:** 3.000 Records über parallele Worker-Threads auf RingBuffer und Pipeline $\to$ **0 Deadlocks, 0 Race Conditions**.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 📦 Installation
|
|
75
|
+
|
|
76
|
+
DataCrease benötigt Python 3.10 oder höher und hat **keine externen Abhängigkeiten**:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pip install datacrease
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Oder direkt aus dem Repository:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
git clone https://github.com/datacrease/datacrease.git
|
|
86
|
+
cd datacrease
|
|
87
|
+
pip install .
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 🚀 Quickstart: Python API
|
|
93
|
+
|
|
94
|
+
### 1. Grundlegende Pipeline-Schleuse
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from datacrease import DataCrease, Iron, Checker, Status, CreaseErrorCode
|
|
98
|
+
|
|
99
|
+
# 1. Pipeline konfigurieren
|
|
100
|
+
pipeline = DataCrease(
|
|
101
|
+
iron=Iron(locale_hint="EU", collapse_whitespace=True),
|
|
102
|
+
checker=Checker(
|
|
103
|
+
required_fields=["id", "device_id"],
|
|
104
|
+
numeric_ranges={"temperature": (-40.0, 85.0)},
|
|
105
|
+
regex_rules={"device_id": r"^DEV-\d{3}$"}
|
|
106
|
+
),
|
|
107
|
+
schema_hints={"temperature": "number", "timestamp": "date"}
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# 2. Unsauberer Rohdaten-Eingang
|
|
111
|
+
raw_record = {
|
|
112
|
+
"id": " 1001 ",
|
|
113
|
+
"device_id": " DEV-042 \n",
|
|
114
|
+
"temperature": " 21,50 °C ",
|
|
115
|
+
"timestamp": " 15.09.2026 18:02:47 ",
|
|
116
|
+
"notes": " N/A "
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# 3. Durch die Schleuse schleusen
|
|
120
|
+
res = pipeline.process(raw_record)
|
|
121
|
+
|
|
122
|
+
print(res.status) # Status.CLEANED
|
|
123
|
+
print(res.cleaned)
|
|
124
|
+
# {
|
|
125
|
+
# "id": "1001",
|
|
126
|
+
# "device_id": "DEV-042",
|
|
127
|
+
# "temperature": 21.5,
|
|
128
|
+
# "timestamp": "2026-09-15T18:02:47Z",
|
|
129
|
+
# "notes": None
|
|
130
|
+
# }
|
|
131
|
+
|
|
132
|
+
# 4. Kryptografischen Beleg (Receipt) auswerten
|
|
133
|
+
print(res.receipt.sha256_raw) # SHA-256 Prüfsumme des Eingangs
|
|
134
|
+
print(res.receipt.sha256_clean) # SHA-256 Prüfsumme des geglätteten Outputs
|
|
135
|
+
print(f"Dauer: {res.receipt.latency_us} µs")
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 2. Typisierte Fehlerbehandlung mit `CreaseErrorCode`
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
from datacrease import CreaseErrorCode
|
|
142
|
+
|
|
143
|
+
result = pipeline.process({"temperature": "ungültig"})
|
|
144
|
+
|
|
145
|
+
if result.status == Status.DROPPED:
|
|
146
|
+
if CreaseErrorCode.MISSING_REQUIRED_FIELD in result.error_codes:
|
|
147
|
+
print("Pflichtfeld fehlt!")
|
|
148
|
+
if CreaseErrorCode.UNPARSEABLE_NUMBER in result.error_codes:
|
|
149
|
+
print("Temperaturwert konnte nicht als Zahl interpretiert werden.")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 3. $O(1)$-Memory Streaming für große Dateien
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
# Verarbeitet Dateien zeilenweise ohne Speicher-Explosion
|
|
156
|
+
for result in pipeline.process_file("huge_dataset.jsonl", stop_on_first_drop=False):
|
|
157
|
+
if result.status != Status.DROPPED:
|
|
158
|
+
save_to_database(result.cleaned)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### 4. Risikofreier Dry-Run / Inspect-Modus
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
from datacrease import Iron
|
|
165
|
+
|
|
166
|
+
iron = Iron()
|
|
167
|
+
# Ermittelt Modifikationen und Hashes, ohne Daten zu mutieren
|
|
168
|
+
receipt = iron.inspect({"name": " Max Mustermann\r\n", "age": "42 "})
|
|
169
|
+
print(receipt.modifications_count) # 2
|
|
170
|
+
print(receipt.status) # Status.CLEANED
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 💻 CLI-Nutzung
|
|
176
|
+
|
|
177
|
+
DataCrease bietet ein vollwertiges Command-Line-Interface (`datacrease`):
|
|
178
|
+
|
|
179
|
+
### Standard-Verarbeitung
|
|
180
|
+
```bash
|
|
181
|
+
# JSONL-Datei glätten und Audit-Trail mitschreiben
|
|
182
|
+
datacrease input.jsonl -o cleaned.jsonl -a audit.jsonl --summary
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Dry-Run / Inspect
|
|
186
|
+
```bash
|
|
187
|
+
# Vorprüfung ohne Dateien zu verändern (Report über Glättungen & Fehler)
|
|
188
|
+
datacrease check input.jsonl --dry-run
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Unix Pipes & Streaming
|
|
192
|
+
```bash
|
|
193
|
+
# Reines Stdin/Stdout-Streaming mit eingebetteten Receipts
|
|
194
|
+
cat raw_stream.jsonl | datacrease --with-receipts > output.jsonl
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Legacy ASCII-Modus
|
|
198
|
+
```bash
|
|
199
|
+
# Umlaute und Sonderzeichen für Legacy-Systeme transliterieren (ä -> ae, € -> EUR)
|
|
200
|
+
datacrease input.jsonl -o ascii_cleaned.jsonl --ascii-only
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## 🛠️ Entwicklung & Testen
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# Schnelle Dev-Testsuite ausführen (80 Tests in ~0.34s)
|
|
209
|
+
pytest
|
|
210
|
+
|
|
211
|
+
# Isolierte Performance-Benchmarks ausführen (10.000 Records & Fuzzing)
|
|
212
|
+
pytest -m benchmark
|
|
213
|
+
|
|
214
|
+
# Alle Tests inklusive Benchmarks ausführen
|
|
215
|
+
pytest -o addopts=""
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## 📄 Lizenz
|
|
221
|
+
|
|
222
|
+
Lizenziert unter der [MIT-Lizenz](LICENSE) (Haftungsausschluss gemäß "AS IS").
|
|
223
|
+
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "datacrease"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Das deterministische Bügeleisen an Daten-Kupplungen: Sanitization, Hash-Guard, Pufferung und Audit-Trails."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [
|
|
11
|
+
{ name = "DataCrease Contributors" }
|
|
12
|
+
]
|
|
13
|
+
license = "MIT"
|
|
14
|
+
license-files = ["LICENSE"]
|
|
15
|
+
requires-python = ">=3.10"
|
|
16
|
+
dependencies = []
|
|
17
|
+
keywords = [
|
|
18
|
+
"data-quality",
|
|
19
|
+
"sanitization",
|
|
20
|
+
"data-cleansing",
|
|
21
|
+
"hash-guard",
|
|
22
|
+
"audit-trail",
|
|
23
|
+
"zero-dependency",
|
|
24
|
+
"streaming",
|
|
25
|
+
"data-pipeline"
|
|
26
|
+
]
|
|
27
|
+
classifiers = [
|
|
28
|
+
"Development Status :: 5 - Production/Stable",
|
|
29
|
+
"Intended Audience :: Developers",
|
|
30
|
+
"Operating System :: OS Independent",
|
|
31
|
+
"Programming Language :: Python :: 3",
|
|
32
|
+
"Programming Language :: Python :: 3.10",
|
|
33
|
+
"Programming Language :: Python :: 3.11",
|
|
34
|
+
"Programming Language :: Python :: 3.12",
|
|
35
|
+
"Programming Language :: Python :: 3.13",
|
|
36
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
37
|
+
"Topic :: Utilities"
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://github.com/datacrease/datacrease"
|
|
42
|
+
Repository = "https://github.com/datacrease/datacrease"
|
|
43
|
+
Issues = "https://github.com/datacrease/datacrease/issues"
|
|
44
|
+
|
|
45
|
+
[project.optional-dependencies]
|
|
46
|
+
dev = [
|
|
47
|
+
"pytest>=7.0.0",
|
|
48
|
+
"pytest-benchmark>=4.0.0"
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
[project.scripts]
|
|
52
|
+
datacrease = "datacrease.cli:main"
|
|
53
|
+
|
|
54
|
+
[tool.setuptools.packages.find]
|
|
55
|
+
where = ["src"]
|
|
56
|
+
|
|
57
|
+
[tool.pytest.ini_options]
|
|
58
|
+
testpaths = ["tests"]
|
|
59
|
+
pythonpath = ["src"]
|
|
60
|
+
markers = [
|
|
61
|
+
"benchmark: marks tests as heavy performance benchmarks (deselect with '-m \"not benchmark\"')"
|
|
62
|
+
]
|
|
63
|
+
addopts = "-m \"not benchmark\""
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""DataCrease: Das deterministische Daten-Bügeleisen.
|
|
2
|
+
|
|
3
|
+
Sanitization, Pufferung, Hash-Guard und Audit-Trails an Daten-Kupplungen.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from datacrease.audit import AuditLogger
|
|
7
|
+
from datacrease.buffer import OverflowPolicy, RingBuffer
|
|
8
|
+
from datacrease.config import IronConfig
|
|
9
|
+
from datacrease.exceptions import (
|
|
10
|
+
BufferOverflowError,
|
|
11
|
+
ConfigError,
|
|
12
|
+
DataCreaseCorruptPayloadError,
|
|
13
|
+
DataCreaseError,
|
|
14
|
+
RegexConfigError,
|
|
15
|
+
)
|
|
16
|
+
from datacrease.hash_guard import HashGuard
|
|
17
|
+
from datacrease.iron import Iron
|
|
18
|
+
from datacrease.models import (
|
|
19
|
+
CheckerResult,
|
|
20
|
+
CreaseErrorCode,
|
|
21
|
+
FieldChangeType,
|
|
22
|
+
FieldModification,
|
|
23
|
+
IronResult,
|
|
24
|
+
ProcessingResult,
|
|
25
|
+
Receipt,
|
|
26
|
+
Status,
|
|
27
|
+
)
|
|
28
|
+
from datacrease.pipeline import DataCrease
|
|
29
|
+
from datacrease.stream import StreamProcessor, StreamStats
|
|
30
|
+
|
|
31
|
+
__version__ = "1.0.0"
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
"__version__",
|
|
35
|
+
"DataCrease",
|
|
36
|
+
"Iron",
|
|
37
|
+
"IronConfig",
|
|
38
|
+
"Checker",
|
|
39
|
+
"HashGuard",
|
|
40
|
+
"RingBuffer",
|
|
41
|
+
"OverflowPolicy",
|
|
42
|
+
"DataCreaseError",
|
|
43
|
+
"DataCreaseCorruptPayloadError",
|
|
44
|
+
"BufferOverflowError",
|
|
45
|
+
"AuditLogger",
|
|
46
|
+
"StreamProcessor",
|
|
47
|
+
"StreamStats",
|
|
48
|
+
"ConfigError",
|
|
49
|
+
"RegexConfigError",
|
|
50
|
+
"Status",
|
|
51
|
+
"CreaseErrorCode",
|
|
52
|
+
"FieldChangeType",
|
|
53
|
+
"FieldModification",
|
|
54
|
+
"IronResult",
|
|
55
|
+
"CheckerResult",
|
|
56
|
+
"ProcessingResult",
|
|
57
|
+
"Receipt",
|
|
58
|
+
]
|