truthound-dashboard 1.2.1__py3-none-any.whl → 1.3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- truthound_dashboard/api/deps.py +28 -0
- truthound_dashboard/api/drift.py +1 -0
- truthound_dashboard/api/mask.py +164 -0
- truthound_dashboard/api/profile.py +11 -3
- truthound_dashboard/api/router.py +22 -0
- truthound_dashboard/api/scan.py +168 -0
- truthound_dashboard/api/schemas.py +13 -4
- truthound_dashboard/api/validations.py +33 -1
- truthound_dashboard/api/validators.py +85 -0
- truthound_dashboard/core/__init__.py +8 -0
- truthound_dashboard/core/phase5/activity.py +1 -1
- truthound_dashboard/core/services.py +457 -7
- truthound_dashboard/core/truthound_adapter.py +441 -26
- truthound_dashboard/db/__init__.py +6 -0
- truthound_dashboard/db/models.py +250 -1
- truthound_dashboard/schemas/__init__.py +52 -1
- truthound_dashboard/schemas/collaboration.py +1 -1
- truthound_dashboard/schemas/drift.py +118 -3
- truthound_dashboard/schemas/mask.py +209 -0
- truthound_dashboard/schemas/profile.py +45 -2
- truthound_dashboard/schemas/scan.py +312 -0
- truthound_dashboard/schemas/schema.py +30 -2
- truthound_dashboard/schemas/validation.py +60 -3
- truthound_dashboard/schemas/validators/__init__.py +59 -0
- truthound_dashboard/schemas/validators/aggregate_validators.py +238 -0
- truthound_dashboard/schemas/validators/anomaly_validators.py +723 -0
- truthound_dashboard/schemas/validators/base.py +263 -0
- truthound_dashboard/schemas/validators/completeness_validators.py +269 -0
- truthound_dashboard/schemas/validators/cross_table_validators.py +375 -0
- truthound_dashboard/schemas/validators/datetime_validators.py +253 -0
- truthound_dashboard/schemas/validators/distribution_validators.py +422 -0
- truthound_dashboard/schemas/validators/drift_validators.py +615 -0
- truthound_dashboard/schemas/validators/geospatial_validators.py +486 -0
- truthound_dashboard/schemas/validators/multi_column_validators.py +706 -0
- truthound_dashboard/schemas/validators/privacy_validators.py +531 -0
- truthound_dashboard/schemas/validators/query_validators.py +510 -0
- truthound_dashboard/schemas/validators/registry.py +318 -0
- truthound_dashboard/schemas/validators/schema_validators.py +408 -0
- truthound_dashboard/schemas/validators/string_validators.py +396 -0
- truthound_dashboard/schemas/validators/table_validators.py +412 -0
- truthound_dashboard/schemas/validators/uniqueness_validators.py +355 -0
- truthound_dashboard/schemas/validators.py +59 -0
- truthound_dashboard/static/assets/index-BZG20KuF.js +586 -0
- truthound_dashboard/static/assets/index-D_HyZ3pb.css +1 -0
- truthound_dashboard/static/assets/unmerged_dictionaries-CtpqQBm0.js +1 -0
- truthound_dashboard/static/index.html +2 -2
- {truthound_dashboard-1.2.1.dist-info → truthound_dashboard-1.3.1.dist-info}/METADATA +50 -11
- {truthound_dashboard-1.2.1.dist-info → truthound_dashboard-1.3.1.dist-info}/RECORD +51 -27
- truthound_dashboard/static/assets/index-BqXVFyqj.js +0 -574
- truthound_dashboard/static/assets/index-o8qHVDte.css +0 -1
- truthound_dashboard/static/assets/unmerged_dictionaries-n_T3wZTf.js +0 -1
- {truthound_dashboard-1.2.1.dist-info → truthound_dashboard-1.3.1.dist-info}/WHEEL +0 -0
- {truthound_dashboard-1.2.1.dist-info → truthound_dashboard-1.3.1.dist-info}/entry_points.txt +0 -0
- {truthound_dashboard-1.2.1.dist-info → truthound_dashboard-1.3.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
"""Validator registry.
|
|
2
|
+
|
|
3
|
+
Central registry combining all validator categories with metadata and lookup functions.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from typing import Literal
|
|
10
|
+
|
|
11
|
+
from .base import ValidatorCategory, ValidatorDefinition
|
|
12
|
+
|
|
13
|
+
# Import all validator category modules
|
|
14
|
+
from .schema_validators import SCHEMA_VALIDATORS
|
|
15
|
+
from .completeness_validators import COMPLETENESS_VALIDATORS
|
|
16
|
+
from .uniqueness_validators import UNIQUENESS_VALIDATORS
|
|
17
|
+
from .distribution_validators import DISTRIBUTION_VALIDATORS
|
|
18
|
+
from .string_validators import STRING_VALIDATORS
|
|
19
|
+
from .datetime_validators import DATETIME_VALIDATORS
|
|
20
|
+
from .aggregate_validators import AGGREGATE_VALIDATORS
|
|
21
|
+
from .cross_table_validators import CROSS_TABLE_VALIDATORS
|
|
22
|
+
from .multi_column_validators import MULTI_COLUMN_VALIDATORS
|
|
23
|
+
from .query_validators import QUERY_VALIDATORS
|
|
24
|
+
from .table_validators import TABLE_VALIDATORS
|
|
25
|
+
from .geospatial_validators import GEOSPATIAL_VALIDATORS
|
|
26
|
+
from .drift_validators import DRIFT_VALIDATORS
|
|
27
|
+
from .anomaly_validators import ANOMALY_VALIDATORS
|
|
28
|
+
from .privacy_validators import PRIVACY_VALIDATORS
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class CategoryInfo:
|
|
33
|
+
"""Metadata for a validator category."""
|
|
34
|
+
|
|
35
|
+
value: str
|
|
36
|
+
label: str
|
|
37
|
+
description: str
|
|
38
|
+
icon: str | None = None
|
|
39
|
+
color: str | None = None
|
|
40
|
+
requires_extra: str | None = None
|
|
41
|
+
validator_count: int = 0
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# Category metadata with UI information
|
|
45
|
+
CATEGORY_INFO: list[CategoryInfo] = [
|
|
46
|
+
# Core validators (no extra dependencies)
|
|
47
|
+
CategoryInfo(
|
|
48
|
+
value="schema",
|
|
49
|
+
label="Schema",
|
|
50
|
+
description="Validate structure, columns, and data types",
|
|
51
|
+
icon="layout",
|
|
52
|
+
color="#3b82f6", # blue
|
|
53
|
+
),
|
|
54
|
+
CategoryInfo(
|
|
55
|
+
value="completeness",
|
|
56
|
+
label="Completeness",
|
|
57
|
+
description="Check for null values and missing data",
|
|
58
|
+
icon="check-circle",
|
|
59
|
+
color="#22c55e", # green
|
|
60
|
+
),
|
|
61
|
+
CategoryInfo(
|
|
62
|
+
value="uniqueness",
|
|
63
|
+
label="Uniqueness",
|
|
64
|
+
description="Detect duplicates and validate keys",
|
|
65
|
+
icon="fingerprint",
|
|
66
|
+
color="#8b5cf6", # purple
|
|
67
|
+
),
|
|
68
|
+
CategoryInfo(
|
|
69
|
+
value="distribution",
|
|
70
|
+
label="Distribution",
|
|
71
|
+
description="Validate value ranges and distributions",
|
|
72
|
+
icon="bar-chart",
|
|
73
|
+
color="#f59e0b", # amber
|
|
74
|
+
),
|
|
75
|
+
# Format validators
|
|
76
|
+
CategoryInfo(
|
|
77
|
+
value="string",
|
|
78
|
+
label="String",
|
|
79
|
+
description="Pattern matching and format validation",
|
|
80
|
+
icon="type",
|
|
81
|
+
color="#06b6d4", # cyan
|
|
82
|
+
),
|
|
83
|
+
CategoryInfo(
|
|
84
|
+
value="datetime",
|
|
85
|
+
label="Datetime",
|
|
86
|
+
description="Date/time format and range validation",
|
|
87
|
+
icon="calendar",
|
|
88
|
+
color="#ec4899", # pink
|
|
89
|
+
),
|
|
90
|
+
# Statistical validators
|
|
91
|
+
CategoryInfo(
|
|
92
|
+
value="aggregate",
|
|
93
|
+
label="Aggregate",
|
|
94
|
+
description="Statistical aggregate checks (mean, sum, etc.)",
|
|
95
|
+
icon="calculator",
|
|
96
|
+
color="#6366f1", # indigo
|
|
97
|
+
),
|
|
98
|
+
CategoryInfo(
|
|
99
|
+
value="drift",
|
|
100
|
+
label="Drift",
|
|
101
|
+
description="Distribution change detection between datasets",
|
|
102
|
+
icon="trending-up",
|
|
103
|
+
color="#ef4444", # red
|
|
104
|
+
requires_extra="drift",
|
|
105
|
+
),
|
|
106
|
+
CategoryInfo(
|
|
107
|
+
value="anomaly",
|
|
108
|
+
label="Anomaly",
|
|
109
|
+
description="ML-based outlier and anomaly detection",
|
|
110
|
+
icon="alert-triangle",
|
|
111
|
+
color="#f97316", # orange
|
|
112
|
+
requires_extra="anomaly",
|
|
113
|
+
),
|
|
114
|
+
# Relational validators
|
|
115
|
+
CategoryInfo(
|
|
116
|
+
value="cross_table",
|
|
117
|
+
label="Cross-Table",
|
|
118
|
+
description="Multi-table relationships and foreign keys",
|
|
119
|
+
icon="link",
|
|
120
|
+
color="#14b8a6", # teal
|
|
121
|
+
),
|
|
122
|
+
CategoryInfo(
|
|
123
|
+
value="multi_column",
|
|
124
|
+
label="Multi-Column",
|
|
125
|
+
description="Column relationships and calculations",
|
|
126
|
+
icon="columns",
|
|
127
|
+
color="#84cc16", # lime
|
|
128
|
+
),
|
|
129
|
+
CategoryInfo(
|
|
130
|
+
value="query",
|
|
131
|
+
label="Query",
|
|
132
|
+
description="Expression-based custom validation",
|
|
133
|
+
icon="code",
|
|
134
|
+
color="#a855f7", # violet
|
|
135
|
+
),
|
|
136
|
+
# Domain validators
|
|
137
|
+
CategoryInfo(
|
|
138
|
+
value="table",
|
|
139
|
+
label="Table",
|
|
140
|
+
description="Table metadata and structure validation",
|
|
141
|
+
icon="table",
|
|
142
|
+
color="#0ea5e9", # sky
|
|
143
|
+
),
|
|
144
|
+
CategoryInfo(
|
|
145
|
+
value="geospatial",
|
|
146
|
+
label="Geospatial",
|
|
147
|
+
description="Geographic coordinate validation",
|
|
148
|
+
icon="map-pin",
|
|
149
|
+
color="#10b981", # emerald
|
|
150
|
+
),
|
|
151
|
+
CategoryInfo(
|
|
152
|
+
value="privacy",
|
|
153
|
+
label="Privacy",
|
|
154
|
+
description="PII detection and compliance (GDPR, CCPA)",
|
|
155
|
+
icon="shield",
|
|
156
|
+
color="#dc2626", # red-600
|
|
157
|
+
),
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _build_registry() -> list[ValidatorDefinition]:
|
|
162
|
+
"""Build the complete validator registry from all categories."""
|
|
163
|
+
return [
|
|
164
|
+
*SCHEMA_VALIDATORS,
|
|
165
|
+
*COMPLETENESS_VALIDATORS,
|
|
166
|
+
*UNIQUENESS_VALIDATORS,
|
|
167
|
+
*DISTRIBUTION_VALIDATORS,
|
|
168
|
+
*STRING_VALIDATORS,
|
|
169
|
+
*DATETIME_VALIDATORS,
|
|
170
|
+
*AGGREGATE_VALIDATORS,
|
|
171
|
+
*CROSS_TABLE_VALIDATORS,
|
|
172
|
+
*MULTI_COLUMN_VALIDATORS,
|
|
173
|
+
*QUERY_VALIDATORS,
|
|
174
|
+
*TABLE_VALIDATORS,
|
|
175
|
+
*GEOSPATIAL_VALIDATORS,
|
|
176
|
+
*DRIFT_VALIDATORS,
|
|
177
|
+
*ANOMALY_VALIDATORS,
|
|
178
|
+
*PRIVACY_VALIDATORS,
|
|
179
|
+
]
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
# Complete validator registry
|
|
183
|
+
VALIDATOR_REGISTRY: list[ValidatorDefinition] = _build_registry()
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _update_category_counts() -> None:
|
|
187
|
+
"""Update validator counts in category info."""
|
|
188
|
+
category_counts: dict[str, int] = {}
|
|
189
|
+
for validator in VALIDATOR_REGISTRY:
|
|
190
|
+
cat = validator.category.value
|
|
191
|
+
category_counts[cat] = category_counts.get(cat, 0) + 1
|
|
192
|
+
|
|
193
|
+
for cat_info in CATEGORY_INFO:
|
|
194
|
+
cat_info.validator_count = category_counts.get(cat_info.value, 0)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
# Update counts on module load
|
|
198
|
+
_update_category_counts()
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def get_validator_by_name(name: str) -> ValidatorDefinition | None:
|
|
202
|
+
"""Get a validator definition by name.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
name: Validator name (case-insensitive).
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
ValidatorDefinition if found, None otherwise.
|
|
209
|
+
"""
|
|
210
|
+
name_lower = name.lower()
|
|
211
|
+
for validator in VALIDATOR_REGISTRY:
|
|
212
|
+
if validator.name.lower() == name_lower:
|
|
213
|
+
return validator
|
|
214
|
+
return None
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def get_validators_by_category(
|
|
218
|
+
category: ValidatorCategory | str,
|
|
219
|
+
) -> list[ValidatorDefinition]:
|
|
220
|
+
"""Get all validators in a category.
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
category: Validator category (enum or string value).
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
List of validator definitions.
|
|
227
|
+
"""
|
|
228
|
+
if isinstance(category, str):
|
|
229
|
+
category_value = category
|
|
230
|
+
else:
|
|
231
|
+
category_value = category.value
|
|
232
|
+
|
|
233
|
+
return [v for v in VALIDATOR_REGISTRY if v.category.value == category_value]
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def search_validators(
|
|
237
|
+
query: str,
|
|
238
|
+
category: ValidatorCategory | str | None = None,
|
|
239
|
+
include_experimental: bool = False,
|
|
240
|
+
include_deprecated: bool = False,
|
|
241
|
+
) -> list[ValidatorDefinition]:
|
|
242
|
+
"""Search validators by name, description, or tags.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
query: Search query string.
|
|
246
|
+
category: Optional category filter.
|
|
247
|
+
include_experimental: Include experimental validators.
|
|
248
|
+
include_deprecated: Include deprecated validators.
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
List of matching validator definitions.
|
|
252
|
+
"""
|
|
253
|
+
query_lower = query.lower()
|
|
254
|
+
results = []
|
|
255
|
+
|
|
256
|
+
for validator in VALIDATOR_REGISTRY:
|
|
257
|
+
# Apply filters
|
|
258
|
+
if not include_experimental and validator.experimental:
|
|
259
|
+
continue
|
|
260
|
+
if not include_deprecated and validator.deprecated:
|
|
261
|
+
continue
|
|
262
|
+
if category:
|
|
263
|
+
cat_value = category if isinstance(category, str) else category.value
|
|
264
|
+
if validator.category.value != cat_value:
|
|
265
|
+
continue
|
|
266
|
+
|
|
267
|
+
# Search in name, display_name, description, and tags
|
|
268
|
+
if (
|
|
269
|
+
query_lower in validator.name.lower()
|
|
270
|
+
or query_lower in validator.display_name.lower()
|
|
271
|
+
or query_lower in validator.description.lower()
|
|
272
|
+
or any(query_lower in tag for tag in validator.tags)
|
|
273
|
+
):
|
|
274
|
+
results.append(validator)
|
|
275
|
+
|
|
276
|
+
return results
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def get_category_info(category: ValidatorCategory | str) -> CategoryInfo | None:
|
|
280
|
+
"""Get category metadata.
|
|
281
|
+
|
|
282
|
+
Args:
|
|
283
|
+
category: Category enum or string value.
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
CategoryInfo if found, None otherwise.
|
|
287
|
+
"""
|
|
288
|
+
cat_value = category if isinstance(category, str) else category.value
|
|
289
|
+
for info in CATEGORY_INFO:
|
|
290
|
+
if info.value == cat_value:
|
|
291
|
+
return info
|
|
292
|
+
return None
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def get_validators_requiring_extra(extra: Literal["drift", "anomaly"]) -> list[ValidatorDefinition]:
|
|
296
|
+
"""Get validators that require an optional dependency.
|
|
297
|
+
|
|
298
|
+
Args:
|
|
299
|
+
extra: Required extra package ('drift' or 'anomaly').
|
|
300
|
+
|
|
301
|
+
Returns:
|
|
302
|
+
List of validators requiring the specified extra.
|
|
303
|
+
"""
|
|
304
|
+
return [v for v in VALIDATOR_REGISTRY if v.requires_extra == extra]
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def get_validator_stats() -> dict[str, int]:
|
|
308
|
+
"""Get statistics about the validator registry.
|
|
309
|
+
|
|
310
|
+
Returns:
|
|
311
|
+
Dict with category names as keys and validator counts as values.
|
|
312
|
+
"""
|
|
313
|
+
stats: dict[str, int] = {}
|
|
314
|
+
for validator in VALIDATOR_REGISTRY:
|
|
315
|
+
cat = validator.category.value
|
|
316
|
+
stats[cat] = stats.get(cat, 0) + 1
|
|
317
|
+
stats["total"] = len(VALIDATOR_REGISTRY)
|
|
318
|
+
return stats
|