truthound-dashboard 1.4.4__py3-none-any.whl → 1.5.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/alerts.py +75 -86
- truthound_dashboard/api/anomaly.py +7 -13
- truthound_dashboard/api/cross_alerts.py +38 -52
- truthound_dashboard/api/drift.py +49 -59
- truthound_dashboard/api/drift_monitor.py +234 -79
- truthound_dashboard/api/enterprise_sampling.py +498 -0
- truthound_dashboard/api/history.py +57 -5
- truthound_dashboard/api/lineage.py +3 -48
- truthound_dashboard/api/maintenance.py +104 -49
- truthound_dashboard/api/mask.py +1 -2
- truthound_dashboard/api/middleware.py +2 -1
- truthound_dashboard/api/model_monitoring.py +435 -311
- truthound_dashboard/api/notifications.py +227 -191
- truthound_dashboard/api/notifications_advanced.py +21 -20
- truthound_dashboard/api/observability.py +586 -0
- truthound_dashboard/api/plugins.py +2 -433
- truthound_dashboard/api/profile.py +199 -37
- truthound_dashboard/api/quality_reporter.py +701 -0
- truthound_dashboard/api/reports.py +7 -16
- truthound_dashboard/api/router.py +66 -0
- truthound_dashboard/api/rule_suggestions.py +5 -5
- truthound_dashboard/api/scan.py +17 -19
- truthound_dashboard/api/schedules.py +85 -50
- truthound_dashboard/api/schema_evolution.py +6 -6
- truthound_dashboard/api/schema_watcher.py +667 -0
- truthound_dashboard/api/sources.py +98 -27
- truthound_dashboard/api/tiering.py +1323 -0
- truthound_dashboard/api/triggers.py +14 -11
- truthound_dashboard/api/validations.py +12 -11
- truthound_dashboard/api/versioning.py +1 -6
- truthound_dashboard/core/__init__.py +129 -3
- truthound_dashboard/core/actions/__init__.py +62 -0
- truthound_dashboard/core/actions/custom.py +426 -0
- truthound_dashboard/core/actions/notifications.py +910 -0
- truthound_dashboard/core/actions/storage.py +472 -0
- truthound_dashboard/core/actions/webhook.py +281 -0
- truthound_dashboard/core/anomaly.py +262 -67
- truthound_dashboard/core/anomaly_explainer.py +4 -3
- truthound_dashboard/core/backends/__init__.py +67 -0
- truthound_dashboard/core/backends/base.py +299 -0
- truthound_dashboard/core/backends/errors.py +191 -0
- truthound_dashboard/core/backends/factory.py +423 -0
- truthound_dashboard/core/backends/mock_backend.py +451 -0
- truthound_dashboard/core/backends/truthound_backend.py +718 -0
- truthound_dashboard/core/checkpoint/__init__.py +87 -0
- truthound_dashboard/core/checkpoint/adapters.py +814 -0
- truthound_dashboard/core/checkpoint/checkpoint.py +491 -0
- truthound_dashboard/core/checkpoint/runner.py +270 -0
- truthound_dashboard/core/connections.py +645 -23
- truthound_dashboard/core/converters/__init__.py +14 -0
- truthound_dashboard/core/converters/truthound.py +620 -0
- truthound_dashboard/core/cross_alerts.py +540 -320
- truthound_dashboard/core/datasource_factory.py +1672 -0
- truthound_dashboard/core/drift_monitor.py +216 -20
- truthound_dashboard/core/enterprise_sampling.py +1291 -0
- truthound_dashboard/core/interfaces/__init__.py +225 -0
- truthound_dashboard/core/interfaces/actions.py +652 -0
- truthound_dashboard/core/interfaces/base.py +247 -0
- truthound_dashboard/core/interfaces/checkpoint.py +676 -0
- truthound_dashboard/core/interfaces/protocols.py +664 -0
- truthound_dashboard/core/interfaces/reporters.py +650 -0
- truthound_dashboard/core/interfaces/routing.py +646 -0
- truthound_dashboard/core/interfaces/triggers.py +619 -0
- truthound_dashboard/core/lineage.py +407 -71
- truthound_dashboard/core/model_monitoring.py +431 -3
- truthound_dashboard/core/notifications/base.py +4 -0
- truthound_dashboard/core/notifications/channels.py +501 -1203
- truthound_dashboard/core/notifications/deduplication/__init__.py +81 -115
- truthound_dashboard/core/notifications/deduplication/service.py +131 -348
- truthound_dashboard/core/notifications/dispatcher.py +202 -11
- truthound_dashboard/core/notifications/escalation/__init__.py +119 -106
- truthound_dashboard/core/notifications/escalation/engine.py +168 -358
- truthound_dashboard/core/notifications/routing/__init__.py +88 -128
- truthound_dashboard/core/notifications/routing/engine.py +90 -317
- truthound_dashboard/core/notifications/stats_aggregator.py +246 -1
- truthound_dashboard/core/notifications/throttling/__init__.py +67 -50
- truthound_dashboard/core/notifications/throttling/builder.py +117 -255
- truthound_dashboard/core/notifications/truthound_adapter.py +842 -0
- truthound_dashboard/core/phase5/collaboration.py +1 -1
- truthound_dashboard/core/plugins/lifecycle/__init__.py +0 -13
- truthound_dashboard/core/quality_reporter.py +1359 -0
- truthound_dashboard/core/report_history.py +0 -6
- truthound_dashboard/core/reporters/__init__.py +175 -14
- truthound_dashboard/core/reporters/adapters.py +943 -0
- truthound_dashboard/core/reporters/base.py +0 -3
- truthound_dashboard/core/reporters/builtin/__init__.py +18 -0
- truthound_dashboard/core/reporters/builtin/csv_reporter.py +111 -0
- truthound_dashboard/core/reporters/builtin/html_reporter.py +270 -0
- truthound_dashboard/core/reporters/builtin/json_reporter.py +127 -0
- truthound_dashboard/core/reporters/compat.py +266 -0
- truthound_dashboard/core/reporters/csv_reporter.py +2 -35
- truthound_dashboard/core/reporters/factory.py +526 -0
- truthound_dashboard/core/reporters/interfaces.py +745 -0
- truthound_dashboard/core/reporters/registry.py +1 -10
- truthound_dashboard/core/scheduler.py +165 -0
- truthound_dashboard/core/schema_evolution.py +3 -3
- truthound_dashboard/core/schema_watcher.py +1528 -0
- truthound_dashboard/core/services.py +595 -76
- truthound_dashboard/core/store_manager.py +810 -0
- truthound_dashboard/core/streaming_anomaly.py +169 -4
- truthound_dashboard/core/tiering.py +1309 -0
- truthound_dashboard/core/triggers/evaluators.py +178 -8
- truthound_dashboard/core/truthound_adapter.py +2620 -197
- truthound_dashboard/core/unified_alerts.py +23 -20
- truthound_dashboard/db/__init__.py +8 -0
- truthound_dashboard/db/database.py +8 -2
- truthound_dashboard/db/models.py +944 -25
- truthound_dashboard/db/repository.py +2 -0
- truthound_dashboard/main.py +15 -0
- truthound_dashboard/schemas/__init__.py +177 -16
- truthound_dashboard/schemas/base.py +44 -23
- truthound_dashboard/schemas/collaboration.py +19 -6
- truthound_dashboard/schemas/cross_alerts.py +19 -3
- truthound_dashboard/schemas/drift.py +61 -55
- truthound_dashboard/schemas/drift_monitor.py +67 -23
- truthound_dashboard/schemas/enterprise_sampling.py +653 -0
- truthound_dashboard/schemas/lineage.py +0 -33
- truthound_dashboard/schemas/mask.py +10 -8
- truthound_dashboard/schemas/model_monitoring.py +89 -10
- truthound_dashboard/schemas/notifications_advanced.py +13 -0
- truthound_dashboard/schemas/observability.py +453 -0
- truthound_dashboard/schemas/plugins.py +0 -280
- truthound_dashboard/schemas/profile.py +154 -247
- truthound_dashboard/schemas/quality_reporter.py +403 -0
- truthound_dashboard/schemas/reports.py +2 -2
- truthound_dashboard/schemas/rule_suggestion.py +8 -1
- truthound_dashboard/schemas/scan.py +4 -24
- truthound_dashboard/schemas/schedule.py +11 -3
- truthound_dashboard/schemas/schema_watcher.py +727 -0
- truthound_dashboard/schemas/source.py +17 -2
- truthound_dashboard/schemas/tiering.py +822 -0
- truthound_dashboard/schemas/triggers.py +16 -0
- truthound_dashboard/schemas/unified_alerts.py +7 -0
- truthound_dashboard/schemas/validation.py +0 -13
- truthound_dashboard/schemas/validators/base.py +41 -21
- truthound_dashboard/schemas/validators/business_rule_validators.py +244 -0
- truthound_dashboard/schemas/validators/localization_validators.py +273 -0
- truthound_dashboard/schemas/validators/ml_feature_validators.py +308 -0
- truthound_dashboard/schemas/validators/profiling_validators.py +275 -0
- truthound_dashboard/schemas/validators/referential_validators.py +312 -0
- truthound_dashboard/schemas/validators/registry.py +93 -8
- truthound_dashboard/schemas/validators/timeseries_validators.py +389 -0
- truthound_dashboard/schemas/versioning.py +1 -6
- truthound_dashboard/static/index.html +2 -2
- truthound_dashboard-1.5.1.dist-info/METADATA +312 -0
- {truthound_dashboard-1.4.4.dist-info → truthound_dashboard-1.5.1.dist-info}/RECORD +149 -148
- truthound_dashboard/core/plugins/hooks/__init__.py +0 -63
- truthound_dashboard/core/plugins/hooks/decorators.py +0 -367
- truthound_dashboard/core/plugins/hooks/manager.py +0 -403
- truthound_dashboard/core/plugins/hooks/protocols.py +0 -265
- truthound_dashboard/core/plugins/lifecycle/hot_reload.py +0 -584
- truthound_dashboard/core/reporters/junit_reporter.py +0 -233
- truthound_dashboard/core/reporters/markdown_reporter.py +0 -207
- truthound_dashboard/core/reporters/pdf_reporter.py +0 -209
- truthound_dashboard/static/assets/_baseUniq-BcrSP13d.js +0 -1
- truthound_dashboard/static/assets/arc-DlYjKwIL.js +0 -1
- truthound_dashboard/static/assets/architectureDiagram-VXUJARFQ-Bb2drbQM.js +0 -36
- truthound_dashboard/static/assets/blockDiagram-VD42YOAC-BlsPG1CH.js +0 -122
- truthound_dashboard/static/assets/c4Diagram-YG6GDRKO-B9JdUoaC.js +0 -10
- truthound_dashboard/static/assets/channel-Q6mHF1Hd.js +0 -1
- truthound_dashboard/static/assets/chunk-4BX2VUAB-DmyoPVuJ.js +0 -1
- truthound_dashboard/static/assets/chunk-55IACEB6-Bcz6Siv8.js +0 -1
- truthound_dashboard/static/assets/chunk-B4BG7PRW-Br3G5Rum.js +0 -165
- truthound_dashboard/static/assets/chunk-DI55MBZ5-DuM9c23u.js +0 -220
- truthound_dashboard/static/assets/chunk-FMBD7UC4-DNU-5mvT.js +0 -15
- truthound_dashboard/static/assets/chunk-QN33PNHL-Im2yNcmS.js +0 -1
- truthound_dashboard/static/assets/chunk-QZHKN3VN-kZr8XFm1.js +0 -1
- truthound_dashboard/static/assets/chunk-TZMSLE5B-Q__360q_.js +0 -1
- truthound_dashboard/static/assets/classDiagram-2ON5EDUG-vtixxUyK.js +0 -1
- truthound_dashboard/static/assets/classDiagram-v2-WZHVMYZB-vtixxUyK.js +0 -1
- truthound_dashboard/static/assets/clone-BOt2LwD0.js +0 -1
- truthound_dashboard/static/assets/cose-bilkent-S5V4N54A-CBDw6iac.js +0 -1
- truthound_dashboard/static/assets/dagre-6UL2VRFP-XdKqmmY9.js +0 -4
- truthound_dashboard/static/assets/diagram-PSM6KHXK-DAZ8nx9V.js +0 -24
- truthound_dashboard/static/assets/diagram-QEK2KX5R-BRvDTbGD.js +0 -43
- truthound_dashboard/static/assets/diagram-S2PKOQOG-bQcczUkl.js +0 -24
- truthound_dashboard/static/assets/erDiagram-Q2GNP2WA-DPje7VMN.js +0 -60
- truthound_dashboard/static/assets/flowDiagram-NV44I4VS-B7BVtFVS.js +0 -162
- truthound_dashboard/static/assets/ganttDiagram-JELNMOA3-D6WKSS7U.js +0 -267
- truthound_dashboard/static/assets/gitGraphDiagram-NY62KEGX-D3vtVd3y.js +0 -65
- truthound_dashboard/static/assets/graph-BKgNKZVp.js +0 -1
- truthound_dashboard/static/assets/index-C6JSrkHo.css +0 -1
- truthound_dashboard/static/assets/index-DkU82VsU.js +0 -1800
- truthound_dashboard/static/assets/infoDiagram-WHAUD3N6-DnNCT429.js +0 -2
- truthound_dashboard/static/assets/journeyDiagram-XKPGCS4Q-DGiMozqS.js +0 -139
- truthound_dashboard/static/assets/kanban-definition-3W4ZIXB7-BV2gUgli.js +0 -89
- truthound_dashboard/static/assets/katex-Cu_Erd72.js +0 -261
- truthound_dashboard/static/assets/layout-DI2MfQ5G.js +0 -1
- truthound_dashboard/static/assets/min-DYdgXVcT.js +0 -1
- truthound_dashboard/static/assets/mindmap-definition-VGOIOE7T-C7x4ruxz.js +0 -68
- truthound_dashboard/static/assets/pieDiagram-ADFJNKIX-CAJaAB9f.js +0 -30
- truthound_dashboard/static/assets/quadrantDiagram-AYHSOK5B-DeqwDI46.js +0 -7
- truthound_dashboard/static/assets/requirementDiagram-UZGBJVZJ-e3XDpZIM.js +0 -64
- truthound_dashboard/static/assets/sankeyDiagram-TZEHDZUN-CNnAv5Ux.js +0 -10
- truthound_dashboard/static/assets/sequenceDiagram-WL72ISMW-Dsne-Of3.js +0 -145
- truthound_dashboard/static/assets/stateDiagram-FKZM4ZOC-Ee0sQXyb.js +0 -1
- truthound_dashboard/static/assets/stateDiagram-v2-4FDKWEC3-B26KqW_W.js +0 -1
- truthound_dashboard/static/assets/timeline-definition-IT6M3QCI-DZYi2yl3.js +0 -61
- truthound_dashboard/static/assets/treemap-KMMF4GRG-CY3f8In2.js +0 -128
- truthound_dashboard/static/assets/unmerged_dictionaries-Dd7xcPWG.js +0 -1
- truthound_dashboard/static/assets/xychartDiagram-PRI3JC2R-CS7fydZZ.js +0 -7
- truthound_dashboard-1.4.4.dist-info/METADATA +0 -507
- {truthound_dashboard-1.4.4.dist-info → truthound_dashboard-1.5.1.dist-info}/WHEEL +0 -0
- {truthound_dashboard-1.4.4.dist-info → truthound_dashboard-1.5.1.dist-info}/entry_points.txt +0 -0
- {truthound_dashboard-1.4.4.dist-info → truthound_dashboard-1.5.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"""Compatibility bridge between old and new reporter APIs.
|
|
2
|
+
|
|
3
|
+
This module provides backward compatibility with the existing reporter
|
|
4
|
+
system while enabling gradual migration to the new interface-based
|
|
5
|
+
architecture.
|
|
6
|
+
|
|
7
|
+
The bridge handles:
|
|
8
|
+
1. Converting old Validation models to new ReportData format
|
|
9
|
+
2. Adapting new reporters to work with old generate_report calls
|
|
10
|
+
3. Providing legacy generate_report function that uses new infrastructure
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
# Old style (still works)
|
|
14
|
+
from truthound_dashboard.core.reporters import generate_report
|
|
15
|
+
report = await generate_report(validation, format="html")
|
|
16
|
+
|
|
17
|
+
# New style (recommended)
|
|
18
|
+
from truthound_dashboard.core.reporters.factory import (
|
|
19
|
+
generate_report_from_validation
|
|
20
|
+
)
|
|
21
|
+
output = await generate_report_from_validation(validation, format="html")
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import logging
|
|
27
|
+
from typing import TYPE_CHECKING, Any
|
|
28
|
+
|
|
29
|
+
from .interfaces import (
|
|
30
|
+
ReportData,
|
|
31
|
+
ReporterConfig,
|
|
32
|
+
ReportFormatType,
|
|
33
|
+
ReportOutput,
|
|
34
|
+
ReportThemeType,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
if TYPE_CHECKING:
|
|
38
|
+
from truthound_dashboard.db.models import Validation
|
|
39
|
+
|
|
40
|
+
logger = logging.getLogger(__name__)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class LegacyReportResult:
|
|
44
|
+
"""Wrapper that mimics the old ReportResult interface.
|
|
45
|
+
|
|
46
|
+
This allows new reporters to be used with code that expects
|
|
47
|
+
the old ReportResult format.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(self, output: ReportOutput, config: ReporterConfig) -> None:
|
|
51
|
+
"""Initialize from new ReportOutput.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
output: New-style report output.
|
|
55
|
+
config: Reporter configuration used.
|
|
56
|
+
"""
|
|
57
|
+
self._output = output
|
|
58
|
+
self._config = config
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def content(self) -> str | bytes:
|
|
62
|
+
return self._output.content
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def content_type(self) -> str:
|
|
66
|
+
return self._output.content_type
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def filename(self) -> str:
|
|
70
|
+
return self._output.filename
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def size_bytes(self) -> int:
|
|
74
|
+
return self._output.size_bytes
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def generation_time_ms(self) -> int:
|
|
78
|
+
return self._output.generation_time_ms
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def metadata(self) -> "LegacyReportMetadata":
|
|
82
|
+
return LegacyReportMetadata(self._output, self._config)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class LegacyReportMetadata:
|
|
86
|
+
"""Wrapper that mimics the old ReportMetadata interface."""
|
|
87
|
+
|
|
88
|
+
def __init__(self, output: ReportOutput, config: ReporterConfig) -> None:
|
|
89
|
+
self._output = output
|
|
90
|
+
self._config = config
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def title(self) -> str:
|
|
94
|
+
return self._config.title
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def generated_at(self) -> Any:
|
|
98
|
+
from datetime import datetime
|
|
99
|
+
|
|
100
|
+
return datetime.utcnow()
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def source_name(self) -> str | None:
|
|
104
|
+
return self._output.metadata.get("source_name")
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def source_id(self) -> str | None:
|
|
108
|
+
return self._output.metadata.get("source_id")
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def validation_id(self) -> str | None:
|
|
112
|
+
return self._output.metadata.get("validation_id")
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def theme(self) -> Any:
|
|
116
|
+
"""Return a theme object with .value property."""
|
|
117
|
+
from .base import ReportTheme
|
|
118
|
+
|
|
119
|
+
theme_str = self._config.theme.value
|
|
120
|
+
return ReportTheme(theme_str)
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def format(self) -> Any:
|
|
124
|
+
"""Return a format object with .value property."""
|
|
125
|
+
from .base import ReportFormat
|
|
126
|
+
|
|
127
|
+
format_str = self._output.format.value
|
|
128
|
+
return ReportFormat(format_str)
|
|
129
|
+
|
|
130
|
+
def to_dict(self) -> dict[str, Any]:
|
|
131
|
+
return {
|
|
132
|
+
"title": self.title,
|
|
133
|
+
"generated_at": self.generated_at.isoformat(),
|
|
134
|
+
"source_name": self.source_name,
|
|
135
|
+
"source_id": self.source_id,
|
|
136
|
+
"validation_id": self.validation_id,
|
|
137
|
+
"theme": self._config.theme.value,
|
|
138
|
+
"format": self._output.format.value,
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def convert_validation_to_report_data(validation: "Validation") -> ReportData:
|
|
143
|
+
"""Convert a Validation model to ReportData.
|
|
144
|
+
|
|
145
|
+
This function bridges the old Validation model with the new
|
|
146
|
+
backend-agnostic ReportData format.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
validation: Validation model from database.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
ReportData instance.
|
|
153
|
+
"""
|
|
154
|
+
return ReportData.from_validation_model(validation)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def convert_theme(theme: str | Any) -> ReportThemeType:
|
|
158
|
+
"""Convert theme string or old ReportTheme to new ReportThemeType.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
theme: Theme as string or ReportTheme enum.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
ReportThemeType enum.
|
|
165
|
+
"""
|
|
166
|
+
if isinstance(theme, ReportThemeType):
|
|
167
|
+
return theme
|
|
168
|
+
if hasattr(theme, "value"):
|
|
169
|
+
theme = theme.value
|
|
170
|
+
return ReportThemeType(theme)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def convert_format(format: str | Any) -> ReportFormatType:
|
|
174
|
+
"""Convert format string or old ReportFormat to new ReportFormatType.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
format: Format as string or ReportFormat enum.
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
ReportFormatType enum.
|
|
181
|
+
"""
|
|
182
|
+
if isinstance(format, ReportFormatType):
|
|
183
|
+
return format
|
|
184
|
+
if hasattr(format, "value"):
|
|
185
|
+
format = format.value
|
|
186
|
+
return ReportFormatType.from_string(format)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
async def legacy_generate_report(
|
|
190
|
+
validation: "Validation",
|
|
191
|
+
*,
|
|
192
|
+
format: str = "html",
|
|
193
|
+
theme: str = "professional",
|
|
194
|
+
locale: str = "en",
|
|
195
|
+
title: str | None = None,
|
|
196
|
+
include_samples: bool = True,
|
|
197
|
+
include_statistics: bool = True,
|
|
198
|
+
custom_metadata: dict[str, Any] | None = None,
|
|
199
|
+
) -> LegacyReportResult:
|
|
200
|
+
"""Generate a report using the new infrastructure but returning old format.
|
|
201
|
+
|
|
202
|
+
This function provides backward compatibility with existing code
|
|
203
|
+
that uses the old generate_report signature.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
validation: Validation model from database.
|
|
207
|
+
format: Report format (html, json, csv, etc.).
|
|
208
|
+
theme: Visual theme.
|
|
209
|
+
locale: Language locale.
|
|
210
|
+
title: Custom title.
|
|
211
|
+
include_samples: Include sample values.
|
|
212
|
+
include_statistics: Include statistics section.
|
|
213
|
+
custom_metadata: Additional metadata.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
LegacyReportResult that mimics the old ReportResult.
|
|
217
|
+
"""
|
|
218
|
+
from .factory import generate_report_from_validation
|
|
219
|
+
|
|
220
|
+
# Build config
|
|
221
|
+
config = ReporterConfig(
|
|
222
|
+
title=title or f"Validation Report - {validation.source_id}",
|
|
223
|
+
theme=convert_theme(theme),
|
|
224
|
+
locale=locale,
|
|
225
|
+
include_samples=include_samples,
|
|
226
|
+
include_statistics=include_statistics,
|
|
227
|
+
custom_options=custom_metadata or {},
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
# Convert format
|
|
231
|
+
format_type = convert_format(format)
|
|
232
|
+
|
|
233
|
+
# Generate using new infrastructure
|
|
234
|
+
output = await generate_report_from_validation(
|
|
235
|
+
validation,
|
|
236
|
+
format=format_type,
|
|
237
|
+
config=config,
|
|
238
|
+
locale=locale,
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
return LegacyReportResult(output, config)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
# Backward compatibility aliases
|
|
245
|
+
async def generate_report_compat(
|
|
246
|
+
validation: "Validation",
|
|
247
|
+
*,
|
|
248
|
+
format: str = "html",
|
|
249
|
+
theme: str = "professional",
|
|
250
|
+
locale: str = "en",
|
|
251
|
+
title: str | None = None,
|
|
252
|
+
include_samples: bool = True,
|
|
253
|
+
include_statistics: bool = True,
|
|
254
|
+
custom_metadata: dict[str, Any] | None = None,
|
|
255
|
+
) -> LegacyReportResult:
|
|
256
|
+
"""Alias for legacy_generate_report for explicit compatibility usage."""
|
|
257
|
+
return await legacy_generate_report(
|
|
258
|
+
validation,
|
|
259
|
+
format=format,
|
|
260
|
+
theme=theme,
|
|
261
|
+
locale=locale,
|
|
262
|
+
title=title,
|
|
263
|
+
include_samples=include_samples,
|
|
264
|
+
include_statistics=include_statistics,
|
|
265
|
+
custom_metadata=custom_metadata,
|
|
266
|
+
)
|
|
@@ -62,41 +62,8 @@ class CSVReporter(Reporter):
|
|
|
62
62
|
output = io.StringIO()
|
|
63
63
|
writer = csv.writer(output, delimiter=self._delimiter)
|
|
64
64
|
|
|
65
|
-
# Write
|
|
66
|
-
writer.writerow(["# Validation Report"])
|
|
67
|
-
writer.writerow(["# Source", metadata.source_name or validation.source_id])
|
|
68
|
-
writer.writerow(["# Validation ID", validation.id])
|
|
69
|
-
writer.writerow(["# Generated At", metadata.generated_at.isoformat()])
|
|
70
|
-
writer.writerow(
|
|
71
|
-
[
|
|
72
|
-
"# Status",
|
|
73
|
-
"PASSED" if validation.passed else "FAILED",
|
|
74
|
-
]
|
|
75
|
-
)
|
|
76
|
-
writer.writerow([]) # Empty row separator
|
|
77
|
-
|
|
78
|
-
# Write statistics section if requested
|
|
79
|
-
if include_statistics:
|
|
80
|
-
writer.writerow(["# Statistics"])
|
|
81
|
-
writer.writerow(["Metric", "Value"])
|
|
82
|
-
writer.writerow(["Row Count", validation.row_count or "N/A"])
|
|
83
|
-
writer.writerow(["Column Count", validation.column_count or "N/A"])
|
|
84
|
-
writer.writerow(["Total Issues", validation.total_issues or 0])
|
|
85
|
-
writer.writerow(["Critical Issues", validation.critical_issues or 0])
|
|
86
|
-
writer.writerow(["High Issues", validation.high_issues or 0])
|
|
87
|
-
writer.writerow(["Medium Issues", validation.medium_issues or 0])
|
|
88
|
-
writer.writerow(["Low Issues", validation.low_issues or 0])
|
|
89
|
-
writer.writerow(
|
|
90
|
-
[
|
|
91
|
-
"Duration (ms)",
|
|
92
|
-
validation.duration_ms if validation.duration_ms else "N/A",
|
|
93
|
-
]
|
|
94
|
-
)
|
|
95
|
-
writer.writerow([]) # Empty row separator
|
|
96
|
-
|
|
97
|
-
# Write issues section
|
|
65
|
+
# Write issues section (main data)
|
|
98
66
|
issues = self._extract_issues(validation)
|
|
99
|
-
writer.writerow(["# Issues"])
|
|
100
67
|
|
|
101
68
|
# Define headers based on options
|
|
102
69
|
headers = ["Column", "Issue Type", "Severity", "Count", "Details"]
|
|
@@ -116,7 +83,7 @@ class CSVReporter(Reporter):
|
|
|
116
83
|
issue.get("details", "") or "",
|
|
117
84
|
]
|
|
118
85
|
if include_samples:
|
|
119
|
-
samples = issue.get("sample_values"
|
|
86
|
+
samples = issue.get("sample_values") or []
|
|
120
87
|
samples_str = "; ".join(str(v)[:50] for v in samples[:5])
|
|
121
88
|
row.append(samples_str)
|
|
122
89
|
|