datafog 4.9.0a2__tar.gz → 4.10.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.
- {datafog-4.9.0a2 → datafog-4.10.0}/PKG-INFO +43 -17
- {datafog-4.9.0a2 → datafog-4.10.0}/README.md +39 -14
- datafog-4.10.0/datafog/__about__.py +1 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/__init__.py +13 -3
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/_core_capabilities.py +7 -6
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/_legacy_retirement.py +5 -1
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/compat/v4.py +8 -7
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/engine.py +193 -33
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/exceptions.py +4 -0
- datafog-4.10.0/datafog/native.py +60 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog.egg-info/PKG-INFO +43 -17
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog.egg-info/SOURCES.txt +2 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog.egg-info/requires.txt +2 -1
- {datafog-4.9.0a2 → datafog-4.10.0}/setup.py +6 -2
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_allowlist.py +19 -1
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_api_bridge_49.py +1 -1
- datafog-4.10.0/tests/test_backend_resolution.py +114 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_contract_481.py +17 -4
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_core04_integration.py +25 -12
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_de_pii_regex.py +13 -4
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_detection_accuracy.py +105 -16
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_legacy_retirement.py +7 -4
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_rust_backend.py +11 -4
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_rust_contract.py +3 -1
- datafog-4.9.0a2/datafog/__about__.py +0 -1
- {datafog-4.9.0a2 → datafog-4.10.0}/LICENSE +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/__init___lean.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/__init___original.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/agent.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/client.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/compat/__init__.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/config.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/core.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/integrations/__init__.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/integrations/claude_code.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/integrations/litellm_guardrail.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/main.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/main_lean.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/main_original.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/models/__init__.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/models/annotator.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/models/anonymizer.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/models/common.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/models/spacy_nlp.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/processing/__init__.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/processing/image_processing/__init__.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/processing/image_processing/donut_processor.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/processing/image_processing/image_downloader.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/processing/image_processing/pytesseract_processor.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/processing/spark_processing/__init__.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/processing/spark_processing/pyspark_udfs.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/processing/text_processing/__init__.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/processing/text_processing/gliner_annotator.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/processing/text_processing/regex_annotator/__init__.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/processing/text_processing/regex_annotator/regex_annotator.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/processing/text_processing/spacy_pii_annotator.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/py.typed +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/services/__init__.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/services/image_service.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/services/spark_service.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/services/text_service.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/services/text_service_lean.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/services/text_service_original.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/telemetry.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog/v5.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog.egg-info/dependency_links.txt +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog.egg-info/entry_points.txt +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/datafog.egg-info/top_level.txt +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/setup.cfg +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_agent_api.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_anonymizer.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_claude_code_hook.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_cli_smoke.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_client.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_core_capability_adapter.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_donut_lazy_import.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_engine_api.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_gliner_annotator.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_image_service.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_install_profiles.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_litellm_guardrail.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_main.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_no_network_core.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_ocr_integration.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_regex_annotator.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_runtime_dependency_safety.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_spark_integration.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_telemetry.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_text_service.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_text_service_integration.py +0 -0
- {datafog-4.9.0a2 → datafog-4.10.0}/tests/test_v44_bridge_api.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: datafog
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.10.0
|
|
4
4
|
Summary: Lightning-fast PII detection and anonymization library, 100x+ faster than NER-based detection (see benchmarks/)
|
|
5
5
|
Author: Sid Mohan
|
|
6
6
|
Author-email: sid@datafog.ai
|
|
@@ -10,7 +10,7 @@ Project-URL: Discord, https://discord.gg/bzDth394R4
|
|
|
10
10
|
Project-URL: Twitter, https://twitter.com/datafoginc
|
|
11
11
|
Project-URL: GitHub, https://github.com/datafog/datafog-python
|
|
12
12
|
Keywords: pii detection anonymization privacy regex performance
|
|
13
|
-
Classifier: Development Status ::
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
14
|
Classifier: Intended Audience :: Developers
|
|
15
15
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -25,11 +25,12 @@ Classifier: Topic :: Security
|
|
|
25
25
|
Requires-Python: >=3.10
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
27
|
License-File: LICENSE
|
|
28
|
+
Requires-Dist: datafog-core<2,>=1.3.0
|
|
28
29
|
Requires-Dist: pydantic<3.0,>=2.0
|
|
29
30
|
Requires-Dist: pydantic-settings>=2.0.0
|
|
30
31
|
Requires-Dist: typing-extensions>=4.0
|
|
31
32
|
Provides-Extra: rust
|
|
32
|
-
Requires-Dist: datafog-core<
|
|
33
|
+
Requires-Dist: datafog-core<2,>=1.3.0; extra == "rust"
|
|
33
34
|
Provides-Extra: nlp
|
|
34
35
|
Requires-Dist: click<9.0,>=8.0; extra == "nlp"
|
|
35
36
|
Requires-Dist: spacy<4.0,>=3.7.0; extra == "nlp"
|
|
@@ -133,8 +134,9 @@ values never echoed into logs or transcripts:
|
|
|
133
134
|
|
|
134
135
|
- **Claude Code hook** (`datafog-hook`): gates agent tool calls (shell
|
|
135
136
|
commands, web requests, file writes, MCP tools) and warns the model when
|
|
136
|
-
prompts or tool results carry PII. ~
|
|
137
|
-
process startup
|
|
137
|
+
prompts or tool results carry PII. ~105–110ms per invocation including
|
|
138
|
+
process startup and the native engine load (`DATAFOG_BACKEND=python` trims
|
|
139
|
+
~20ms at the cost of detection coverage). Easiest install is the
|
|
138
140
|
[Claude Code plugin](https://github.com/DataFog/datafog-claude-plugin):
|
|
139
141
|
|
|
140
142
|
```
|
|
@@ -146,8 +148,8 @@ values never echoed into logs or transcripts:
|
|
|
146
148
|
|
|
147
149
|
- **LiteLLM guardrail** (`DataFogGuardrail`): redacts or blocks PII in
|
|
148
150
|
requests and responses at the gateway, for any LiteLLM-proxied provider.
|
|
149
|
-
In-process (
|
|
150
|
-
|
|
151
|
+
In-process (tens of microseconds per message scanned on the native engine),
|
|
152
|
+
no sidecar service. Setup:
|
|
151
153
|
[examples/litellm_guardrail/](examples/litellm_guardrail/).
|
|
152
154
|
|
|
153
155
|
Both default to the high-precision entity set (`EMAIL`, `PHONE`,
|
|
@@ -165,7 +167,7 @@ NER live in [benchmarks/](benchmarks/).
|
|
|
165
167
|
## Installation
|
|
166
168
|
|
|
167
169
|
```bash
|
|
168
|
-
# Core install
|
|
170
|
+
# Core install: native engine, no extra packages needed
|
|
169
171
|
pip install datafog
|
|
170
172
|
|
|
171
173
|
# Add spaCy support
|
|
@@ -184,9 +186,33 @@ pip install datafog[distributed]
|
|
|
184
186
|
pip install datafog[all]
|
|
185
187
|
```
|
|
186
188
|
|
|
189
|
+
`pip install datafog` pulls `datafog-core`, which is the native engine. Wheels
|
|
190
|
+
exist for Linux (glibc and musl, x86_64/aarch64/s390x/ppc64le), macOS and
|
|
191
|
+
Windows (amd64/arm64); anywhere else the source build needs a Rust toolchain.
|
|
192
|
+
If Core cannot be imported, detection falls back to the pure-Python engine and
|
|
193
|
+
warns once — `DATAFOG_BACKEND=python` selects that path deliberately.
|
|
194
|
+
|
|
187
195
|
The `nlp-advanced` extra includes SentencePiece and protobuf for GLiNER's
|
|
188
196
|
multilingual tokenizer; installing the OCR extra is not required for GLiNER.
|
|
189
197
|
|
|
198
|
+
## Backends
|
|
199
|
+
|
|
200
|
+
`backend` defaults to `auto`: the native engine when `datafog-core` is
|
|
201
|
+
importable, the pure-Python regex engine otherwise. `DATAFOG_BACKEND` sets the
|
|
202
|
+
default and `backend="python"` / `backend="rust"` override it per call.
|
|
203
|
+
`auto` never selects the native engine for `engine="spacy"`, `"gliner"` or
|
|
204
|
+
`"smart"`, which stay on the Python ML path.
|
|
205
|
+
|
|
206
|
+
The native engine adds detectors the Python engine never had — `API_KEY`,
|
|
207
|
+
`BEARER_TOKEN`, `JWT`, `PRIVATE_KEY`, `CREDENTIAL_URI`, `ACCOUNT_NUMBER`,
|
|
208
|
+
`US_ROUTING_NUMBER`, `NPI`, `UUID` and a German set — and serves prose `PERSON`
|
|
209
|
+
and `ADDRESS` from an embedded model, so name and address detection needs no
|
|
210
|
+
spaCy and no model download. Findings keep `engine="regex"` provenance and
|
|
211
|
+
`confidence=1.0` as compatibility values, not native confidence estimates.
|
|
212
|
+
Reviewed differences from the Python engine are listed in
|
|
213
|
+
[tests/contracts/rust-1.3.0.json](tests/contracts/rust-1.3.0.json).
|
|
214
|
+
`datafog.native` exposes the native schema directly.
|
|
215
|
+
|
|
190
216
|
Python 3.13 support is certified for the core SDK, CLI, `nlp`,
|
|
191
217
|
`nlp-advanced`, and `ocr` install profiles. Donut OCR still requires a model
|
|
192
218
|
that is available locally before runtime use. `distributed` and `all` remain
|
|
@@ -302,10 +328,12 @@ scan/redact helpers, or guardrail helpers.
|
|
|
302
328
|
model.
|
|
303
329
|
- A Java runtime is required by PySpark.
|
|
304
330
|
|
|
305
|
-
DataFog
|
|
306
|
-
warnings; their APIs and extras will be removed in 5.0.
|
|
307
|
-
|
|
308
|
-
the [
|
|
331
|
+
DataFog deprecates OCR and Spark with visible use-time
|
|
332
|
+
warnings; their APIs and extras will be removed in 5.0. The last supported
|
|
333
|
+
version is 4.10.0 — pin it with `pip install "datafog==4.10.0"` — and every
|
|
334
|
+
retired surface is tracked in the [retirement schedule](docs/retirement.rst).
|
|
335
|
+
See the [4.9 migration guide](docs/migration-4.9.md) for the transition plan,
|
|
336
|
+
and [VERSIONING.md](VERSIONING.md) for what a version number promises.
|
|
309
337
|
|
|
310
338
|
## Backward-Compatible APIs
|
|
311
339
|
|
|
@@ -375,11 +403,9 @@ The [4.9 migration guide](docs/migration-4.9.md) explains opt-in Rust detection,
|
|
|
375
403
|
the native `datafog.v5` preview, and the revised 5.0 retirement schedule for
|
|
376
404
|
`detect`/`process`, OCR, and Spark. The Python detector remains the default.
|
|
377
405
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
installing the Rust extra does not change the default backend. See the
|
|
382
|
-
[4.9.0 release notes](RELEASE_NOTES_4.9.0.md).
|
|
406
|
+
4.10.0 requires Core `>=1.3.0,<2` and capability contract 1, and installs it by
|
|
407
|
+
default. See the [4.10.0 release notes](RELEASE_NOTES_4.10.0.md) and the
|
|
408
|
+
[4.10 migration guide](docs/migration-4.10.md).
|
|
383
409
|
Entity labels, locales, and activation settings come from the installed
|
|
384
410
|
Core, allowing compatible releases to add detectors without a Python update.
|
|
385
411
|
German detection is opt-in through locale or entity selection; UUID is opt-in
|
|
@@ -19,8 +19,9 @@ values never echoed into logs or transcripts:
|
|
|
19
19
|
|
|
20
20
|
- **Claude Code hook** (`datafog-hook`): gates agent tool calls (shell
|
|
21
21
|
commands, web requests, file writes, MCP tools) and warns the model when
|
|
22
|
-
prompts or tool results carry PII. ~
|
|
23
|
-
process startup
|
|
22
|
+
prompts or tool results carry PII. ~105–110ms per invocation including
|
|
23
|
+
process startup and the native engine load (`DATAFOG_BACKEND=python` trims
|
|
24
|
+
~20ms at the cost of detection coverage). Easiest install is the
|
|
24
25
|
[Claude Code plugin](https://github.com/DataFog/datafog-claude-plugin):
|
|
25
26
|
|
|
26
27
|
```
|
|
@@ -32,8 +33,8 @@ values never echoed into logs or transcripts:
|
|
|
32
33
|
|
|
33
34
|
- **LiteLLM guardrail** (`DataFogGuardrail`): redacts or blocks PII in
|
|
34
35
|
requests and responses at the gateway, for any LiteLLM-proxied provider.
|
|
35
|
-
In-process (
|
|
36
|
-
|
|
36
|
+
In-process (tens of microseconds per message scanned on the native engine),
|
|
37
|
+
no sidecar service. Setup:
|
|
37
38
|
[examples/litellm_guardrail/](examples/litellm_guardrail/).
|
|
38
39
|
|
|
39
40
|
Both default to the high-precision entity set (`EMAIL`, `PHONE`,
|
|
@@ -51,7 +52,7 @@ NER live in [benchmarks/](benchmarks/).
|
|
|
51
52
|
## Installation
|
|
52
53
|
|
|
53
54
|
```bash
|
|
54
|
-
# Core install
|
|
55
|
+
# Core install: native engine, no extra packages needed
|
|
55
56
|
pip install datafog
|
|
56
57
|
|
|
57
58
|
# Add spaCy support
|
|
@@ -70,9 +71,33 @@ pip install datafog[distributed]
|
|
|
70
71
|
pip install datafog[all]
|
|
71
72
|
```
|
|
72
73
|
|
|
74
|
+
`pip install datafog` pulls `datafog-core`, which is the native engine. Wheels
|
|
75
|
+
exist for Linux (glibc and musl, x86_64/aarch64/s390x/ppc64le), macOS and
|
|
76
|
+
Windows (amd64/arm64); anywhere else the source build needs a Rust toolchain.
|
|
77
|
+
If Core cannot be imported, detection falls back to the pure-Python engine and
|
|
78
|
+
warns once — `DATAFOG_BACKEND=python` selects that path deliberately.
|
|
79
|
+
|
|
73
80
|
The `nlp-advanced` extra includes SentencePiece and protobuf for GLiNER's
|
|
74
81
|
multilingual tokenizer; installing the OCR extra is not required for GLiNER.
|
|
75
82
|
|
|
83
|
+
## Backends
|
|
84
|
+
|
|
85
|
+
`backend` defaults to `auto`: the native engine when `datafog-core` is
|
|
86
|
+
importable, the pure-Python regex engine otherwise. `DATAFOG_BACKEND` sets the
|
|
87
|
+
default and `backend="python"` / `backend="rust"` override it per call.
|
|
88
|
+
`auto` never selects the native engine for `engine="spacy"`, `"gliner"` or
|
|
89
|
+
`"smart"`, which stay on the Python ML path.
|
|
90
|
+
|
|
91
|
+
The native engine adds detectors the Python engine never had — `API_KEY`,
|
|
92
|
+
`BEARER_TOKEN`, `JWT`, `PRIVATE_KEY`, `CREDENTIAL_URI`, `ACCOUNT_NUMBER`,
|
|
93
|
+
`US_ROUTING_NUMBER`, `NPI`, `UUID` and a German set — and serves prose `PERSON`
|
|
94
|
+
and `ADDRESS` from an embedded model, so name and address detection needs no
|
|
95
|
+
spaCy and no model download. Findings keep `engine="regex"` provenance and
|
|
96
|
+
`confidence=1.0` as compatibility values, not native confidence estimates.
|
|
97
|
+
Reviewed differences from the Python engine are listed in
|
|
98
|
+
[tests/contracts/rust-1.3.0.json](tests/contracts/rust-1.3.0.json).
|
|
99
|
+
`datafog.native` exposes the native schema directly.
|
|
100
|
+
|
|
76
101
|
Python 3.13 support is certified for the core SDK, CLI, `nlp`,
|
|
77
102
|
`nlp-advanced`, and `ocr` install profiles. Donut OCR still requires a model
|
|
78
103
|
that is available locally before runtime use. `distributed` and `all` remain
|
|
@@ -188,10 +213,12 @@ scan/redact helpers, or guardrail helpers.
|
|
|
188
213
|
model.
|
|
189
214
|
- A Java runtime is required by PySpark.
|
|
190
215
|
|
|
191
|
-
DataFog
|
|
192
|
-
warnings; their APIs and extras will be removed in 5.0.
|
|
193
|
-
|
|
194
|
-
the [
|
|
216
|
+
DataFog deprecates OCR and Spark with visible use-time
|
|
217
|
+
warnings; their APIs and extras will be removed in 5.0. The last supported
|
|
218
|
+
version is 4.10.0 — pin it with `pip install "datafog==4.10.0"` — and every
|
|
219
|
+
retired surface is tracked in the [retirement schedule](docs/retirement.rst).
|
|
220
|
+
See the [4.9 migration guide](docs/migration-4.9.md) for the transition plan,
|
|
221
|
+
and [VERSIONING.md](VERSIONING.md) for what a version number promises.
|
|
195
222
|
|
|
196
223
|
## Backward-Compatible APIs
|
|
197
224
|
|
|
@@ -261,11 +288,9 @@ The [4.9 migration guide](docs/migration-4.9.md) explains opt-in Rust detection,
|
|
|
261
288
|
the native `datafog.v5` preview, and the revised 5.0 retirement schedule for
|
|
262
289
|
`detect`/`process`, OCR, and Spark. The Python detector remains the default.
|
|
263
290
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
installing the Rust extra does not change the default backend. See the
|
|
268
|
-
[4.9.0 release notes](RELEASE_NOTES_4.9.0.md).
|
|
291
|
+
4.10.0 requires Core `>=1.3.0,<2` and capability contract 1, and installs it by
|
|
292
|
+
default. See the [4.10.0 release notes](RELEASE_NOTES_4.10.0.md) and the
|
|
293
|
+
[4.10 migration guide](docs/migration-4.10.md).
|
|
269
294
|
Entity labels, locales, and activation settings come from the installed
|
|
270
295
|
Core, allowing compatible releases to add detectors without a Python update.
|
|
271
296
|
German detection is opt-in through locale or entity selection; UUID is opt-in
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "4.10.0"
|
|
@@ -12,6 +12,7 @@ Optional extras available for advanced features:
|
|
|
12
12
|
import warnings
|
|
13
13
|
|
|
14
14
|
from .__about__ import __version__
|
|
15
|
+
from ._legacy_retirement import LAST_SUPPORTED as _LAST_SUPPORTED
|
|
15
16
|
from .agent import create_guardrail, filter_output, sanitize, scan_prompt
|
|
16
17
|
|
|
17
18
|
# Core API functions - always available (lightweight)
|
|
@@ -81,6 +82,13 @@ def __getattr__(name: str):
|
|
|
81
82
|
|
|
82
83
|
elif name in _LAZY_EXPORTS:
|
|
83
84
|
module_path, attr_name, extra_name = _LAZY_EXPORTS[name]
|
|
85
|
+
if attr_name is None:
|
|
86
|
+
# Submodule export (``datafog.native``): return the module itself.
|
|
87
|
+
import importlib
|
|
88
|
+
|
|
89
|
+
value = importlib.import_module(module_path)
|
|
90
|
+
globals()[name] = value
|
|
91
|
+
return value
|
|
84
92
|
try:
|
|
85
93
|
module = __import__(module_path, fromlist=[attr_name])
|
|
86
94
|
value = getattr(module, attr_name)
|
|
@@ -104,6 +112,7 @@ def __getattr__(name: str):
|
|
|
104
112
|
|
|
105
113
|
|
|
106
114
|
_LAZY_EXPORTS = {
|
|
115
|
+
"native": ("datafog.native", None, None),
|
|
107
116
|
"app": ("datafog.client", "app", None),
|
|
108
117
|
"DataFog": ("datafog.main", "DataFog", None),
|
|
109
118
|
"TextPIIAnnotator": ("datafog.main", "TextPIIAnnotator", None),
|
|
@@ -131,7 +140,8 @@ _LAZY_EXPORTS = {
|
|
|
131
140
|
def _warn_v5_replacement(old_api: str, replacement: str) -> None:
|
|
132
141
|
warnings.warn(
|
|
133
142
|
f"datafog.{old_api}() is deprecated and will be removed in 5.0. Use {replacement} instead. "
|
|
134
|
-
|
|
143
|
+
f'Last supported version is {_LAST_SUPPORTED}. Pin it with: pip install "datafog=={_LAST_SUPPORTED}". '
|
|
144
|
+
"The earlier promise to retain this shim through 5.x has been revised. See docs/retirement.rst.",
|
|
135
145
|
FutureWarning,
|
|
136
146
|
stacklevel=3,
|
|
137
147
|
)
|
|
@@ -145,7 +155,7 @@ def scan(
|
|
|
145
155
|
allowlist: list[str] | None = None,
|
|
146
156
|
allowlist_patterns: list[str] | None = None,
|
|
147
157
|
*,
|
|
148
|
-
backend: str =
|
|
158
|
+
backend: str | None = None,
|
|
149
159
|
) -> ScanResult:
|
|
150
160
|
"""Scan using the 4.x compatibility API; Rust detection is opt-in."""
|
|
151
161
|
return _compat_v4.scan(
|
|
@@ -170,7 +180,7 @@ def redact(
|
|
|
170
180
|
allowlist: list[str] | None = None,
|
|
171
181
|
allowlist_patterns: list[str] | None = None,
|
|
172
182
|
*,
|
|
173
|
-
backend: str =
|
|
183
|
+
backend: str | None = None,
|
|
174
184
|
) -> RedactResult:
|
|
175
185
|
"""Redact using the 4.x compatibility API and legacy strategies."""
|
|
176
186
|
return _compat_v4.redact(
|
|
@@ -85,7 +85,7 @@ def _requested_locales(locales: Any, lookup: dict[str, str]) -> set[str]:
|
|
|
85
85
|
return {_resolve_locale(locale, lookup) for locale in locales or []}
|
|
86
86
|
|
|
87
87
|
|
|
88
|
-
def _activation_config(label: str, metadata: dict) -> dict:
|
|
88
|
+
def _activation_config(label: str, metadata: dict) -> dict | None:
|
|
89
89
|
details = metadata.get(label)
|
|
90
90
|
if not isinstance(details, dict):
|
|
91
91
|
raise _invalid(f"missing entity metadata for {label!r}")
|
|
@@ -95,10 +95,9 @@ def _activation_config(label: str, metadata: dict) -> dict:
|
|
|
95
95
|
):
|
|
96
96
|
raise _invalid(f"invalid scopes for {label!r}")
|
|
97
97
|
if "text" not in scopes:
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
)
|
|
98
|
+
# Structured-only labels are served by the caller, usually from the
|
|
99
|
+
# embedded model, so a mixed selection is not an error.
|
|
100
|
+
return None
|
|
102
101
|
activation = details.get("activation")
|
|
103
102
|
if not isinstance(activation, dict):
|
|
104
103
|
raise _invalid(f"missing activation metadata for {label!r}")
|
|
@@ -120,13 +119,15 @@ def scan_configs(core: Any, requested: set[str], locales: Any) -> list[dict]:
|
|
|
120
119
|
capabilities = getattr(core, "capabilities", None)
|
|
121
120
|
if not callable(capabilities):
|
|
122
121
|
raise _invalid(
|
|
123
|
-
"contract version 1 is required; install a compatible
|
|
122
|
+
"contract version 1 is required; install a compatible datafog-core"
|
|
124
123
|
)
|
|
125
124
|
supported, lookup, metadata = _read_capabilities(capabilities)
|
|
126
125
|
selected_locales = _requested_locales(locales, lookup)
|
|
127
126
|
common: dict[str, Any] = {}
|
|
128
127
|
for label in sorted(requested & supported):
|
|
129
128
|
config = _activation_config(label, metadata)
|
|
129
|
+
if config is None:
|
|
130
|
+
continue
|
|
130
131
|
for key, value in config.items():
|
|
131
132
|
if key == "locale":
|
|
132
133
|
selected_locales.add(_resolve_locale(value, lookup))
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import warnings
|
|
4
4
|
|
|
5
|
+
#: Final release on which retired optional surfaces still work.
|
|
6
|
+
LAST_SUPPORTED = "4.10.0"
|
|
7
|
+
|
|
5
8
|
|
|
6
9
|
class LegacySurfaceWarning(FutureWarning):
|
|
7
10
|
"""An optional DataFog surface scheduled for removal in 5.0."""
|
|
@@ -11,7 +14,8 @@ def warn_legacy_surface(surface: str) -> None:
|
|
|
11
14
|
"""Warn at the caller's public API boundary, before optional imports."""
|
|
12
15
|
warnings.warn(
|
|
13
16
|
f"DataFog {surface} support is deprecated in 4.9 and will be removed in 5.0. "
|
|
14
|
-
|
|
17
|
+
f'Last supported version is {LAST_SUPPORTED}. Pin it with: pip install "datafog=={LAST_SUPPORTED}". '
|
|
18
|
+
"See docs/retirement.rst.",
|
|
15
19
|
LegacySurfaceWarning,
|
|
16
20
|
stacklevel=3,
|
|
17
21
|
)
|
|
@@ -6,6 +6,7 @@ not include the deprecated detect/process shims.
|
|
|
6
6
|
|
|
7
7
|
from ..engine import Entity, RedactResult, ScanResult
|
|
8
8
|
from ..engine import redact as _redact_entities
|
|
9
|
+
from ..engine import resolve_backend
|
|
9
10
|
from ..engine import scan as _scan
|
|
10
11
|
from ..engine import scan_and_redact as _scan_and_redact
|
|
11
12
|
|
|
@@ -29,13 +30,13 @@ def scan(
|
|
|
29
30
|
allowlist: list[str] | None = None,
|
|
30
31
|
allowlist_patterns: list[str] | None = None,
|
|
31
32
|
*,
|
|
32
|
-
backend: str =
|
|
33
|
+
backend: str | None = None,
|
|
33
34
|
) -> ScanResult:
|
|
34
35
|
"""
|
|
35
|
-
Scan with the legacy result schema
|
|
36
|
+
Scan with the legacy result schema.
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
Backend selection follows ``datafog.engine.resolve_backend``: native when
|
|
39
|
+
``datafog-core`` is importable, otherwise Python with a one-time warning.
|
|
39
40
|
|
|
40
41
|
``allowlist`` exempts exact entity texts (your own support address, doc
|
|
41
42
|
placeholders); ``allowlist_patterns`` exempts entities whose full text
|
|
@@ -64,7 +65,7 @@ def redact(
|
|
|
64
65
|
allowlist: list[str] | None = None,
|
|
65
66
|
allowlist_patterns: list[str] | None = None,
|
|
66
67
|
*,
|
|
67
|
-
backend: str =
|
|
68
|
+
backend: str | None = None,
|
|
68
69
|
) -> RedactResult:
|
|
69
70
|
"""
|
|
70
71
|
Redact with legacy strategies and result schema.
|
|
@@ -75,8 +76,8 @@ def redact(
|
|
|
75
76
|
full-text regex match respectively); they apply to the scan path and are
|
|
76
77
|
rejected when explicit ``entities`` are supplied.
|
|
77
78
|
"""
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
# Validate the backend even when explicit entities skip the scan path.
|
|
80
|
+
resolve_backend(backend, engine)
|
|
80
81
|
|
|
81
82
|
if preset is not None:
|
|
82
83
|
try:
|