truthound 1.0.8__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 (877) hide show
  1. truthound/__init__.py +162 -0
  2. truthound/adapters.py +100 -0
  3. truthound/api.py +365 -0
  4. truthound/audit/__init__.py +248 -0
  5. truthound/audit/core.py +967 -0
  6. truthound/audit/filters.py +620 -0
  7. truthound/audit/formatters.py +707 -0
  8. truthound/audit/logger.py +902 -0
  9. truthound/audit/middleware.py +571 -0
  10. truthound/audit/storage.py +1083 -0
  11. truthound/benchmark/__init__.py +123 -0
  12. truthound/benchmark/base.py +757 -0
  13. truthound/benchmark/comparison.py +635 -0
  14. truthound/benchmark/generators.py +706 -0
  15. truthound/benchmark/reporters.py +718 -0
  16. truthound/benchmark/runner.py +635 -0
  17. truthound/benchmark/scenarios.py +712 -0
  18. truthound/cache.py +252 -0
  19. truthound/checkpoint/__init__.py +136 -0
  20. truthound/checkpoint/actions/__init__.py +164 -0
  21. truthound/checkpoint/actions/base.py +324 -0
  22. truthound/checkpoint/actions/custom.py +234 -0
  23. truthound/checkpoint/actions/discord_notify.py +290 -0
  24. truthound/checkpoint/actions/email_notify.py +405 -0
  25. truthound/checkpoint/actions/github_action.py +406 -0
  26. truthound/checkpoint/actions/opsgenie.py +1499 -0
  27. truthound/checkpoint/actions/pagerduty.py +226 -0
  28. truthound/checkpoint/actions/slack_notify.py +233 -0
  29. truthound/checkpoint/actions/store_result.py +249 -0
  30. truthound/checkpoint/actions/teams_notify.py +1570 -0
  31. truthound/checkpoint/actions/telegram_notify.py +419 -0
  32. truthound/checkpoint/actions/update_docs.py +552 -0
  33. truthound/checkpoint/actions/webhook.py +293 -0
  34. truthound/checkpoint/analytics/__init__.py +147 -0
  35. truthound/checkpoint/analytics/aggregations/__init__.py +23 -0
  36. truthound/checkpoint/analytics/aggregations/rollup.py +481 -0
  37. truthound/checkpoint/analytics/aggregations/time_bucket.py +306 -0
  38. truthound/checkpoint/analytics/analyzers/__init__.py +17 -0
  39. truthound/checkpoint/analytics/analyzers/anomaly.py +386 -0
  40. truthound/checkpoint/analytics/analyzers/base.py +270 -0
  41. truthound/checkpoint/analytics/analyzers/forecast.py +421 -0
  42. truthound/checkpoint/analytics/analyzers/trend.py +314 -0
  43. truthound/checkpoint/analytics/models.py +292 -0
  44. truthound/checkpoint/analytics/protocols.py +549 -0
  45. truthound/checkpoint/analytics/service.py +718 -0
  46. truthound/checkpoint/analytics/stores/__init__.py +16 -0
  47. truthound/checkpoint/analytics/stores/base.py +306 -0
  48. truthound/checkpoint/analytics/stores/memory_store.py +353 -0
  49. truthound/checkpoint/analytics/stores/sqlite_store.py +557 -0
  50. truthound/checkpoint/analytics/stores/timescale_store.py +501 -0
  51. truthound/checkpoint/async_actions.py +794 -0
  52. truthound/checkpoint/async_base.py +708 -0
  53. truthound/checkpoint/async_checkpoint.py +617 -0
  54. truthound/checkpoint/async_runner.py +639 -0
  55. truthound/checkpoint/checkpoint.py +527 -0
  56. truthound/checkpoint/ci/__init__.py +61 -0
  57. truthound/checkpoint/ci/detector.py +355 -0
  58. truthound/checkpoint/ci/reporter.py +436 -0
  59. truthound/checkpoint/ci/templates.py +454 -0
  60. truthound/checkpoint/circuitbreaker/__init__.py +133 -0
  61. truthound/checkpoint/circuitbreaker/breaker.py +542 -0
  62. truthound/checkpoint/circuitbreaker/core.py +252 -0
  63. truthound/checkpoint/circuitbreaker/detection.py +459 -0
  64. truthound/checkpoint/circuitbreaker/middleware.py +389 -0
  65. truthound/checkpoint/circuitbreaker/registry.py +357 -0
  66. truthound/checkpoint/distributed/__init__.py +139 -0
  67. truthound/checkpoint/distributed/backends/__init__.py +35 -0
  68. truthound/checkpoint/distributed/backends/celery_backend.py +503 -0
  69. truthound/checkpoint/distributed/backends/kubernetes_backend.py +696 -0
  70. truthound/checkpoint/distributed/backends/local_backend.py +397 -0
  71. truthound/checkpoint/distributed/backends/ray_backend.py +625 -0
  72. truthound/checkpoint/distributed/base.py +774 -0
  73. truthound/checkpoint/distributed/orchestrator.py +765 -0
  74. truthound/checkpoint/distributed/protocols.py +842 -0
  75. truthound/checkpoint/distributed/registry.py +449 -0
  76. truthound/checkpoint/idempotency/__init__.py +120 -0
  77. truthound/checkpoint/idempotency/core.py +295 -0
  78. truthound/checkpoint/idempotency/fingerprint.py +454 -0
  79. truthound/checkpoint/idempotency/locking.py +604 -0
  80. truthound/checkpoint/idempotency/service.py +592 -0
  81. truthound/checkpoint/idempotency/stores.py +653 -0
  82. truthound/checkpoint/monitoring/__init__.py +134 -0
  83. truthound/checkpoint/monitoring/aggregators/__init__.py +15 -0
  84. truthound/checkpoint/monitoring/aggregators/base.py +372 -0
  85. truthound/checkpoint/monitoring/aggregators/realtime.py +300 -0
  86. truthound/checkpoint/monitoring/aggregators/window.py +493 -0
  87. truthound/checkpoint/monitoring/collectors/__init__.py +17 -0
  88. truthound/checkpoint/monitoring/collectors/base.py +257 -0
  89. truthound/checkpoint/monitoring/collectors/memory_collector.py +617 -0
  90. truthound/checkpoint/monitoring/collectors/prometheus_collector.py +451 -0
  91. truthound/checkpoint/monitoring/collectors/redis_collector.py +518 -0
  92. truthound/checkpoint/monitoring/events.py +410 -0
  93. truthound/checkpoint/monitoring/protocols.py +636 -0
  94. truthound/checkpoint/monitoring/service.py +578 -0
  95. truthound/checkpoint/monitoring/views/__init__.py +17 -0
  96. truthound/checkpoint/monitoring/views/base.py +172 -0
  97. truthound/checkpoint/monitoring/views/queue_view.py +220 -0
  98. truthound/checkpoint/monitoring/views/task_view.py +240 -0
  99. truthound/checkpoint/monitoring/views/worker_view.py +263 -0
  100. truthound/checkpoint/registry.py +337 -0
  101. truthound/checkpoint/runner.py +356 -0
  102. truthound/checkpoint/transaction/__init__.py +133 -0
  103. truthound/checkpoint/transaction/base.py +389 -0
  104. truthound/checkpoint/transaction/compensatable.py +537 -0
  105. truthound/checkpoint/transaction/coordinator.py +576 -0
  106. truthound/checkpoint/transaction/executor.py +622 -0
  107. truthound/checkpoint/transaction/idempotency.py +534 -0
  108. truthound/checkpoint/transaction/saga/__init__.py +143 -0
  109. truthound/checkpoint/transaction/saga/builder.py +584 -0
  110. truthound/checkpoint/transaction/saga/definition.py +515 -0
  111. truthound/checkpoint/transaction/saga/event_store.py +542 -0
  112. truthound/checkpoint/transaction/saga/patterns.py +833 -0
  113. truthound/checkpoint/transaction/saga/runner.py +718 -0
  114. truthound/checkpoint/transaction/saga/state_machine.py +793 -0
  115. truthound/checkpoint/transaction/saga/strategies.py +780 -0
  116. truthound/checkpoint/transaction/saga/testing.py +886 -0
  117. truthound/checkpoint/triggers/__init__.py +58 -0
  118. truthound/checkpoint/triggers/base.py +237 -0
  119. truthound/checkpoint/triggers/event.py +385 -0
  120. truthound/checkpoint/triggers/schedule.py +355 -0
  121. truthound/cli.py +2358 -0
  122. truthound/cli_modules/__init__.py +124 -0
  123. truthound/cli_modules/advanced/__init__.py +45 -0
  124. truthound/cli_modules/advanced/benchmark.py +343 -0
  125. truthound/cli_modules/advanced/docs.py +225 -0
  126. truthound/cli_modules/advanced/lineage.py +209 -0
  127. truthound/cli_modules/advanced/ml.py +320 -0
  128. truthound/cli_modules/advanced/realtime.py +196 -0
  129. truthound/cli_modules/checkpoint/__init__.py +46 -0
  130. truthound/cli_modules/checkpoint/init.py +114 -0
  131. truthound/cli_modules/checkpoint/list.py +71 -0
  132. truthound/cli_modules/checkpoint/run.py +159 -0
  133. truthound/cli_modules/checkpoint/validate.py +67 -0
  134. truthound/cli_modules/common/__init__.py +71 -0
  135. truthound/cli_modules/common/errors.py +414 -0
  136. truthound/cli_modules/common/options.py +419 -0
  137. truthound/cli_modules/common/output.py +507 -0
  138. truthound/cli_modules/common/protocol.py +552 -0
  139. truthound/cli_modules/core/__init__.py +48 -0
  140. truthound/cli_modules/core/check.py +123 -0
  141. truthound/cli_modules/core/compare.py +104 -0
  142. truthound/cli_modules/core/learn.py +57 -0
  143. truthound/cli_modules/core/mask.py +77 -0
  144. truthound/cli_modules/core/profile.py +65 -0
  145. truthound/cli_modules/core/scan.py +61 -0
  146. truthound/cli_modules/profiler/__init__.py +51 -0
  147. truthound/cli_modules/profiler/auto_profile.py +175 -0
  148. truthound/cli_modules/profiler/metadata.py +107 -0
  149. truthound/cli_modules/profiler/suite.py +283 -0
  150. truthound/cli_modules/registry.py +431 -0
  151. truthound/cli_modules/scaffolding/__init__.py +89 -0
  152. truthound/cli_modules/scaffolding/base.py +631 -0
  153. truthound/cli_modules/scaffolding/commands.py +545 -0
  154. truthound/cli_modules/scaffolding/plugins.py +1072 -0
  155. truthound/cli_modules/scaffolding/reporters.py +594 -0
  156. truthound/cli_modules/scaffolding/validators.py +1127 -0
  157. truthound/common/__init__.py +18 -0
  158. truthound/common/resilience/__init__.py +130 -0
  159. truthound/common/resilience/bulkhead.py +266 -0
  160. truthound/common/resilience/circuit_breaker.py +516 -0
  161. truthound/common/resilience/composite.py +332 -0
  162. truthound/common/resilience/config.py +292 -0
  163. truthound/common/resilience/protocols.py +217 -0
  164. truthound/common/resilience/rate_limiter.py +404 -0
  165. truthound/common/resilience/retry.py +341 -0
  166. truthound/datadocs/__init__.py +260 -0
  167. truthound/datadocs/base.py +571 -0
  168. truthound/datadocs/builder.py +761 -0
  169. truthound/datadocs/charts.py +764 -0
  170. truthound/datadocs/dashboard/__init__.py +63 -0
  171. truthound/datadocs/dashboard/app.py +576 -0
  172. truthound/datadocs/dashboard/components.py +584 -0
  173. truthound/datadocs/dashboard/state.py +240 -0
  174. truthound/datadocs/engine/__init__.py +46 -0
  175. truthound/datadocs/engine/context.py +376 -0
  176. truthound/datadocs/engine/pipeline.py +618 -0
  177. truthound/datadocs/engine/registry.py +469 -0
  178. truthound/datadocs/exporters/__init__.py +49 -0
  179. truthound/datadocs/exporters/base.py +198 -0
  180. truthound/datadocs/exporters/html.py +178 -0
  181. truthound/datadocs/exporters/json_exporter.py +253 -0
  182. truthound/datadocs/exporters/markdown.py +284 -0
  183. truthound/datadocs/exporters/pdf.py +392 -0
  184. truthound/datadocs/i18n/__init__.py +86 -0
  185. truthound/datadocs/i18n/catalog.py +960 -0
  186. truthound/datadocs/i18n/formatting.py +505 -0
  187. truthound/datadocs/i18n/loader.py +256 -0
  188. truthound/datadocs/i18n/plurals.py +378 -0
  189. truthound/datadocs/renderers/__init__.py +42 -0
  190. truthound/datadocs/renderers/base.py +401 -0
  191. truthound/datadocs/renderers/custom.py +342 -0
  192. truthound/datadocs/renderers/jinja.py +697 -0
  193. truthound/datadocs/sections.py +736 -0
  194. truthound/datadocs/styles.py +931 -0
  195. truthound/datadocs/themes/__init__.py +101 -0
  196. truthound/datadocs/themes/base.py +336 -0
  197. truthound/datadocs/themes/default.py +417 -0
  198. truthound/datadocs/themes/enterprise.py +419 -0
  199. truthound/datadocs/themes/loader.py +336 -0
  200. truthound/datadocs/themes.py +301 -0
  201. truthound/datadocs/transformers/__init__.py +57 -0
  202. truthound/datadocs/transformers/base.py +268 -0
  203. truthound/datadocs/transformers/enrichers.py +544 -0
  204. truthound/datadocs/transformers/filters.py +447 -0
  205. truthound/datadocs/transformers/i18n.py +468 -0
  206. truthound/datadocs/versioning/__init__.py +62 -0
  207. truthound/datadocs/versioning/diff.py +639 -0
  208. truthound/datadocs/versioning/storage.py +497 -0
  209. truthound/datadocs/versioning/version.py +358 -0
  210. truthound/datasources/__init__.py +223 -0
  211. truthound/datasources/_async_protocols.py +222 -0
  212. truthound/datasources/_protocols.py +159 -0
  213. truthound/datasources/adapters.py +428 -0
  214. truthound/datasources/async_base.py +599 -0
  215. truthound/datasources/async_factory.py +511 -0
  216. truthound/datasources/base.py +516 -0
  217. truthound/datasources/factory.py +433 -0
  218. truthound/datasources/nosql/__init__.py +47 -0
  219. truthound/datasources/nosql/base.py +487 -0
  220. truthound/datasources/nosql/elasticsearch.py +801 -0
  221. truthound/datasources/nosql/mongodb.py +636 -0
  222. truthound/datasources/pandas_optimized.py +582 -0
  223. truthound/datasources/pandas_source.py +216 -0
  224. truthound/datasources/polars_source.py +395 -0
  225. truthound/datasources/spark_source.py +479 -0
  226. truthound/datasources/sql/__init__.py +154 -0
  227. truthound/datasources/sql/base.py +710 -0
  228. truthound/datasources/sql/bigquery.py +410 -0
  229. truthound/datasources/sql/cloud_base.py +199 -0
  230. truthound/datasources/sql/databricks.py +471 -0
  231. truthound/datasources/sql/mysql.py +316 -0
  232. truthound/datasources/sql/oracle.py +427 -0
  233. truthound/datasources/sql/postgresql.py +321 -0
  234. truthound/datasources/sql/redshift.py +479 -0
  235. truthound/datasources/sql/snowflake.py +439 -0
  236. truthound/datasources/sql/sqlite.py +286 -0
  237. truthound/datasources/sql/sqlserver.py +437 -0
  238. truthound/datasources/streaming/__init__.py +47 -0
  239. truthound/datasources/streaming/base.py +350 -0
  240. truthound/datasources/streaming/kafka.py +670 -0
  241. truthound/decorators.py +98 -0
  242. truthound/docs/__init__.py +69 -0
  243. truthound/docs/extractor.py +971 -0
  244. truthound/docs/generator.py +601 -0
  245. truthound/docs/parser.py +1037 -0
  246. truthound/docs/renderer.py +999 -0
  247. truthound/drift/__init__.py +22 -0
  248. truthound/drift/compare.py +189 -0
  249. truthound/drift/detectors.py +464 -0
  250. truthound/drift/report.py +160 -0
  251. truthound/execution/__init__.py +65 -0
  252. truthound/execution/_protocols.py +324 -0
  253. truthound/execution/base.py +576 -0
  254. truthound/execution/distributed/__init__.py +179 -0
  255. truthound/execution/distributed/aggregations.py +731 -0
  256. truthound/execution/distributed/arrow_bridge.py +817 -0
  257. truthound/execution/distributed/base.py +550 -0
  258. truthound/execution/distributed/dask_engine.py +976 -0
  259. truthound/execution/distributed/mixins.py +766 -0
  260. truthound/execution/distributed/protocols.py +756 -0
  261. truthound/execution/distributed/ray_engine.py +1127 -0
  262. truthound/execution/distributed/registry.py +446 -0
  263. truthound/execution/distributed/spark_engine.py +1011 -0
  264. truthound/execution/distributed/validator_adapter.py +682 -0
  265. truthound/execution/pandas_engine.py +401 -0
  266. truthound/execution/polars_engine.py +497 -0
  267. truthound/execution/pushdown/__init__.py +230 -0
  268. truthound/execution/pushdown/ast.py +1550 -0
  269. truthound/execution/pushdown/builder.py +1550 -0
  270. truthound/execution/pushdown/dialects.py +1072 -0
  271. truthound/execution/pushdown/executor.py +829 -0
  272. truthound/execution/pushdown/optimizer.py +1041 -0
  273. truthound/execution/sql_engine.py +518 -0
  274. truthound/infrastructure/__init__.py +189 -0
  275. truthound/infrastructure/audit.py +1515 -0
  276. truthound/infrastructure/config.py +1133 -0
  277. truthound/infrastructure/encryption.py +1132 -0
  278. truthound/infrastructure/logging.py +1503 -0
  279. truthound/infrastructure/metrics.py +1220 -0
  280. truthound/lineage/__init__.py +89 -0
  281. truthound/lineage/base.py +746 -0
  282. truthound/lineage/impact_analysis.py +474 -0
  283. truthound/lineage/integrations/__init__.py +22 -0
  284. truthound/lineage/integrations/openlineage.py +548 -0
  285. truthound/lineage/tracker.py +512 -0
  286. truthound/lineage/visualization/__init__.py +33 -0
  287. truthound/lineage/visualization/protocols.py +145 -0
  288. truthound/lineage/visualization/renderers/__init__.py +20 -0
  289. truthound/lineage/visualization/renderers/cytoscape.py +329 -0
  290. truthound/lineage/visualization/renderers/d3.py +331 -0
  291. truthound/lineage/visualization/renderers/graphviz.py +276 -0
  292. truthound/lineage/visualization/renderers/mermaid.py +308 -0
  293. truthound/maskers.py +113 -0
  294. truthound/ml/__init__.py +124 -0
  295. truthound/ml/anomaly_models/__init__.py +31 -0
  296. truthound/ml/anomaly_models/ensemble.py +362 -0
  297. truthound/ml/anomaly_models/isolation_forest.py +444 -0
  298. truthound/ml/anomaly_models/statistical.py +392 -0
  299. truthound/ml/base.py +1178 -0
  300. truthound/ml/drift_detection/__init__.py +26 -0
  301. truthound/ml/drift_detection/concept.py +381 -0
  302. truthound/ml/drift_detection/distribution.py +361 -0
  303. truthound/ml/drift_detection/feature.py +442 -0
  304. truthound/ml/drift_detection/multivariate.py +495 -0
  305. truthound/ml/monitoring/__init__.py +88 -0
  306. truthound/ml/monitoring/alerting/__init__.py +33 -0
  307. truthound/ml/monitoring/alerting/handlers.py +427 -0
  308. truthound/ml/monitoring/alerting/rules.py +508 -0
  309. truthound/ml/monitoring/collectors/__init__.py +19 -0
  310. truthound/ml/monitoring/collectors/composite.py +105 -0
  311. truthound/ml/monitoring/collectors/drift.py +324 -0
  312. truthound/ml/monitoring/collectors/performance.py +179 -0
  313. truthound/ml/monitoring/collectors/quality.py +369 -0
  314. truthound/ml/monitoring/monitor.py +536 -0
  315. truthound/ml/monitoring/protocols.py +451 -0
  316. truthound/ml/monitoring/stores/__init__.py +15 -0
  317. truthound/ml/monitoring/stores/memory.py +201 -0
  318. truthound/ml/monitoring/stores/prometheus.py +296 -0
  319. truthound/ml/rule_learning/__init__.py +25 -0
  320. truthound/ml/rule_learning/constraint_miner.py +443 -0
  321. truthound/ml/rule_learning/pattern_learner.py +499 -0
  322. truthound/ml/rule_learning/profile_learner.py +462 -0
  323. truthound/multitenancy/__init__.py +326 -0
  324. truthound/multitenancy/core.py +852 -0
  325. truthound/multitenancy/integration.py +597 -0
  326. truthound/multitenancy/isolation.py +630 -0
  327. truthound/multitenancy/manager.py +770 -0
  328. truthound/multitenancy/middleware.py +765 -0
  329. truthound/multitenancy/quota.py +537 -0
  330. truthound/multitenancy/resolvers.py +603 -0
  331. truthound/multitenancy/storage.py +703 -0
  332. truthound/observability/__init__.py +307 -0
  333. truthound/observability/context.py +531 -0
  334. truthound/observability/instrumentation.py +611 -0
  335. truthound/observability/logging.py +887 -0
  336. truthound/observability/metrics.py +1157 -0
  337. truthound/observability/tracing/__init__.py +178 -0
  338. truthound/observability/tracing/baggage.py +310 -0
  339. truthound/observability/tracing/config.py +426 -0
  340. truthound/observability/tracing/exporter.py +787 -0
  341. truthound/observability/tracing/integration.py +1018 -0
  342. truthound/observability/tracing/otel/__init__.py +146 -0
  343. truthound/observability/tracing/otel/adapter.py +982 -0
  344. truthound/observability/tracing/otel/bridge.py +1177 -0
  345. truthound/observability/tracing/otel/compat.py +681 -0
  346. truthound/observability/tracing/otel/config.py +691 -0
  347. truthound/observability/tracing/otel/detection.py +327 -0
  348. truthound/observability/tracing/otel/protocols.py +426 -0
  349. truthound/observability/tracing/processor.py +561 -0
  350. truthound/observability/tracing/propagator.py +757 -0
  351. truthound/observability/tracing/provider.py +569 -0
  352. truthound/observability/tracing/resource.py +515 -0
  353. truthound/observability/tracing/sampler.py +487 -0
  354. truthound/observability/tracing/span.py +676 -0
  355. truthound/plugins/__init__.py +198 -0
  356. truthound/plugins/base.py +599 -0
  357. truthound/plugins/cli.py +680 -0
  358. truthound/plugins/dependencies/__init__.py +42 -0
  359. truthound/plugins/dependencies/graph.py +422 -0
  360. truthound/plugins/dependencies/resolver.py +417 -0
  361. truthound/plugins/discovery.py +379 -0
  362. truthound/plugins/docs/__init__.py +46 -0
  363. truthound/plugins/docs/extractor.py +444 -0
  364. truthound/plugins/docs/renderer.py +499 -0
  365. truthound/plugins/enterprise_manager.py +877 -0
  366. truthound/plugins/examples/__init__.py +19 -0
  367. truthound/plugins/examples/custom_validators.py +317 -0
  368. truthound/plugins/examples/slack_notifier.py +312 -0
  369. truthound/plugins/examples/xml_reporter.py +254 -0
  370. truthound/plugins/hooks.py +558 -0
  371. truthound/plugins/lifecycle/__init__.py +43 -0
  372. truthound/plugins/lifecycle/hot_reload.py +402 -0
  373. truthound/plugins/lifecycle/manager.py +371 -0
  374. truthound/plugins/manager.py +736 -0
  375. truthound/plugins/registry.py +338 -0
  376. truthound/plugins/security/__init__.py +93 -0
  377. truthound/plugins/security/exceptions.py +332 -0
  378. truthound/plugins/security/policies.py +348 -0
  379. truthound/plugins/security/protocols.py +643 -0
  380. truthound/plugins/security/sandbox/__init__.py +45 -0
  381. truthound/plugins/security/sandbox/context.py +158 -0
  382. truthound/plugins/security/sandbox/engines/__init__.py +19 -0
  383. truthound/plugins/security/sandbox/engines/container.py +379 -0
  384. truthound/plugins/security/sandbox/engines/noop.py +144 -0
  385. truthound/plugins/security/sandbox/engines/process.py +336 -0
  386. truthound/plugins/security/sandbox/factory.py +211 -0
  387. truthound/plugins/security/signing/__init__.py +57 -0
  388. truthound/plugins/security/signing/service.py +330 -0
  389. truthound/plugins/security/signing/trust_store.py +368 -0
  390. truthound/plugins/security/signing/verifier.py +459 -0
  391. truthound/plugins/versioning/__init__.py +41 -0
  392. truthound/plugins/versioning/constraints.py +297 -0
  393. truthound/plugins/versioning/resolver.py +329 -0
  394. truthound/profiler/__init__.py +1729 -0
  395. truthound/profiler/_lazy.py +452 -0
  396. truthound/profiler/ab_testing/__init__.py +80 -0
  397. truthound/profiler/ab_testing/analysis.py +449 -0
  398. truthound/profiler/ab_testing/base.py +257 -0
  399. truthound/profiler/ab_testing/experiment.py +395 -0
  400. truthound/profiler/ab_testing/tracking.py +368 -0
  401. truthound/profiler/auto_threshold.py +1170 -0
  402. truthound/profiler/base.py +579 -0
  403. truthound/profiler/cache_patterns.py +911 -0
  404. truthound/profiler/caching.py +1303 -0
  405. truthound/profiler/column_profiler.py +712 -0
  406. truthound/profiler/comparison.py +1007 -0
  407. truthound/profiler/custom_patterns.py +1170 -0
  408. truthound/profiler/dashboard/__init__.py +50 -0
  409. truthound/profiler/dashboard/app.py +476 -0
  410. truthound/profiler/dashboard/components.py +457 -0
  411. truthound/profiler/dashboard/config.py +72 -0
  412. truthound/profiler/distributed/__init__.py +83 -0
  413. truthound/profiler/distributed/base.py +281 -0
  414. truthound/profiler/distributed/dask_backend.py +498 -0
  415. truthound/profiler/distributed/local_backend.py +293 -0
  416. truthound/profiler/distributed/profiler.py +304 -0
  417. truthound/profiler/distributed/ray_backend.py +374 -0
  418. truthound/profiler/distributed/spark_backend.py +375 -0
  419. truthound/profiler/distributed.py +1366 -0
  420. truthound/profiler/enterprise_sampling.py +1065 -0
  421. truthound/profiler/errors.py +488 -0
  422. truthound/profiler/evolution/__init__.py +91 -0
  423. truthound/profiler/evolution/alerts.py +426 -0
  424. truthound/profiler/evolution/changes.py +206 -0
  425. truthound/profiler/evolution/compatibility.py +365 -0
  426. truthound/profiler/evolution/detector.py +372 -0
  427. truthound/profiler/evolution/protocols.py +121 -0
  428. truthound/profiler/generators/__init__.py +48 -0
  429. truthound/profiler/generators/base.py +384 -0
  430. truthound/profiler/generators/ml_rules.py +375 -0
  431. truthound/profiler/generators/pattern_rules.py +384 -0
  432. truthound/profiler/generators/schema_rules.py +267 -0
  433. truthound/profiler/generators/stats_rules.py +324 -0
  434. truthound/profiler/generators/suite_generator.py +857 -0
  435. truthound/profiler/i18n.py +1542 -0
  436. truthound/profiler/incremental.py +554 -0
  437. truthound/profiler/incremental_validation.py +1710 -0
  438. truthound/profiler/integration/__init__.py +73 -0
  439. truthound/profiler/integration/adapters.py +345 -0
  440. truthound/profiler/integration/context.py +371 -0
  441. truthound/profiler/integration/executor.py +527 -0
  442. truthound/profiler/integration/naming.py +75 -0
  443. truthound/profiler/integration/protocols.py +243 -0
  444. truthound/profiler/memory.py +1185 -0
  445. truthound/profiler/migration/__init__.py +60 -0
  446. truthound/profiler/migration/base.py +345 -0
  447. truthound/profiler/migration/manager.py +444 -0
  448. truthound/profiler/migration/v1_0_to_v1_1.py +484 -0
  449. truthound/profiler/ml/__init__.py +73 -0
  450. truthound/profiler/ml/base.py +244 -0
  451. truthound/profiler/ml/classifier.py +507 -0
  452. truthound/profiler/ml/feature_extraction.py +604 -0
  453. truthound/profiler/ml/pretrained.py +448 -0
  454. truthound/profiler/ml_inference.py +1276 -0
  455. truthound/profiler/native_patterns.py +815 -0
  456. truthound/profiler/observability.py +1184 -0
  457. truthound/profiler/process_timeout.py +1566 -0
  458. truthound/profiler/progress.py +568 -0
  459. truthound/profiler/progress_callbacks.py +1734 -0
  460. truthound/profiler/quality.py +1345 -0
  461. truthound/profiler/resilience.py +1180 -0
  462. truthound/profiler/sampled_matcher.py +794 -0
  463. truthound/profiler/sampling.py +1288 -0
  464. truthound/profiler/scheduling/__init__.py +82 -0
  465. truthound/profiler/scheduling/protocols.py +214 -0
  466. truthound/profiler/scheduling/scheduler.py +474 -0
  467. truthound/profiler/scheduling/storage.py +457 -0
  468. truthound/profiler/scheduling/triggers.py +449 -0
  469. truthound/profiler/schema.py +603 -0
  470. truthound/profiler/streaming.py +685 -0
  471. truthound/profiler/streaming_patterns.py +1354 -0
  472. truthound/profiler/suite_cli.py +625 -0
  473. truthound/profiler/suite_config.py +789 -0
  474. truthound/profiler/suite_export.py +1268 -0
  475. truthound/profiler/table_profiler.py +547 -0
  476. truthound/profiler/timeout.py +565 -0
  477. truthound/profiler/validation.py +1532 -0
  478. truthound/profiler/visualization/__init__.py +118 -0
  479. truthound/profiler/visualization/base.py +346 -0
  480. truthound/profiler/visualization/generator.py +1259 -0
  481. truthound/profiler/visualization/plotly_renderer.py +811 -0
  482. truthound/profiler/visualization/renderers.py +669 -0
  483. truthound/profiler/visualization/sections.py +540 -0
  484. truthound/profiler/visualization.py +2122 -0
  485. truthound/profiler/yaml_validation.py +1151 -0
  486. truthound/py.typed +0 -0
  487. truthound/ratelimit/__init__.py +248 -0
  488. truthound/ratelimit/algorithms.py +1108 -0
  489. truthound/ratelimit/core.py +573 -0
  490. truthound/ratelimit/integration.py +532 -0
  491. truthound/ratelimit/limiter.py +663 -0
  492. truthound/ratelimit/middleware.py +700 -0
  493. truthound/ratelimit/policy.py +792 -0
  494. truthound/ratelimit/storage.py +763 -0
  495. truthound/rbac/__init__.py +340 -0
  496. truthound/rbac/core.py +976 -0
  497. truthound/rbac/integration.py +760 -0
  498. truthound/rbac/manager.py +1052 -0
  499. truthound/rbac/middleware.py +842 -0
  500. truthound/rbac/policy.py +954 -0
  501. truthound/rbac/storage.py +878 -0
  502. truthound/realtime/__init__.py +141 -0
  503. truthound/realtime/adapters/__init__.py +43 -0
  504. truthound/realtime/adapters/base.py +533 -0
  505. truthound/realtime/adapters/kafka.py +487 -0
  506. truthound/realtime/adapters/kinesis.py +479 -0
  507. truthound/realtime/adapters/mock.py +243 -0
  508. truthound/realtime/base.py +553 -0
  509. truthound/realtime/factory.py +382 -0
  510. truthound/realtime/incremental.py +660 -0
  511. truthound/realtime/processing/__init__.py +67 -0
  512. truthound/realtime/processing/exactly_once.py +575 -0
  513. truthound/realtime/processing/state.py +547 -0
  514. truthound/realtime/processing/windows.py +647 -0
  515. truthound/realtime/protocols.py +569 -0
  516. truthound/realtime/streaming.py +605 -0
  517. truthound/realtime/testing/__init__.py +32 -0
  518. truthound/realtime/testing/containers.py +615 -0
  519. truthound/realtime/testing/fixtures.py +484 -0
  520. truthound/report.py +280 -0
  521. truthound/reporters/__init__.py +46 -0
  522. truthound/reporters/_protocols.py +30 -0
  523. truthound/reporters/base.py +324 -0
  524. truthound/reporters/ci/__init__.py +66 -0
  525. truthound/reporters/ci/azure.py +436 -0
  526. truthound/reporters/ci/base.py +509 -0
  527. truthound/reporters/ci/bitbucket.py +567 -0
  528. truthound/reporters/ci/circleci.py +547 -0
  529. truthound/reporters/ci/detection.py +364 -0
  530. truthound/reporters/ci/factory.py +182 -0
  531. truthound/reporters/ci/github.py +388 -0
  532. truthound/reporters/ci/gitlab.py +471 -0
  533. truthound/reporters/ci/jenkins.py +525 -0
  534. truthound/reporters/console_reporter.py +299 -0
  535. truthound/reporters/factory.py +211 -0
  536. truthound/reporters/html_reporter.py +524 -0
  537. truthound/reporters/json_reporter.py +256 -0
  538. truthound/reporters/markdown_reporter.py +280 -0
  539. truthound/reporters/sdk/__init__.py +174 -0
  540. truthound/reporters/sdk/builder.py +558 -0
  541. truthound/reporters/sdk/mixins.py +1150 -0
  542. truthound/reporters/sdk/schema.py +1493 -0
  543. truthound/reporters/sdk/templates.py +666 -0
  544. truthound/reporters/sdk/testing.py +968 -0
  545. truthound/scanners.py +170 -0
  546. truthound/scheduling/__init__.py +122 -0
  547. truthound/scheduling/cron.py +1136 -0
  548. truthound/scheduling/presets.py +212 -0
  549. truthound/schema.py +275 -0
  550. truthound/secrets/__init__.py +173 -0
  551. truthound/secrets/base.py +618 -0
  552. truthound/secrets/cloud.py +682 -0
  553. truthound/secrets/integration.py +507 -0
  554. truthound/secrets/manager.py +633 -0
  555. truthound/secrets/oidc/__init__.py +172 -0
  556. truthound/secrets/oidc/base.py +902 -0
  557. truthound/secrets/oidc/credential_provider.py +623 -0
  558. truthound/secrets/oidc/exchangers.py +1001 -0
  559. truthound/secrets/oidc/github/__init__.py +110 -0
  560. truthound/secrets/oidc/github/claims.py +718 -0
  561. truthound/secrets/oidc/github/enhanced_provider.py +693 -0
  562. truthound/secrets/oidc/github/trust_policy.py +742 -0
  563. truthound/secrets/oidc/github/verification.py +723 -0
  564. truthound/secrets/oidc/github/workflow.py +691 -0
  565. truthound/secrets/oidc/providers.py +825 -0
  566. truthound/secrets/providers.py +506 -0
  567. truthound/secrets/resolver.py +495 -0
  568. truthound/stores/__init__.py +177 -0
  569. truthound/stores/backends/__init__.py +18 -0
  570. truthound/stores/backends/_protocols.py +340 -0
  571. truthound/stores/backends/azure_blob.py +530 -0
  572. truthound/stores/backends/concurrent_filesystem.py +915 -0
  573. truthound/stores/backends/connection_pool.py +1365 -0
  574. truthound/stores/backends/database.py +743 -0
  575. truthound/stores/backends/filesystem.py +538 -0
  576. truthound/stores/backends/gcs.py +399 -0
  577. truthound/stores/backends/memory.py +354 -0
  578. truthound/stores/backends/s3.py +434 -0
  579. truthound/stores/backpressure/__init__.py +84 -0
  580. truthound/stores/backpressure/base.py +375 -0
  581. truthound/stores/backpressure/circuit_breaker.py +434 -0
  582. truthound/stores/backpressure/monitor.py +376 -0
  583. truthound/stores/backpressure/strategies.py +677 -0
  584. truthound/stores/base.py +551 -0
  585. truthound/stores/batching/__init__.py +65 -0
  586. truthound/stores/batching/base.py +305 -0
  587. truthound/stores/batching/buffer.py +370 -0
  588. truthound/stores/batching/store.py +248 -0
  589. truthound/stores/batching/writer.py +521 -0
  590. truthound/stores/caching/__init__.py +60 -0
  591. truthound/stores/caching/backends.py +684 -0
  592. truthound/stores/caching/base.py +356 -0
  593. truthound/stores/caching/store.py +305 -0
  594. truthound/stores/compression/__init__.py +193 -0
  595. truthound/stores/compression/adaptive.py +694 -0
  596. truthound/stores/compression/base.py +514 -0
  597. truthound/stores/compression/pipeline.py +868 -0
  598. truthound/stores/compression/providers.py +672 -0
  599. truthound/stores/compression/streaming.py +832 -0
  600. truthound/stores/concurrency/__init__.py +81 -0
  601. truthound/stores/concurrency/atomic.py +556 -0
  602. truthound/stores/concurrency/index.py +775 -0
  603. truthound/stores/concurrency/locks.py +576 -0
  604. truthound/stores/concurrency/manager.py +482 -0
  605. truthound/stores/encryption/__init__.py +297 -0
  606. truthound/stores/encryption/base.py +952 -0
  607. truthound/stores/encryption/keys.py +1191 -0
  608. truthound/stores/encryption/pipeline.py +903 -0
  609. truthound/stores/encryption/providers.py +953 -0
  610. truthound/stores/encryption/streaming.py +950 -0
  611. truthound/stores/expectations.py +227 -0
  612. truthound/stores/factory.py +246 -0
  613. truthound/stores/migration/__init__.py +75 -0
  614. truthound/stores/migration/base.py +480 -0
  615. truthound/stores/migration/manager.py +347 -0
  616. truthound/stores/migration/registry.py +382 -0
  617. truthound/stores/migration/store.py +559 -0
  618. truthound/stores/observability/__init__.py +106 -0
  619. truthound/stores/observability/audit.py +718 -0
  620. truthound/stores/observability/config.py +270 -0
  621. truthound/stores/observability/factory.py +208 -0
  622. truthound/stores/observability/metrics.py +636 -0
  623. truthound/stores/observability/protocols.py +410 -0
  624. truthound/stores/observability/store.py +570 -0
  625. truthound/stores/observability/tracing.py +784 -0
  626. truthound/stores/replication/__init__.py +76 -0
  627. truthound/stores/replication/base.py +260 -0
  628. truthound/stores/replication/monitor.py +269 -0
  629. truthound/stores/replication/store.py +439 -0
  630. truthound/stores/replication/syncer.py +391 -0
  631. truthound/stores/results.py +359 -0
  632. truthound/stores/retention/__init__.py +77 -0
  633. truthound/stores/retention/base.py +378 -0
  634. truthound/stores/retention/policies.py +621 -0
  635. truthound/stores/retention/scheduler.py +279 -0
  636. truthound/stores/retention/store.py +526 -0
  637. truthound/stores/streaming/__init__.py +138 -0
  638. truthound/stores/streaming/base.py +801 -0
  639. truthound/stores/streaming/database.py +984 -0
  640. truthound/stores/streaming/filesystem.py +719 -0
  641. truthound/stores/streaming/reader.py +629 -0
  642. truthound/stores/streaming/s3.py +843 -0
  643. truthound/stores/streaming/writer.py +790 -0
  644. truthound/stores/tiering/__init__.py +108 -0
  645. truthound/stores/tiering/base.py +462 -0
  646. truthound/stores/tiering/manager.py +249 -0
  647. truthound/stores/tiering/policies.py +692 -0
  648. truthound/stores/tiering/store.py +526 -0
  649. truthound/stores/versioning/__init__.py +56 -0
  650. truthound/stores/versioning/base.py +376 -0
  651. truthound/stores/versioning/store.py +660 -0
  652. truthound/stores/versioning/strategies.py +353 -0
  653. truthound/types.py +56 -0
  654. truthound/validators/__init__.py +774 -0
  655. truthound/validators/aggregate/__init__.py +27 -0
  656. truthound/validators/aggregate/central.py +116 -0
  657. truthound/validators/aggregate/extremes.py +116 -0
  658. truthound/validators/aggregate/spread.py +118 -0
  659. truthound/validators/aggregate/sum.py +64 -0
  660. truthound/validators/aggregate/type.py +78 -0
  661. truthound/validators/anomaly/__init__.py +93 -0
  662. truthound/validators/anomaly/base.py +431 -0
  663. truthound/validators/anomaly/ml_based.py +1190 -0
  664. truthound/validators/anomaly/multivariate.py +647 -0
  665. truthound/validators/anomaly/statistical.py +599 -0
  666. truthound/validators/base.py +1089 -0
  667. truthound/validators/business_rule/__init__.py +46 -0
  668. truthound/validators/business_rule/base.py +147 -0
  669. truthound/validators/business_rule/checksum.py +509 -0
  670. truthound/validators/business_rule/financial.py +526 -0
  671. truthound/validators/cache.py +733 -0
  672. truthound/validators/completeness/__init__.py +39 -0
  673. truthound/validators/completeness/conditional.py +73 -0
  674. truthound/validators/completeness/default.py +98 -0
  675. truthound/validators/completeness/empty.py +103 -0
  676. truthound/validators/completeness/nan.py +337 -0
  677. truthound/validators/completeness/null.py +152 -0
  678. truthound/validators/cross_table/__init__.py +17 -0
  679. truthound/validators/cross_table/aggregate.py +333 -0
  680. truthound/validators/cross_table/row_count.py +122 -0
  681. truthound/validators/datetime/__init__.py +29 -0
  682. truthound/validators/datetime/format.py +78 -0
  683. truthound/validators/datetime/freshness.py +269 -0
  684. truthound/validators/datetime/order.py +73 -0
  685. truthound/validators/datetime/parseable.py +185 -0
  686. truthound/validators/datetime/range.py +202 -0
  687. truthound/validators/datetime/timezone.py +69 -0
  688. truthound/validators/distribution/__init__.py +49 -0
  689. truthound/validators/distribution/distribution.py +128 -0
  690. truthound/validators/distribution/monotonic.py +119 -0
  691. truthound/validators/distribution/outlier.py +178 -0
  692. truthound/validators/distribution/quantile.py +80 -0
  693. truthound/validators/distribution/range.py +254 -0
  694. truthound/validators/distribution/set.py +125 -0
  695. truthound/validators/distribution/statistical.py +459 -0
  696. truthound/validators/drift/__init__.py +79 -0
  697. truthound/validators/drift/base.py +427 -0
  698. truthound/validators/drift/multi_feature.py +401 -0
  699. truthound/validators/drift/numeric.py +395 -0
  700. truthound/validators/drift/psi.py +446 -0
  701. truthound/validators/drift/statistical.py +510 -0
  702. truthound/validators/enterprise.py +1658 -0
  703. truthound/validators/geospatial/__init__.py +80 -0
  704. truthound/validators/geospatial/base.py +97 -0
  705. truthound/validators/geospatial/boundary.py +238 -0
  706. truthound/validators/geospatial/coordinate.py +351 -0
  707. truthound/validators/geospatial/distance.py +399 -0
  708. truthound/validators/geospatial/polygon.py +665 -0
  709. truthound/validators/i18n/__init__.py +308 -0
  710. truthound/validators/i18n/bidi.py +571 -0
  711. truthound/validators/i18n/catalogs.py +570 -0
  712. truthound/validators/i18n/dialects.py +763 -0
  713. truthound/validators/i18n/extended_catalogs.py +549 -0
  714. truthound/validators/i18n/formatting.py +1434 -0
  715. truthound/validators/i18n/loader.py +1020 -0
  716. truthound/validators/i18n/messages.py +521 -0
  717. truthound/validators/i18n/plural.py +683 -0
  718. truthound/validators/i18n/protocols.py +855 -0
  719. truthound/validators/i18n/tms.py +1162 -0
  720. truthound/validators/localization/__init__.py +53 -0
  721. truthound/validators/localization/base.py +122 -0
  722. truthound/validators/localization/chinese.py +362 -0
  723. truthound/validators/localization/japanese.py +275 -0
  724. truthound/validators/localization/korean.py +524 -0
  725. truthound/validators/memory/__init__.py +94 -0
  726. truthound/validators/memory/approximate_knn.py +506 -0
  727. truthound/validators/memory/base.py +547 -0
  728. truthound/validators/memory/sgd_online.py +719 -0
  729. truthound/validators/memory/streaming_ecdf.py +753 -0
  730. truthound/validators/ml_feature/__init__.py +54 -0
  731. truthound/validators/ml_feature/base.py +249 -0
  732. truthound/validators/ml_feature/correlation.py +299 -0
  733. truthound/validators/ml_feature/leakage.py +344 -0
  734. truthound/validators/ml_feature/null_impact.py +270 -0
  735. truthound/validators/ml_feature/scale.py +264 -0
  736. truthound/validators/multi_column/__init__.py +89 -0
  737. truthound/validators/multi_column/arithmetic.py +284 -0
  738. truthound/validators/multi_column/base.py +231 -0
  739. truthound/validators/multi_column/comparison.py +273 -0
  740. truthound/validators/multi_column/consistency.py +312 -0
  741. truthound/validators/multi_column/statistical.py +299 -0
  742. truthound/validators/optimization/__init__.py +164 -0
  743. truthound/validators/optimization/aggregation.py +563 -0
  744. truthound/validators/optimization/covariance.py +556 -0
  745. truthound/validators/optimization/geo.py +626 -0
  746. truthound/validators/optimization/graph.py +587 -0
  747. truthound/validators/optimization/orchestrator.py +970 -0
  748. truthound/validators/optimization/profiling.py +1312 -0
  749. truthound/validators/privacy/__init__.py +223 -0
  750. truthound/validators/privacy/base.py +635 -0
  751. truthound/validators/privacy/ccpa.py +670 -0
  752. truthound/validators/privacy/gdpr.py +728 -0
  753. truthound/validators/privacy/global_patterns.py +604 -0
  754. truthound/validators/privacy/plugins.py +867 -0
  755. truthound/validators/profiling/__init__.py +52 -0
  756. truthound/validators/profiling/base.py +175 -0
  757. truthound/validators/profiling/cardinality.py +312 -0
  758. truthound/validators/profiling/entropy.py +391 -0
  759. truthound/validators/profiling/frequency.py +455 -0
  760. truthound/validators/pushdown_support.py +660 -0
  761. truthound/validators/query/__init__.py +91 -0
  762. truthound/validators/query/aggregate.py +346 -0
  763. truthound/validators/query/base.py +246 -0
  764. truthound/validators/query/column.py +249 -0
  765. truthound/validators/query/expression.py +274 -0
  766. truthound/validators/query/result.py +323 -0
  767. truthound/validators/query/row_count.py +264 -0
  768. truthound/validators/referential/__init__.py +80 -0
  769. truthound/validators/referential/base.py +395 -0
  770. truthound/validators/referential/cascade.py +391 -0
  771. truthound/validators/referential/circular.py +563 -0
  772. truthound/validators/referential/foreign_key.py +624 -0
  773. truthound/validators/referential/orphan.py +485 -0
  774. truthound/validators/registry.py +112 -0
  775. truthound/validators/schema/__init__.py +41 -0
  776. truthound/validators/schema/column_count.py +142 -0
  777. truthound/validators/schema/column_exists.py +80 -0
  778. truthound/validators/schema/column_order.py +82 -0
  779. truthound/validators/schema/column_pair.py +85 -0
  780. truthound/validators/schema/column_pair_set.py +195 -0
  781. truthound/validators/schema/column_type.py +94 -0
  782. truthound/validators/schema/multi_column.py +53 -0
  783. truthound/validators/schema/multi_column_aggregate.py +175 -0
  784. truthound/validators/schema/referential.py +274 -0
  785. truthound/validators/schema/table_schema.py +91 -0
  786. truthound/validators/schema_validator.py +219 -0
  787. truthound/validators/sdk/__init__.py +250 -0
  788. truthound/validators/sdk/builder.py +680 -0
  789. truthound/validators/sdk/decorators.py +474 -0
  790. truthound/validators/sdk/enterprise/__init__.py +211 -0
  791. truthound/validators/sdk/enterprise/docs.py +725 -0
  792. truthound/validators/sdk/enterprise/fuzzing.py +659 -0
  793. truthound/validators/sdk/enterprise/licensing.py +709 -0
  794. truthound/validators/sdk/enterprise/manager.py +543 -0
  795. truthound/validators/sdk/enterprise/resources.py +628 -0
  796. truthound/validators/sdk/enterprise/sandbox.py +766 -0
  797. truthound/validators/sdk/enterprise/signing.py +603 -0
  798. truthound/validators/sdk/enterprise/templates.py +865 -0
  799. truthound/validators/sdk/enterprise/versioning.py +659 -0
  800. truthound/validators/sdk/templates.py +757 -0
  801. truthound/validators/sdk/testing.py +807 -0
  802. truthound/validators/security/__init__.py +181 -0
  803. truthound/validators/security/redos/__init__.py +182 -0
  804. truthound/validators/security/redos/core.py +861 -0
  805. truthound/validators/security/redos/cpu_monitor.py +593 -0
  806. truthound/validators/security/redos/cve_database.py +791 -0
  807. truthound/validators/security/redos/ml/__init__.py +155 -0
  808. truthound/validators/security/redos/ml/base.py +785 -0
  809. truthound/validators/security/redos/ml/datasets.py +618 -0
  810. truthound/validators/security/redos/ml/features.py +359 -0
  811. truthound/validators/security/redos/ml/models.py +1000 -0
  812. truthound/validators/security/redos/ml/predictor.py +507 -0
  813. truthound/validators/security/redos/ml/storage.py +632 -0
  814. truthound/validators/security/redos/ml/training.py +571 -0
  815. truthound/validators/security/redos/ml_analyzer.py +937 -0
  816. truthound/validators/security/redos/optimizer.py +674 -0
  817. truthound/validators/security/redos/profiler.py +682 -0
  818. truthound/validators/security/redos/re2_engine.py +709 -0
  819. truthound/validators/security/redos.py +886 -0
  820. truthound/validators/security/sql_security.py +1247 -0
  821. truthound/validators/streaming/__init__.py +126 -0
  822. truthound/validators/streaming/base.py +292 -0
  823. truthound/validators/streaming/completeness.py +210 -0
  824. truthound/validators/streaming/mixin.py +575 -0
  825. truthound/validators/streaming/range.py +308 -0
  826. truthound/validators/streaming/sources.py +846 -0
  827. truthound/validators/string/__init__.py +57 -0
  828. truthound/validators/string/casing.py +158 -0
  829. truthound/validators/string/charset.py +96 -0
  830. truthound/validators/string/format.py +501 -0
  831. truthound/validators/string/json.py +77 -0
  832. truthound/validators/string/json_schema.py +184 -0
  833. truthound/validators/string/length.py +104 -0
  834. truthound/validators/string/like_pattern.py +237 -0
  835. truthound/validators/string/regex.py +202 -0
  836. truthound/validators/string/regex_extended.py +435 -0
  837. truthound/validators/table/__init__.py +88 -0
  838. truthound/validators/table/base.py +78 -0
  839. truthound/validators/table/column_count.py +198 -0
  840. truthound/validators/table/freshness.py +362 -0
  841. truthound/validators/table/row_count.py +251 -0
  842. truthound/validators/table/schema.py +333 -0
  843. truthound/validators/table/size.py +285 -0
  844. truthound/validators/timeout/__init__.py +102 -0
  845. truthound/validators/timeout/advanced/__init__.py +247 -0
  846. truthound/validators/timeout/advanced/circuit_breaker.py +675 -0
  847. truthound/validators/timeout/advanced/prediction.py +773 -0
  848. truthound/validators/timeout/advanced/priority.py +618 -0
  849. truthound/validators/timeout/advanced/redis_backend.py +770 -0
  850. truthound/validators/timeout/advanced/retry.py +721 -0
  851. truthound/validators/timeout/advanced/sampling.py +788 -0
  852. truthound/validators/timeout/advanced/sla.py +661 -0
  853. truthound/validators/timeout/advanced/telemetry.py +804 -0
  854. truthound/validators/timeout/cascade.py +477 -0
  855. truthound/validators/timeout/deadline.py +657 -0
  856. truthound/validators/timeout/degradation.py +525 -0
  857. truthound/validators/timeout/distributed.py +597 -0
  858. truthound/validators/timeseries/__init__.py +89 -0
  859. truthound/validators/timeseries/base.py +326 -0
  860. truthound/validators/timeseries/completeness.py +617 -0
  861. truthound/validators/timeseries/gap.py +485 -0
  862. truthound/validators/timeseries/monotonic.py +310 -0
  863. truthound/validators/timeseries/seasonality.py +422 -0
  864. truthound/validators/timeseries/trend.py +510 -0
  865. truthound/validators/uniqueness/__init__.py +59 -0
  866. truthound/validators/uniqueness/approximate.py +475 -0
  867. truthound/validators/uniqueness/distinct_values.py +253 -0
  868. truthound/validators/uniqueness/duplicate.py +118 -0
  869. truthound/validators/uniqueness/primary_key.py +140 -0
  870. truthound/validators/uniqueness/unique.py +191 -0
  871. truthound/validators/uniqueness/within_record.py +599 -0
  872. truthound/validators/utils.py +756 -0
  873. truthound-1.0.8.dist-info/METADATA +474 -0
  874. truthound-1.0.8.dist-info/RECORD +877 -0
  875. truthound-1.0.8.dist-info/WHEEL +4 -0
  876. truthound-1.0.8.dist-info/entry_points.txt +2 -0
  877. truthound-1.0.8.dist-info/licenses/LICENSE +190 -0
@@ -0,0 +1,1072 @@
1
+ """Plugin scaffold generator.
2
+
3
+ This module provides scaffolding for creating Truthound plugins with
4
+ various template variants:
5
+ - validator: Plugin that provides custom validators
6
+ - reporter: Plugin that provides custom reporters
7
+ - hook: Plugin that provides event hooks
8
+ - datasource: Plugin that provides data source connectors
9
+ - action: Plugin that provides checkpoint actions
10
+ - full: Full-featured plugin with all components
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from typing import Any, ClassVar
16
+
17
+ from truthound.cli_modules.scaffolding.base import (
18
+ BaseScaffold,
19
+ ScaffoldConfig,
20
+ ScaffoldResult,
21
+ register_scaffold,
22
+ )
23
+
24
+
25
+ @register_scaffold(
26
+ name="plugin",
27
+ description="Generate a Truthound plugin",
28
+ aliases=("plug", "p"),
29
+ )
30
+ class PluginScaffold(BaseScaffold):
31
+ """Scaffold generator for plugins.
32
+
33
+ Creates complete plugin packages with pyproject.toml, README, and tests.
34
+ """
35
+
36
+ name: ClassVar[str] = "plugin"
37
+ description: ClassVar[str] = "Generate a Truthound plugin"
38
+ aliases: ClassVar[tuple[str, ...]] = ("plug", "p")
39
+
40
+ TEMPLATE_VARIANTS: ClassVar[tuple[str, ...]] = (
41
+ "validator",
42
+ "reporter",
43
+ "hook",
44
+ "datasource",
45
+ "action",
46
+ "full",
47
+ )
48
+
49
+ def get_options(self) -> dict[str, Any]:
50
+ """Get plugin-specific options."""
51
+ return {
52
+ "plugin_type": {
53
+ "type": "str",
54
+ "default": "validator",
55
+ "description": "Type of plugin (validator, reporter, hook, datasource, action)",
56
+ "choices": ["validator", "reporter", "hook", "datasource", "action"],
57
+ },
58
+ "min_truthound_version": {
59
+ "type": "str",
60
+ "default": "0.1.0",
61
+ "description": "Minimum Truthound version required",
62
+ },
63
+ "python_version": {
64
+ "type": "str",
65
+ "default": "3.10",
66
+ "description": "Minimum Python version",
67
+ },
68
+ }
69
+
70
+ def _generate_files(self, config: ScaffoldConfig, result: ScaffoldResult) -> None:
71
+ """Generate plugin files based on variant."""
72
+ variant = config.template_variant
73
+ pkg_name = config.name.replace("-", "_")
74
+
75
+ # Generate plugin package structure
76
+ self._generate_pyproject(config, result)
77
+ self._generate_readme(config, result)
78
+ self._generate_package_init(config, result, pkg_name)
79
+
80
+ # Generate plugin implementation based on type
81
+ if variant == "validator":
82
+ self._generate_validator_plugin(config, result, pkg_name)
83
+ elif variant == "reporter":
84
+ self._generate_reporter_plugin(config, result, pkg_name)
85
+ elif variant == "hook":
86
+ self._generate_hook_plugin(config, result, pkg_name)
87
+ elif variant == "datasource":
88
+ self._generate_datasource_plugin(config, result, pkg_name)
89
+ elif variant == "action":
90
+ self._generate_action_plugin(config, result, pkg_name)
91
+ elif variant == "full":
92
+ self._generate_full_plugin(config, result, pkg_name)
93
+ else:
94
+ self._generate_validator_plugin(config, result, pkg_name)
95
+
96
+ # Generate tests
97
+ if config.include_tests:
98
+ self._generate_tests(config, result, pkg_name)
99
+
100
+ def _generate_pyproject(self, config: ScaffoldConfig, result: ScaffoldResult) -> None:
101
+ """Generate pyproject.toml."""
102
+ pkg_name = config.name.replace("-", "_")
103
+ min_python = config.extra.get("python_version", "3.10")
104
+ min_truthound = config.extra.get("min_truthound_version", "0.1.0")
105
+
106
+ content = f'''[build-system]
107
+ requires = ["setuptools>=61.0", "wheel"]
108
+ build-backend = "setuptools.build_meta"
109
+
110
+ [project]
111
+ name = "truthound-plugin-{config.name}"
112
+ version = "{config.version}"
113
+ description = "{config.description or f'A {config.template_variant} plugin for Truthound'}"
114
+ readme = "README.md"
115
+ license = {{text = "{config.license_type}"}}
116
+ authors = [
117
+ {{name = "{config.author or 'Your Name'}", email = "your@email.com"}}
118
+ ]
119
+ requires-python = ">={min_python}"
120
+ dependencies = [
121
+ "truthound>={min_truthound}",
122
+ ]
123
+ classifiers = [
124
+ "Development Status :: 3 - Alpha",
125
+ "Intended Audience :: Developers",
126
+ "License :: OSI Approved :: MIT License",
127
+ "Programming Language :: Python :: 3",
128
+ "Programming Language :: Python :: 3.10",
129
+ "Programming Language :: Python :: 3.11",
130
+ "Programming Language :: Python :: 3.12",
131
+ "Topic :: Software Development :: Quality Assurance",
132
+ ]
133
+ keywords = ["truthound", "data-quality", "plugin"]
134
+
135
+ [project.optional-dependencies]
136
+ dev = [
137
+ "pytest>=7.0.0",
138
+ "pytest-cov>=4.0.0",
139
+ "ruff>=0.1.0",
140
+ "mypy>=1.0.0",
141
+ ]
142
+
143
+ [project.urls]
144
+ Homepage = "https://github.com/{config.author or 'yourusername'}/truthound-plugin-{config.name}"
145
+ Repository = "https://github.com/{config.author or 'yourusername'}/truthound-plugin-{config.name}"
146
+ Issues = "https://github.com/{config.author or 'yourusername'}/truthound-plugin-{config.name}/issues"
147
+
148
+ [project.entry-points."truthound.plugins"]
149
+ {config.name} = "{pkg_name}:{config.class_name}Plugin"
150
+
151
+ [tool.setuptools.packages.find]
152
+ where = ["."]
153
+
154
+ [tool.ruff]
155
+ line-length = 100
156
+ target-version = "py310"
157
+
158
+ [tool.ruff.lint]
159
+ select = ["E", "F", "W", "I", "N", "B", "A", "C4", "SIM"]
160
+ ignore = ["E501"]
161
+
162
+ [tool.mypy]
163
+ python_version = "{min_python}"
164
+ warn_return_any = true
165
+ warn_unused_configs = true
166
+ disallow_untyped_defs = true
167
+
168
+ [tool.pytest.ini_options]
169
+ testpaths = ["tests"]
170
+ python_files = ["test_*.py"]
171
+ python_functions = ["test_*"]
172
+ addopts = "-v --tb=short"
173
+ '''
174
+ result.add_file("pyproject.toml", content)
175
+
176
+ def _generate_readme(self, config: ScaffoldConfig, result: ScaffoldResult) -> None:
177
+ """Generate README.md."""
178
+ content = f'''# Truthound Plugin: {config.name}
179
+
180
+ {config.description or f'A {config.template_variant} plugin for Truthound.'}
181
+
182
+ ## Installation
183
+
184
+ ```bash
185
+ pip install truthound-plugin-{config.name}
186
+ ```
187
+
188
+ Or install from source:
189
+
190
+ ```bash
191
+ git clone https://github.com/{config.author or 'yourusername'}/truthound-plugin-{config.name}
192
+ cd truthound-plugin-{config.name}
193
+ pip install -e .
194
+ ```
195
+
196
+ ## Usage
197
+
198
+ The plugin is automatically discovered by Truthound:
199
+
200
+ ```python
201
+ from truthound.plugins import get_plugin_manager
202
+
203
+ # Get plugin manager
204
+ manager = get_plugin_manager()
205
+
206
+ # Discover and load plugins
207
+ manager.discover_plugins()
208
+ manager.load_plugin("{config.name}")
209
+
210
+ # List loaded plugins
211
+ print(manager.registry.list_names())
212
+ ```
213
+
214
+ ## Development
215
+
216
+ ### Setup
217
+
218
+ ```bash
219
+ # Clone the repository
220
+ git clone https://github.com/{config.author or 'yourusername'}/truthound-plugin-{config.name}
221
+ cd truthound-plugin-{config.name}
222
+
223
+ # Install in development mode
224
+ pip install -e ".[dev]"
225
+ ```
226
+
227
+ ### Testing
228
+
229
+ ```bash
230
+ pytest
231
+ ```
232
+
233
+ ### Linting
234
+
235
+ ```bash
236
+ ruff check .
237
+ ruff format .
238
+ mypy .
239
+ ```
240
+
241
+ ## License
242
+
243
+ {config.license_type}
244
+
245
+ ---
246
+
247
+ *Version: {config.version}*
248
+ *Author: {config.author or 'Unknown'}*
249
+ '''
250
+ result.add_file("README.md", content)
251
+
252
+ def _generate_package_init(
253
+ self, config: ScaffoldConfig, result: ScaffoldResult, pkg_name: str
254
+ ) -> None:
255
+ """Generate package __init__.py."""
256
+ content = f'''"""Truthound plugin: {config.name}
257
+
258
+ {config.description or f'A {config.template_variant} plugin for Truthound.'}
259
+ """
260
+
261
+ from {pkg_name}.plugin import {config.class_name}Plugin
262
+
263
+ __version__ = "{config.version}"
264
+ __all__ = ["{config.class_name}Plugin"]
265
+ '''
266
+ result.add_file(f"{pkg_name}/__init__.py", content)
267
+
268
+ def _generate_validator_plugin(
269
+ self, config: ScaffoldConfig, result: ScaffoldResult, pkg_name: str
270
+ ) -> None:
271
+ """Generate validator plugin template."""
272
+ content = f'''{self._get_header(config)}
273
+
274
+ from __future__ import annotations
275
+
276
+ from typing import Any
277
+
278
+ import polars as pl
279
+
280
+ from truthound.plugins import ValidatorPlugin, PluginInfo, PluginType
281
+ from truthound.validators.base import Validator, ValidatorConfig, ValidationIssue
282
+ from truthound.types import Severity
283
+
284
+
285
+ class {config.class_name}Validator(Validator):
286
+ """Custom validator provided by {config.name} plugin.
287
+
288
+ TODO: Implement your validation logic here.
289
+
290
+ Example:
291
+ >>> validator = {config.class_name}Validator()
292
+ >>> issues = validator.validate(lf)
293
+ """
294
+
295
+ name = "{config.name}"
296
+ category = "custom"
297
+ default_severity = Severity.MEDIUM
298
+
299
+ def __init__(
300
+ self,
301
+ config: ValidatorConfig | None = None,
302
+ **kwargs: Any,
303
+ ) -> None:
304
+ """Initialize the validator.
305
+
306
+ Args:
307
+ config: Optional validator configuration.
308
+ **kwargs: Additional arguments.
309
+ """
310
+ super().__init__(config, **kwargs)
311
+
312
+ def validate(self, lf: pl.LazyFrame) -> list[ValidationIssue]:
313
+ """Perform validation.
314
+
315
+ Args:
316
+ lf: Polars LazyFrame to validate.
317
+
318
+ Returns:
319
+ List of validation issues found.
320
+ """
321
+ issues: list[ValidationIssue] = []
322
+ total_rows = lf.select(pl.len()).collect().item()
323
+
324
+ if total_rows == 0:
325
+ return issues
326
+
327
+ # TODO: Implement your validation logic
328
+ # Example:
329
+ # for col in self._get_target_columns(lf):
330
+ # violations = lf.filter(pl.col(col).is_null()).collect()
331
+ # if violations.height > 0:
332
+ # issues.append(ValidationIssue(
333
+ # column=col,
334
+ # issue_type=self.name,
335
+ # count=violations.height,
336
+ # severity=self.default_severity,
337
+ # details=f"Found {{violations.height}} issues",
338
+ # ))
339
+
340
+ return issues
341
+
342
+
343
+ class {config.class_name}Plugin(ValidatorPlugin):
344
+ """Plugin that provides custom validators.
345
+
346
+ This plugin is automatically discovered and can be loaded using:
347
+
348
+ manager.load_plugin("{config.name}")
349
+ """
350
+
351
+ def _get_plugin_name(self) -> str:
352
+ return "{config.name}"
353
+
354
+ def _get_plugin_version(self) -> str:
355
+ return "{config.version}"
356
+
357
+ def _get_description(self) -> str:
358
+ return "{config.description or 'Custom validators for Truthound'}"
359
+
360
+ def _get_author(self) -> str:
361
+ return "{config.author or ''}"
362
+
363
+ def get_validators(self) -> list[type[Validator]]:
364
+ """Return validator classes to register.
365
+
366
+ Returns:
367
+ List of validator classes.
368
+ """
369
+ return [{config.class_name}Validator]
370
+ '''
371
+ result.add_file(f"{pkg_name}/plugin.py", content)
372
+
373
+ def _generate_reporter_plugin(
374
+ self, config: ScaffoldConfig, result: ScaffoldResult, pkg_name: str
375
+ ) -> None:
376
+ """Generate reporter plugin template."""
377
+ content = f'''{self._get_header(config)}
378
+
379
+ from __future__ import annotations
380
+
381
+ from dataclasses import dataclass
382
+ from typing import TYPE_CHECKING, Any
383
+
384
+ from truthound.plugins import ReporterPlugin, PluginInfo, PluginType
385
+ from truthound.reporters.base import ValidationReporter, ReporterConfig
386
+
387
+ if TYPE_CHECKING:
388
+ from truthound.stores.results import ValidationResult
389
+
390
+
391
+ @dataclass
392
+ class {config.class_name}ReporterConfig(ReporterConfig):
393
+ """Configuration for {config.class_name} reporter."""
394
+
395
+ include_passed: bool = False
396
+
397
+
398
+ class {config.class_name}Reporter(ValidationReporter[{config.class_name}ReporterConfig]):
399
+ """Custom reporter provided by {config.name} plugin.
400
+
401
+ Example:
402
+ >>> reporter = {config.class_name}Reporter()
403
+ >>> output = reporter.render(validation_result)
404
+ """
405
+
406
+ name = "{config.name}"
407
+ file_extension = ".txt"
408
+ content_type = "text/plain"
409
+
410
+ @classmethod
411
+ def _default_config(cls) -> {config.class_name}ReporterConfig:
412
+ return {config.class_name}ReporterConfig()
413
+
414
+ def render(self, data: "ValidationResult") -> str:
415
+ """Render validation result to string.
416
+
417
+ Args:
418
+ data: Validation result to render.
419
+
420
+ Returns:
421
+ Rendered string.
422
+ """
423
+ lines = [
424
+ f"Validation Report: {{data.data_asset}}",
425
+ f"Status: {{data.status.value}}",
426
+ f"Total Issues: {{len([r for r in data.results if not r.success])}}",
427
+ "",
428
+ ]
429
+
430
+ for result in data.results:
431
+ if not result.success or self._config.include_passed:
432
+ lines.append(
433
+ f"- {{result.column or 'table'}}: "
434
+ f"{{result.issue_type}} ({{result.severity}})"
435
+ )
436
+
437
+ return "\\n".join(lines)
438
+
439
+
440
+ class {config.class_name}Plugin(ReporterPlugin):
441
+ """Plugin that provides custom reporters."""
442
+
443
+ def _get_plugin_name(self) -> str:
444
+ return "{config.name}"
445
+
446
+ def _get_plugin_version(self) -> str:
447
+ return "{config.version}"
448
+
449
+ def _get_description(self) -> str:
450
+ return "{config.description or 'Custom reporter for Truthound'}"
451
+
452
+ def _get_author(self) -> str:
453
+ return "{config.author or ''}"
454
+
455
+ def get_reporters(self) -> dict[str, type[ValidationReporter]]:
456
+ """Return reporter classes to register.
457
+
458
+ Returns:
459
+ Dictionary of reporter name to class.
460
+ """
461
+ return {{"{config.name}": {config.class_name}Reporter}}
462
+ '''
463
+ result.add_file(f"{pkg_name}/plugin.py", content)
464
+
465
+ def _generate_hook_plugin(
466
+ self, config: ScaffoldConfig, result: ScaffoldResult, pkg_name: str
467
+ ) -> None:
468
+ """Generate hook plugin template."""
469
+ content = f'''{self._get_header(config)}
470
+
471
+ from __future__ import annotations
472
+
473
+ import logging
474
+ from typing import Any, Callable
475
+
476
+ from truthound.plugins import HookPlugin, PluginInfo, PluginType, HookType
477
+
478
+ logger = logging.getLogger(__name__)
479
+
480
+
481
+ def on_validation_start(
482
+ datasource: Any,
483
+ validators: list[Any],
484
+ **kwargs: Any,
485
+ ) -> None:
486
+ """Called before validation starts.
487
+
488
+ Args:
489
+ datasource: The data source being validated.
490
+ validators: List of validators to run.
491
+ **kwargs: Additional context.
492
+ """
493
+ logger.info(f"[{config.name}] Starting validation on {{datasource}}")
494
+ logger.debug(f"[{config.name}] Validators: {{[v.name for v in validators]}}")
495
+
496
+
497
+ def on_validation_complete(
498
+ datasource: Any,
499
+ result: Any,
500
+ issues: list[Any],
501
+ **kwargs: Any,
502
+ ) -> None:
503
+ """Called after validation completes.
504
+
505
+ Args:
506
+ datasource: The data source that was validated.
507
+ result: The validation result.
508
+ issues: List of issues found.
509
+ **kwargs: Additional context.
510
+ """
511
+ logger.info(
512
+ f"[{config.name}] Validation complete: "
513
+ f"{{len(issues)}} issues found"
514
+ )
515
+
516
+
517
+ def on_validator_start(
518
+ validator: Any,
519
+ datasource: Any,
520
+ **kwargs: Any,
521
+ ) -> None:
522
+ """Called before each validator runs.
523
+
524
+ Args:
525
+ validator: The validator about to run.
526
+ datasource: The data source.
527
+ **kwargs: Additional context.
528
+ """
529
+ logger.debug(f"[{config.name}] Starting validator: {{validator.name}}")
530
+
531
+
532
+ def on_validator_complete(
533
+ validator: Any,
534
+ issues: list[Any],
535
+ duration: float,
536
+ **kwargs: Any,
537
+ ) -> None:
538
+ """Called after each validator completes.
539
+
540
+ Args:
541
+ validator: The validator that completed.
542
+ issues: Issues found by this validator.
543
+ duration: Execution time in seconds.
544
+ **kwargs: Additional context.
545
+ """
546
+ logger.debug(
547
+ f"[{config.name}] Validator {{validator.name}} completed in "
548
+ f"{{duration:.3f}}s with {{len(issues)}} issues"
549
+ )
550
+
551
+
552
+ class {config.class_name}Plugin(HookPlugin):
553
+ """Plugin that provides event hooks.
554
+
555
+ Available hooks:
556
+ - BEFORE_VALIDATION: Called before validation starts
557
+ - AFTER_VALIDATION: Called after validation completes
558
+ - BEFORE_VALIDATOR: Called before each validator
559
+ - AFTER_VALIDATOR: Called after each validator
560
+ """
561
+
562
+ def _get_plugin_name(self) -> str:
563
+ return "{config.name}"
564
+
565
+ def _get_plugin_version(self) -> str:
566
+ return "{config.version}"
567
+
568
+ def _get_description(self) -> str:
569
+ return "{config.description or 'Event hooks for Truthound'}"
570
+
571
+ def _get_author(self) -> str:
572
+ return "{config.author or ''}"
573
+
574
+ def get_hooks(self) -> dict[str, Callable[..., Any]]:
575
+ """Return hooks to register.
576
+
577
+ Returns:
578
+ Dictionary of hook type to callback function.
579
+ """
580
+ return {{
581
+ HookType.BEFORE_VALIDATION.value: on_validation_start,
582
+ HookType.AFTER_VALIDATION.value: on_validation_complete,
583
+ HookType.BEFORE_VALIDATOR.value: on_validator_start,
584
+ HookType.AFTER_VALIDATOR.value: on_validator_complete,
585
+ }}
586
+ '''
587
+ result.add_file(f"{pkg_name}/plugin.py", content)
588
+
589
+ def _generate_datasource_plugin(
590
+ self, config: ScaffoldConfig, result: ScaffoldResult, pkg_name: str
591
+ ) -> None:
592
+ """Generate datasource plugin template."""
593
+ content = f'''{self._get_header(config)}
594
+
595
+ from __future__ import annotations
596
+
597
+ from typing import Any
598
+
599
+ import polars as pl
600
+
601
+ from truthound.plugins import DataSourcePlugin, PluginInfo, PluginType
602
+ from truthound.datasources.base import DataSource, DataSourceConfig
603
+
604
+
605
+ class {config.class_name}DataSource(DataSource):
606
+ """Custom data source provided by {config.name} plugin.
607
+
608
+ TODO: Implement connection and data reading logic.
609
+
610
+ Example:
611
+ >>> ds = {config.class_name}DataSource(connection_string="...")
612
+ >>> lf = ds.read()
613
+ """
614
+
615
+ name = "{config.name}"
616
+
617
+ def __init__(
618
+ self,
619
+ connection_string: str | None = None,
620
+ config: DataSourceConfig | None = None,
621
+ **kwargs: Any,
622
+ ) -> None:
623
+ """Initialize the data source.
624
+
625
+ Args:
626
+ connection_string: Connection string for the data source.
627
+ config: Data source configuration.
628
+ **kwargs: Additional arguments.
629
+ """
630
+ super().__init__(config, **kwargs)
631
+ self._connection_string = connection_string
632
+ self._connection = None
633
+
634
+ def connect(self) -> None:
635
+ """Establish connection to the data source."""
636
+ # TODO: Implement connection logic
637
+ pass
638
+
639
+ def disconnect(self) -> None:
640
+ """Close connection to the data source."""
641
+ # TODO: Implement disconnection logic
642
+ self._connection = None
643
+
644
+ def read(
645
+ self,
646
+ query: str | None = None,
647
+ limit: int | None = None,
648
+ **kwargs: Any,
649
+ ) -> pl.LazyFrame:
650
+ """Read data from the source.
651
+
652
+ Args:
653
+ query: Optional query or table name.
654
+ limit: Maximum rows to read.
655
+ **kwargs: Additional read options.
656
+
657
+ Returns:
658
+ Polars LazyFrame with the data.
659
+ """
660
+ # TODO: Implement data reading logic
661
+ # Example:
662
+ # if query:
663
+ # result = self._execute_query(query)
664
+ # else:
665
+ # result = self._read_all()
666
+ #
667
+ # if limit:
668
+ # result = result.head(limit)
669
+ #
670
+ # return result.lazy()
671
+
672
+ raise NotImplementedError("Implement read() method")
673
+
674
+ def get_schema(self) -> dict[str, Any]:
675
+ """Get schema information from the data source.
676
+
677
+ Returns:
678
+ Dictionary with schema information.
679
+ """
680
+ # TODO: Implement schema retrieval
681
+ return {{}}
682
+
683
+
684
+ class {config.class_name}Plugin(DataSourcePlugin):
685
+ """Plugin that provides custom data source connectors."""
686
+
687
+ def _get_plugin_name(self) -> str:
688
+ return "{config.name}"
689
+
690
+ def _get_plugin_version(self) -> str:
691
+ return "{config.version}"
692
+
693
+ def _get_description(self) -> str:
694
+ return "{config.description or 'Custom data source for Truthound'}"
695
+
696
+ def _get_author(self) -> str:
697
+ return "{config.author or ''}"
698
+
699
+ def get_datasources(self) -> dict[str, type[DataSource]]:
700
+ """Return data source classes to register.
701
+
702
+ Returns:
703
+ Dictionary of data source name to class.
704
+ """
705
+ return {{"{config.name}": {config.class_name}DataSource}}
706
+ '''
707
+ result.add_file(f"{pkg_name}/plugin.py", content)
708
+
709
+ def _generate_action_plugin(
710
+ self, config: ScaffoldConfig, result: ScaffoldResult, pkg_name: str
711
+ ) -> None:
712
+ """Generate checkpoint action plugin template."""
713
+ content = f'''{self._get_header(config)}
714
+
715
+ from __future__ import annotations
716
+
717
+ import logging
718
+ from typing import Any
719
+
720
+ from truthound.plugins import ActionPlugin, PluginInfo, PluginType
721
+ from truthound.checkpoint.actions.base import CheckpointAction, ActionConfig
722
+ from truthound.checkpoint.core import CheckpointResult
723
+
724
+ logger = logging.getLogger(__name__)
725
+
726
+
727
+ class {config.class_name}ActionConfig(ActionConfig):
728
+ """Configuration for {config.class_name} action.
729
+
730
+ Attributes:
731
+ enabled: Whether the action is enabled.
732
+ trigger_on: When to trigger (success, failure, always).
733
+ custom_option: Your custom configuration option.
734
+ """
735
+
736
+ enabled: bool = True
737
+ trigger_on: str = "always"
738
+ custom_option: str = ""
739
+
740
+
741
+ class {config.class_name}Action(CheckpointAction[{config.class_name}ActionConfig]):
742
+ """Custom checkpoint action provided by {config.name} plugin.
743
+
744
+ This action is triggered after checkpoint validation completes.
745
+
746
+ Example:
747
+ >>> action = {config.class_name}Action(custom_option="value")
748
+ >>> action.execute(checkpoint_result)
749
+ """
750
+
751
+ name = "{config.name}"
752
+
753
+ def __init__(
754
+ self,
755
+ config: {config.class_name}ActionConfig | None = None,
756
+ **kwargs: Any,
757
+ ) -> None:
758
+ """Initialize the action.
759
+
760
+ Args:
761
+ config: Action configuration.
762
+ **kwargs: Additional arguments passed to config.
763
+ """
764
+ if config is None:
765
+ config = {config.class_name}ActionConfig(**kwargs)
766
+ super().__init__(config)
767
+
768
+ def execute(self, result: CheckpointResult) -> bool:
769
+ """Execute the action.
770
+
771
+ Args:
772
+ result: The checkpoint result to act on.
773
+
774
+ Returns:
775
+ True if action succeeded, False otherwise.
776
+ """
777
+ if not self._should_trigger(result):
778
+ logger.debug(f"[{config.name}] Skipping - trigger condition not met")
779
+ return True
780
+
781
+ try:
782
+ # TODO: Implement your action logic
783
+ logger.info(
784
+ f"[{config.name}] Executing action for checkpoint "
785
+ f"'{{result.checkpoint_name}}'"
786
+ )
787
+
788
+ # Example: Log results
789
+ logger.info(f" Status: {{result.status.value}}")
790
+ logger.info(f" Issues: {{result.issue_count}}")
791
+
792
+ if self._config.custom_option:
793
+ logger.info(f" Custom option: {{self._config.custom_option}}")
794
+
795
+ return True
796
+
797
+ except Exception as e:
798
+ logger.error(f"[{config.name}] Action failed: {{e}}")
799
+ return False
800
+
801
+ def _should_trigger(self, result: CheckpointResult) -> bool:
802
+ """Check if action should trigger based on configuration.
803
+
804
+ Args:
805
+ result: The checkpoint result.
806
+
807
+ Returns:
808
+ True if should trigger, False otherwise.
809
+ """
810
+ if not self._config.enabled:
811
+ return False
812
+
813
+ trigger = self._config.trigger_on.lower()
814
+ if trigger == "always":
815
+ return True
816
+ elif trigger == "success":
817
+ return result.status.value == "success"
818
+ elif trigger == "failure":
819
+ return result.status.value in ("failure", "error")
820
+
821
+ return True
822
+
823
+
824
+ class {config.class_name}Plugin(ActionPlugin):
825
+ """Plugin that provides custom checkpoint actions."""
826
+
827
+ def _get_plugin_name(self) -> str:
828
+ return "{config.name}"
829
+
830
+ def _get_plugin_version(self) -> str:
831
+ return "{config.version}"
832
+
833
+ def _get_description(self) -> str:
834
+ return "{config.description or 'Custom checkpoint action for Truthound'}"
835
+
836
+ def _get_author(self) -> str:
837
+ return "{config.author or ''}"
838
+
839
+ def get_actions(self) -> dict[str, type[CheckpointAction]]:
840
+ """Return action classes to register.
841
+
842
+ Returns:
843
+ Dictionary of action name to class.
844
+ """
845
+ return {{"{config.name}": {config.class_name}Action}}
846
+ '''
847
+ result.add_file(f"{pkg_name}/plugin.py", content)
848
+
849
+ def _generate_full_plugin(
850
+ self, config: ScaffoldConfig, result: ScaffoldResult, pkg_name: str
851
+ ) -> None:
852
+ """Generate full-featured plugin with multiple components."""
853
+ content = f'''{self._get_header(config)}
854
+
855
+ from __future__ import annotations
856
+
857
+ import logging
858
+ from dataclasses import dataclass
859
+ from typing import Any, Callable, TYPE_CHECKING
860
+
861
+ import polars as pl
862
+
863
+ from truthound.plugins import (
864
+ Plugin,
865
+ PluginInfo,
866
+ PluginType,
867
+ PluginConfig,
868
+ HookType,
869
+ )
870
+ from truthound.validators.base import Validator, ValidatorConfig, ValidationIssue
871
+ from truthound.reporters.base import ValidationReporter, ReporterConfig
872
+ from truthound.types import Severity
873
+
874
+ if TYPE_CHECKING:
875
+ from truthound.plugins import PluginManager
876
+ from truthound.stores.results import ValidationResult
877
+
878
+ logger = logging.getLogger(__name__)
879
+
880
+
881
+ # =============================================================================
882
+ # Validators
883
+ # =============================================================================
884
+
885
+
886
+ class {config.class_name}Validator(Validator):
887
+ """Custom validator provided by {config.name} plugin."""
888
+
889
+ name = "{config.name}_validator"
890
+ category = "custom"
891
+
892
+ def validate(self, lf: pl.LazyFrame) -> list[ValidationIssue]:
893
+ issues: list[ValidationIssue] = []
894
+ # TODO: Implement validation logic
895
+ return issues
896
+
897
+
898
+ # =============================================================================
899
+ # Reporters
900
+ # =============================================================================
901
+
902
+
903
+ @dataclass
904
+ class {config.class_name}ReporterConfig(ReporterConfig):
905
+ """Configuration for {config.class_name} reporter."""
906
+ include_passed: bool = False
907
+
908
+
909
+ class {config.class_name}Reporter(ValidationReporter[{config.class_name}ReporterConfig]):
910
+ """Custom reporter provided by {config.name} plugin."""
911
+
912
+ name = "{config.name}_reporter"
913
+ file_extension = ".txt"
914
+ content_type = "text/plain"
915
+
916
+ @classmethod
917
+ def _default_config(cls) -> {config.class_name}ReporterConfig:
918
+ return {config.class_name}ReporterConfig()
919
+
920
+ def render(self, data: "ValidationResult") -> str:
921
+ lines = [f"Report: {{data.data_asset}}"]
922
+ for r in data.results:
923
+ if not r.success:
924
+ lines.append(f"- {{r.column}}: {{r.issue_type}}")
925
+ return "\\n".join(lines)
926
+
927
+
928
+ # =============================================================================
929
+ # Hooks
930
+ # =============================================================================
931
+
932
+
933
+ def on_validation_complete(
934
+ datasource: Any,
935
+ result: Any,
936
+ issues: list[Any],
937
+ **kwargs: Any,
938
+ ) -> None:
939
+ """Hook called after validation completes."""
940
+ logger.info(f"[{config.name}] Validation complete: {{len(issues)}} issues")
941
+
942
+
943
+ # =============================================================================
944
+ # Plugin
945
+ # =============================================================================
946
+
947
+
948
+ @dataclass
949
+ class {config.class_name}PluginConfig(PluginConfig):
950
+ """Configuration for {config.class_name} plugin.
951
+
952
+ Attributes:
953
+ enable_validator: Enable the validator component.
954
+ enable_reporter: Enable the reporter component.
955
+ enable_hooks: Enable event hooks.
956
+ """
957
+
958
+ enable_validator: bool = True
959
+ enable_reporter: bool = True
960
+ enable_hooks: bool = True
961
+
962
+
963
+ class {config.class_name}Plugin(Plugin[{config.class_name}PluginConfig]):
964
+ """Full-featured Truthound plugin.
965
+
966
+ This plugin provides:
967
+ - Custom validators
968
+ - Custom reporters
969
+ - Event hooks
970
+
971
+ Components can be enabled/disabled via configuration.
972
+ """
973
+
974
+ @property
975
+ def info(self) -> PluginInfo:
976
+ return PluginInfo(
977
+ name="{config.name}",
978
+ version="{config.version}",
979
+ plugin_type=PluginType.CUSTOM,
980
+ description="{config.description or 'Full-featured Truthound plugin'}",
981
+ author="{config.author or ''}",
982
+ tags=["validator", "reporter", "hooks"],
983
+ )
984
+
985
+ def setup(self) -> None:
986
+ """Initialize the plugin."""
987
+ logger.info(f"[{config.name}] Plugin setup complete")
988
+
989
+ def teardown(self) -> None:
990
+ """Cleanup plugin resources."""
991
+ logger.info(f"[{config.name}] Plugin teardown complete")
992
+
993
+ def register(self, manager: "PluginManager") -> None:
994
+ """Register plugin components with the manager.
995
+
996
+ Args:
997
+ manager: The plugin manager.
998
+ """
999
+ config = self._config or {config.class_name}PluginConfig()
1000
+
1001
+ # Register validators
1002
+ if config.enable_validator:
1003
+ manager.register_validator({config.class_name}Validator)
1004
+ logger.debug(f"[{config.name}] Registered validator")
1005
+
1006
+ # Register reporters
1007
+ if config.enable_reporter:
1008
+ manager.register_reporter("{config.name}", {config.class_name}Reporter)
1009
+ logger.debug(f"[{config.name}] Registered reporter")
1010
+
1011
+ # Register hooks
1012
+ if config.enable_hooks:
1013
+ manager.register_hook(
1014
+ HookType.AFTER_VALIDATION.value,
1015
+ on_validation_complete,
1016
+ )
1017
+ logger.debug(f"[{config.name}] Registered hooks")
1018
+ '''
1019
+ result.add_file(f"{pkg_name}/plugin.py", content)
1020
+
1021
+ def _generate_tests(
1022
+ self, config: ScaffoldConfig, result: ScaffoldResult, pkg_name: str
1023
+ ) -> None:
1024
+ """Generate test files."""
1025
+ # Test __init__.py
1026
+ result.add_file("tests/__init__.py", "")
1027
+
1028
+ # Main test file
1029
+ content = f'''"""Tests for {config.name} plugin."""
1030
+
1031
+ import pytest
1032
+
1033
+ from {pkg_name} import {config.class_name}Plugin
1034
+
1035
+
1036
+ class Test{config.class_name}Plugin:
1037
+ """Test cases for {config.class_name}Plugin."""
1038
+
1039
+ def test_plugin_info(self):
1040
+ """Test plugin info properties."""
1041
+ plugin = {config.class_name}Plugin()
1042
+
1043
+ assert plugin.name == "{config.name}"
1044
+ assert plugin.version == "{config.version}"
1045
+
1046
+ def test_plugin_setup(self):
1047
+ """Test plugin setup."""
1048
+ plugin = {config.class_name}Plugin()
1049
+ plugin.setup()
1050
+ # Should not raise
1051
+
1052
+ def test_plugin_teardown(self):
1053
+ """Test plugin teardown."""
1054
+ plugin = {config.class_name}Plugin()
1055
+ plugin.setup()
1056
+ plugin.teardown()
1057
+ # Should not raise
1058
+
1059
+
1060
+ class Test{config.class_name}Components:
1061
+ """Test plugin components."""
1062
+
1063
+ @pytest.mark.parametrize("variant", ["{config.template_variant}"])
1064
+ def test_component_exists(self, variant):
1065
+ """Test that expected components exist."""
1066
+ plugin = {config.class_name}Plugin()
1067
+
1068
+ # Plugin should have required methods
1069
+ assert hasattr(plugin, "setup")
1070
+ assert hasattr(plugin, "teardown")
1071
+ '''
1072
+ result.add_file("tests/test_plugin.py", content)