truthound-dashboard 1.4.4__py3-none-any.whl → 1.5.0__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.
Files changed (205) hide show
  1. truthound_dashboard/api/alerts.py +75 -86
  2. truthound_dashboard/api/anomaly.py +7 -13
  3. truthound_dashboard/api/cross_alerts.py +38 -52
  4. truthound_dashboard/api/drift.py +49 -59
  5. truthound_dashboard/api/drift_monitor.py +234 -79
  6. truthound_dashboard/api/enterprise_sampling.py +498 -0
  7. truthound_dashboard/api/history.py +57 -5
  8. truthound_dashboard/api/lineage.py +3 -48
  9. truthound_dashboard/api/maintenance.py +104 -49
  10. truthound_dashboard/api/mask.py +1 -2
  11. truthound_dashboard/api/middleware.py +2 -1
  12. truthound_dashboard/api/model_monitoring.py +435 -311
  13. truthound_dashboard/api/notifications.py +227 -191
  14. truthound_dashboard/api/notifications_advanced.py +21 -20
  15. truthound_dashboard/api/observability.py +586 -0
  16. truthound_dashboard/api/plugins.py +2 -433
  17. truthound_dashboard/api/profile.py +199 -37
  18. truthound_dashboard/api/quality_reporter.py +701 -0
  19. truthound_dashboard/api/reports.py +7 -16
  20. truthound_dashboard/api/router.py +66 -0
  21. truthound_dashboard/api/rule_suggestions.py +5 -5
  22. truthound_dashboard/api/scan.py +17 -19
  23. truthound_dashboard/api/schedules.py +85 -50
  24. truthound_dashboard/api/schema_evolution.py +6 -6
  25. truthound_dashboard/api/schema_watcher.py +667 -0
  26. truthound_dashboard/api/sources.py +98 -27
  27. truthound_dashboard/api/tiering.py +1323 -0
  28. truthound_dashboard/api/triggers.py +14 -11
  29. truthound_dashboard/api/validations.py +12 -11
  30. truthound_dashboard/api/versioning.py +1 -6
  31. truthound_dashboard/core/__init__.py +129 -3
  32. truthound_dashboard/core/actions/__init__.py +62 -0
  33. truthound_dashboard/core/actions/custom.py +426 -0
  34. truthound_dashboard/core/actions/notifications.py +910 -0
  35. truthound_dashboard/core/actions/storage.py +472 -0
  36. truthound_dashboard/core/actions/webhook.py +281 -0
  37. truthound_dashboard/core/anomaly.py +262 -67
  38. truthound_dashboard/core/anomaly_explainer.py +4 -3
  39. truthound_dashboard/core/backends/__init__.py +67 -0
  40. truthound_dashboard/core/backends/base.py +299 -0
  41. truthound_dashboard/core/backends/errors.py +191 -0
  42. truthound_dashboard/core/backends/factory.py +423 -0
  43. truthound_dashboard/core/backends/mock_backend.py +451 -0
  44. truthound_dashboard/core/backends/truthound_backend.py +718 -0
  45. truthound_dashboard/core/checkpoint/__init__.py +87 -0
  46. truthound_dashboard/core/checkpoint/adapters.py +814 -0
  47. truthound_dashboard/core/checkpoint/checkpoint.py +491 -0
  48. truthound_dashboard/core/checkpoint/runner.py +270 -0
  49. truthound_dashboard/core/connections.py +437 -10
  50. truthound_dashboard/core/converters/__init__.py +14 -0
  51. truthound_dashboard/core/converters/truthound.py +620 -0
  52. truthound_dashboard/core/cross_alerts.py +540 -320
  53. truthound_dashboard/core/datasource_factory.py +1672 -0
  54. truthound_dashboard/core/drift_monitor.py +216 -20
  55. truthound_dashboard/core/enterprise_sampling.py +1291 -0
  56. truthound_dashboard/core/interfaces/__init__.py +225 -0
  57. truthound_dashboard/core/interfaces/actions.py +652 -0
  58. truthound_dashboard/core/interfaces/base.py +247 -0
  59. truthound_dashboard/core/interfaces/checkpoint.py +676 -0
  60. truthound_dashboard/core/interfaces/protocols.py +664 -0
  61. truthound_dashboard/core/interfaces/reporters.py +650 -0
  62. truthound_dashboard/core/interfaces/routing.py +646 -0
  63. truthound_dashboard/core/interfaces/triggers.py +619 -0
  64. truthound_dashboard/core/lineage.py +407 -71
  65. truthound_dashboard/core/model_monitoring.py +431 -3
  66. truthound_dashboard/core/notifications/base.py +4 -0
  67. truthound_dashboard/core/notifications/channels.py +501 -1203
  68. truthound_dashboard/core/notifications/deduplication/__init__.py +81 -115
  69. truthound_dashboard/core/notifications/deduplication/service.py +131 -348
  70. truthound_dashboard/core/notifications/dispatcher.py +202 -11
  71. truthound_dashboard/core/notifications/escalation/__init__.py +119 -106
  72. truthound_dashboard/core/notifications/escalation/engine.py +168 -358
  73. truthound_dashboard/core/notifications/routing/__init__.py +88 -128
  74. truthound_dashboard/core/notifications/routing/engine.py +90 -317
  75. truthound_dashboard/core/notifications/stats_aggregator.py +246 -1
  76. truthound_dashboard/core/notifications/throttling/__init__.py +67 -50
  77. truthound_dashboard/core/notifications/throttling/builder.py +117 -255
  78. truthound_dashboard/core/notifications/truthound_adapter.py +842 -0
  79. truthound_dashboard/core/phase5/collaboration.py +1 -1
  80. truthound_dashboard/core/plugins/lifecycle/__init__.py +0 -13
  81. truthound_dashboard/core/quality_reporter.py +1359 -0
  82. truthound_dashboard/core/report_history.py +0 -6
  83. truthound_dashboard/core/reporters/__init__.py +175 -14
  84. truthound_dashboard/core/reporters/adapters.py +943 -0
  85. truthound_dashboard/core/reporters/base.py +0 -3
  86. truthound_dashboard/core/reporters/builtin/__init__.py +18 -0
  87. truthound_dashboard/core/reporters/builtin/csv_reporter.py +111 -0
  88. truthound_dashboard/core/reporters/builtin/html_reporter.py +270 -0
  89. truthound_dashboard/core/reporters/builtin/json_reporter.py +127 -0
  90. truthound_dashboard/core/reporters/compat.py +266 -0
  91. truthound_dashboard/core/reporters/csv_reporter.py +2 -35
  92. truthound_dashboard/core/reporters/factory.py +526 -0
  93. truthound_dashboard/core/reporters/interfaces.py +745 -0
  94. truthound_dashboard/core/reporters/registry.py +1 -10
  95. truthound_dashboard/core/scheduler.py +165 -0
  96. truthound_dashboard/core/schema_evolution.py +3 -3
  97. truthound_dashboard/core/schema_watcher.py +1528 -0
  98. truthound_dashboard/core/services.py +595 -76
  99. truthound_dashboard/core/store_manager.py +810 -0
  100. truthound_dashboard/core/streaming_anomaly.py +169 -4
  101. truthound_dashboard/core/tiering.py +1309 -0
  102. truthound_dashboard/core/triggers/evaluators.py +178 -8
  103. truthound_dashboard/core/truthound_adapter.py +2620 -197
  104. truthound_dashboard/core/unified_alerts.py +23 -20
  105. truthound_dashboard/db/__init__.py +8 -0
  106. truthound_dashboard/db/database.py +8 -2
  107. truthound_dashboard/db/models.py +944 -25
  108. truthound_dashboard/db/repository.py +2 -0
  109. truthound_dashboard/main.py +11 -0
  110. truthound_dashboard/schemas/__init__.py +177 -16
  111. truthound_dashboard/schemas/base.py +44 -23
  112. truthound_dashboard/schemas/collaboration.py +19 -6
  113. truthound_dashboard/schemas/cross_alerts.py +19 -3
  114. truthound_dashboard/schemas/drift.py +61 -55
  115. truthound_dashboard/schemas/drift_monitor.py +67 -23
  116. truthound_dashboard/schemas/enterprise_sampling.py +653 -0
  117. truthound_dashboard/schemas/lineage.py +0 -33
  118. truthound_dashboard/schemas/mask.py +10 -8
  119. truthound_dashboard/schemas/model_monitoring.py +89 -10
  120. truthound_dashboard/schemas/notifications_advanced.py +13 -0
  121. truthound_dashboard/schemas/observability.py +453 -0
  122. truthound_dashboard/schemas/plugins.py +0 -280
  123. truthound_dashboard/schemas/profile.py +154 -247
  124. truthound_dashboard/schemas/quality_reporter.py +403 -0
  125. truthound_dashboard/schemas/reports.py +2 -2
  126. truthound_dashboard/schemas/rule_suggestion.py +8 -1
  127. truthound_dashboard/schemas/scan.py +4 -24
  128. truthound_dashboard/schemas/schedule.py +11 -3
  129. truthound_dashboard/schemas/schema_watcher.py +727 -0
  130. truthound_dashboard/schemas/source.py +17 -2
  131. truthound_dashboard/schemas/tiering.py +822 -0
  132. truthound_dashboard/schemas/triggers.py +16 -0
  133. truthound_dashboard/schemas/unified_alerts.py +7 -0
  134. truthound_dashboard/schemas/validation.py +0 -13
  135. truthound_dashboard/schemas/validators/base.py +41 -21
  136. truthound_dashboard/schemas/validators/business_rule_validators.py +244 -0
  137. truthound_dashboard/schemas/validators/localization_validators.py +273 -0
  138. truthound_dashboard/schemas/validators/ml_feature_validators.py +308 -0
  139. truthound_dashboard/schemas/validators/profiling_validators.py +275 -0
  140. truthound_dashboard/schemas/validators/referential_validators.py +312 -0
  141. truthound_dashboard/schemas/validators/registry.py +93 -8
  142. truthound_dashboard/schemas/validators/timeseries_validators.py +389 -0
  143. truthound_dashboard/schemas/versioning.py +1 -6
  144. truthound_dashboard/static/index.html +2 -2
  145. truthound_dashboard-1.5.0.dist-info/METADATA +309 -0
  146. {truthound_dashboard-1.4.4.dist-info → truthound_dashboard-1.5.0.dist-info}/RECORD +149 -148
  147. truthound_dashboard/core/plugins/hooks/__init__.py +0 -63
  148. truthound_dashboard/core/plugins/hooks/decorators.py +0 -367
  149. truthound_dashboard/core/plugins/hooks/manager.py +0 -403
  150. truthound_dashboard/core/plugins/hooks/protocols.py +0 -265
  151. truthound_dashboard/core/plugins/lifecycle/hot_reload.py +0 -584
  152. truthound_dashboard/core/reporters/junit_reporter.py +0 -233
  153. truthound_dashboard/core/reporters/markdown_reporter.py +0 -207
  154. truthound_dashboard/core/reporters/pdf_reporter.py +0 -209
  155. truthound_dashboard/static/assets/_baseUniq-BcrSP13d.js +0 -1
  156. truthound_dashboard/static/assets/arc-DlYjKwIL.js +0 -1
  157. truthound_dashboard/static/assets/architectureDiagram-VXUJARFQ-Bb2drbQM.js +0 -36
  158. truthound_dashboard/static/assets/blockDiagram-VD42YOAC-BlsPG1CH.js +0 -122
  159. truthound_dashboard/static/assets/c4Diagram-YG6GDRKO-B9JdUoaC.js +0 -10
  160. truthound_dashboard/static/assets/channel-Q6mHF1Hd.js +0 -1
  161. truthound_dashboard/static/assets/chunk-4BX2VUAB-DmyoPVuJ.js +0 -1
  162. truthound_dashboard/static/assets/chunk-55IACEB6-Bcz6Siv8.js +0 -1
  163. truthound_dashboard/static/assets/chunk-B4BG7PRW-Br3G5Rum.js +0 -165
  164. truthound_dashboard/static/assets/chunk-DI55MBZ5-DuM9c23u.js +0 -220
  165. truthound_dashboard/static/assets/chunk-FMBD7UC4-DNU-5mvT.js +0 -15
  166. truthound_dashboard/static/assets/chunk-QN33PNHL-Im2yNcmS.js +0 -1
  167. truthound_dashboard/static/assets/chunk-QZHKN3VN-kZr8XFm1.js +0 -1
  168. truthound_dashboard/static/assets/chunk-TZMSLE5B-Q__360q_.js +0 -1
  169. truthound_dashboard/static/assets/classDiagram-2ON5EDUG-vtixxUyK.js +0 -1
  170. truthound_dashboard/static/assets/classDiagram-v2-WZHVMYZB-vtixxUyK.js +0 -1
  171. truthound_dashboard/static/assets/clone-BOt2LwD0.js +0 -1
  172. truthound_dashboard/static/assets/cose-bilkent-S5V4N54A-CBDw6iac.js +0 -1
  173. truthound_dashboard/static/assets/dagre-6UL2VRFP-XdKqmmY9.js +0 -4
  174. truthound_dashboard/static/assets/diagram-PSM6KHXK-DAZ8nx9V.js +0 -24
  175. truthound_dashboard/static/assets/diagram-QEK2KX5R-BRvDTbGD.js +0 -43
  176. truthound_dashboard/static/assets/diagram-S2PKOQOG-bQcczUkl.js +0 -24
  177. truthound_dashboard/static/assets/erDiagram-Q2GNP2WA-DPje7VMN.js +0 -60
  178. truthound_dashboard/static/assets/flowDiagram-NV44I4VS-B7BVtFVS.js +0 -162
  179. truthound_dashboard/static/assets/ganttDiagram-JELNMOA3-D6WKSS7U.js +0 -267
  180. truthound_dashboard/static/assets/gitGraphDiagram-NY62KEGX-D3vtVd3y.js +0 -65
  181. truthound_dashboard/static/assets/graph-BKgNKZVp.js +0 -1
  182. truthound_dashboard/static/assets/index-C6JSrkHo.css +0 -1
  183. truthound_dashboard/static/assets/index-DkU82VsU.js +0 -1800
  184. truthound_dashboard/static/assets/infoDiagram-WHAUD3N6-DnNCT429.js +0 -2
  185. truthound_dashboard/static/assets/journeyDiagram-XKPGCS4Q-DGiMozqS.js +0 -139
  186. truthound_dashboard/static/assets/kanban-definition-3W4ZIXB7-BV2gUgli.js +0 -89
  187. truthound_dashboard/static/assets/katex-Cu_Erd72.js +0 -261
  188. truthound_dashboard/static/assets/layout-DI2MfQ5G.js +0 -1
  189. truthound_dashboard/static/assets/min-DYdgXVcT.js +0 -1
  190. truthound_dashboard/static/assets/mindmap-definition-VGOIOE7T-C7x4ruxz.js +0 -68
  191. truthound_dashboard/static/assets/pieDiagram-ADFJNKIX-CAJaAB9f.js +0 -30
  192. truthound_dashboard/static/assets/quadrantDiagram-AYHSOK5B-DeqwDI46.js +0 -7
  193. truthound_dashboard/static/assets/requirementDiagram-UZGBJVZJ-e3XDpZIM.js +0 -64
  194. truthound_dashboard/static/assets/sankeyDiagram-TZEHDZUN-CNnAv5Ux.js +0 -10
  195. truthound_dashboard/static/assets/sequenceDiagram-WL72ISMW-Dsne-Of3.js +0 -145
  196. truthound_dashboard/static/assets/stateDiagram-FKZM4ZOC-Ee0sQXyb.js +0 -1
  197. truthound_dashboard/static/assets/stateDiagram-v2-4FDKWEC3-B26KqW_W.js +0 -1
  198. truthound_dashboard/static/assets/timeline-definition-IT6M3QCI-DZYi2yl3.js +0 -61
  199. truthound_dashboard/static/assets/treemap-KMMF4GRG-CY3f8In2.js +0 -128
  200. truthound_dashboard/static/assets/unmerged_dictionaries-Dd7xcPWG.js +0 -1
  201. truthound_dashboard/static/assets/xychartDiagram-PRI3JC2R-CS7fydZZ.js +0 -7
  202. truthound_dashboard-1.4.4.dist-info/METADATA +0 -507
  203. {truthound_dashboard-1.4.4.dist-info → truthound_dashboard-1.5.0.dist-info}/WHEEL +0 -0
  204. {truthound_dashboard-1.4.4.dist-info → truthound_dashboard-1.5.0.dist-info}/entry_points.txt +0 -0
  205. {truthound_dashboard-1.4.4.dist-info → truthound_dashboard-1.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,247 @@
1
+ """Base interfaces and types for truthound-dashboard.
2
+
3
+ This module defines foundational types and interfaces that are used
4
+ across all other interface modules. It provides the common building
5
+ blocks for the dashboard's abstraction layer.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from dataclasses import dataclass, field
11
+ from enum import Enum, auto
12
+ from typing import Any, Protocol, Union, runtime_checkable
13
+
14
+
15
+ # Type alias for data input - can be path string, DataSource, or DataFrame
16
+ DataInput = Union[str, Any]
17
+
18
+
19
+ class DataSourceCapability(Enum):
20
+ """Capabilities that a data source may support.
21
+
22
+ This enum defines features that data sources can declare to enable
23
+ optimizations and feature detection.
24
+ """
25
+
26
+ LAZY_EVALUATION = auto() # Supports lazy/deferred execution
27
+ SQL_PUSHDOWN = auto() # Can push operations to database
28
+ SAMPLING = auto() # Supports data sampling
29
+ STREAMING = auto() # Supports streaming processing
30
+ SCHEMA_INFERENCE = auto() # Can infer schema automatically
31
+ ROW_COUNT = auto() # Can efficiently count rows
32
+ CONNECTION_TEST = auto() # Supports connection testing
33
+ WRITE = auto() # Supports writing data
34
+ TRANSACTION = auto() # Supports transactions
35
+ BATCH_INSERT = auto() # Supports batch insert
36
+ UPSERT = auto() # Supports upsert operations
37
+
38
+
39
+ class ColumnType(str, Enum):
40
+ """Logical column types for schema definition."""
41
+
42
+ STRING = "string"
43
+ INTEGER = "integer"
44
+ FLOAT = "float"
45
+ BOOLEAN = "boolean"
46
+ DATE = "date"
47
+ DATETIME = "datetime"
48
+ TIME = "time"
49
+ DECIMAL = "decimal"
50
+ BINARY = "binary"
51
+ JSON = "json"
52
+ ARRAY = "array"
53
+ STRUCT = "struct"
54
+ UNKNOWN = "unknown"
55
+
56
+
57
+ @dataclass
58
+ class ExecutionContext:
59
+ """Context for execution operations.
60
+
61
+ Provides runtime context for validation, profiling, and other
62
+ operations. Includes configuration, environment, and metadata.
63
+
64
+ Attributes:
65
+ run_id: Unique execution identifier.
66
+ user_id: User who initiated the execution.
67
+ session_id: Session identifier.
68
+ environment: Environment variables (may contain secrets).
69
+ metadata: Additional metadata.
70
+ tags: Tags for categorization.
71
+ timeout_seconds: Execution timeout.
72
+ parallel: Enable parallel execution.
73
+ max_workers: Max parallel workers.
74
+ """
75
+
76
+ run_id: str = ""
77
+ user_id: str | None = None
78
+ session_id: str | None = None
79
+ environment: dict[str, str] = field(default_factory=dict)
80
+ metadata: dict[str, Any] = field(default_factory=dict)
81
+ tags: dict[str, str] = field(default_factory=dict)
82
+ timeout_seconds: int = 300
83
+ parallel: bool = False
84
+ max_workers: int = 4
85
+
86
+ def to_dict(self) -> dict[str, Any]:
87
+ """Convert to dictionary (excluding secrets)."""
88
+ return {
89
+ "run_id": self.run_id,
90
+ "user_id": self.user_id,
91
+ "session_id": self.session_id,
92
+ "metadata": self.metadata,
93
+ "tags": self.tags,
94
+ "timeout_seconds": self.timeout_seconds,
95
+ "parallel": self.parallel,
96
+ "max_workers": self.max_workers,
97
+ }
98
+
99
+
100
+ @runtime_checkable
101
+ class DataSourceProtocol(Protocol):
102
+ """Protocol for data source objects.
103
+
104
+ Any object that provides access to tabular data should implement
105
+ this interface. This abstracts away the specific DataSource
106
+ implementation from truthound or other libraries.
107
+ """
108
+
109
+ @property
110
+ def name(self) -> str:
111
+ """Get the data source name."""
112
+ ...
113
+
114
+ @property
115
+ def columns(self) -> list[str]:
116
+ """Get list of column names."""
117
+ ...
118
+
119
+ @property
120
+ def row_count(self) -> int | None:
121
+ """Get row count if available."""
122
+ ...
123
+
124
+ @property
125
+ def capabilities(self) -> set[DataSourceCapability]:
126
+ """Get the capabilities of this data source."""
127
+ ...
128
+
129
+ def to_polars_lazyframe(self) -> Any:
130
+ """Convert to Polars LazyFrame for processing."""
131
+ ...
132
+
133
+
134
+ @runtime_checkable
135
+ class ResultProtocol(Protocol):
136
+ """Protocol for result objects.
137
+
138
+ All result types should implement this base protocol for
139
+ consistent serialization and access.
140
+ """
141
+
142
+ def to_dict(self) -> dict[str, Any]:
143
+ """Convert to dictionary."""
144
+ ...
145
+
146
+
147
+ @dataclass
148
+ class ColumnSchema:
149
+ """Schema definition for a single column.
150
+
151
+ Attributes:
152
+ name: Column name.
153
+ dtype: Data type.
154
+ nullable: Whether null values are allowed.
155
+ unique: Whether values must be unique.
156
+ min_value: Minimum value (for numeric/date).
157
+ max_value: Maximum value (for numeric/date).
158
+ allowed_values: Set of allowed values (for categorical).
159
+ pattern: Regex pattern (for string).
160
+ min_length: Minimum string length.
161
+ max_length: Maximum string length.
162
+ description: Column description.
163
+ metadata: Additional metadata.
164
+ """
165
+
166
+ name: str
167
+ dtype: ColumnType = ColumnType.UNKNOWN
168
+ nullable: bool = True
169
+ unique: bool = False
170
+ min_value: Any | None = None
171
+ max_value: Any | None = None
172
+ allowed_values: list[Any] | None = None
173
+ pattern: str | None = None
174
+ min_length: int | None = None
175
+ max_length: int | None = None
176
+ description: str = ""
177
+ metadata: dict[str, Any] = field(default_factory=dict)
178
+
179
+ def to_dict(self) -> dict[str, Any]:
180
+ """Convert to dictionary."""
181
+ result = {
182
+ "name": self.name,
183
+ "dtype": self.dtype.value,
184
+ "nullable": self.nullable,
185
+ "unique": self.unique,
186
+ }
187
+ if self.min_value is not None:
188
+ result["min_value"] = self.min_value
189
+ if self.max_value is not None:
190
+ result["max_value"] = self.max_value
191
+ if self.allowed_values:
192
+ result["allowed_values"] = self.allowed_values
193
+ if self.pattern:
194
+ result["pattern"] = self.pattern
195
+ if self.min_length is not None:
196
+ result["min_length"] = self.min_length
197
+ if self.max_length is not None:
198
+ result["max_length"] = self.max_length
199
+ if self.description:
200
+ result["description"] = self.description
201
+ if self.metadata:
202
+ result["metadata"] = self.metadata
203
+ return result
204
+
205
+
206
+ @dataclass
207
+ class TableSchema:
208
+ """Schema definition for a table/dataset.
209
+
210
+ Attributes:
211
+ name: Table/dataset name.
212
+ columns: Column schemas.
213
+ primary_key: Primary key column(s).
214
+ version: Schema version.
215
+ description: Table description.
216
+ metadata: Additional metadata.
217
+ """
218
+
219
+ name: str = ""
220
+ columns: list[ColumnSchema] = field(default_factory=list)
221
+ primary_key: list[str] = field(default_factory=list)
222
+ version: str = "1.0"
223
+ description: str = ""
224
+ metadata: dict[str, Any] = field(default_factory=dict)
225
+
226
+ def get_column(self, name: str) -> ColumnSchema | None:
227
+ """Get column schema by name."""
228
+ for col in self.columns:
229
+ if col.name == name:
230
+ return col
231
+ return None
232
+
233
+ @property
234
+ def column_names(self) -> list[str]:
235
+ """Get list of column names."""
236
+ return [col.name for col in self.columns]
237
+
238
+ def to_dict(self) -> dict[str, Any]:
239
+ """Convert to dictionary."""
240
+ return {
241
+ "name": self.name,
242
+ "columns": [col.to_dict() for col in self.columns],
243
+ "primary_key": self.primary_key,
244
+ "version": self.version,
245
+ "description": self.description,
246
+ "metadata": self.metadata,
247
+ }