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,903 @@
1
+ """Encryption pipeline for combining compression and encryption.
2
+
3
+ This module provides a pipeline that combines compression and encryption
4
+ in the correct order (compress-then-encrypt) for optimal security and
5
+ efficiency.
6
+
7
+ Security Note:
8
+ Always compress BEFORE encrypting. Encrypting first prevents effective
9
+ compression (ciphertext appears random), while compressing ciphertext
10
+ can leak information about the plaintext.
11
+
12
+ Example:
13
+ >>> from truthound.stores.encryption.pipeline import (
14
+ ... EncryptionPipeline,
15
+ ... create_secure_pipeline,
16
+ ... )
17
+ >>>
18
+ >>> # Create default secure pipeline
19
+ >>> pipeline = create_secure_pipeline(key)
20
+ >>> encrypted = pipeline.process(data)
21
+ >>> decrypted = pipeline.reverse(encrypted)
22
+ >>>
23
+ >>> # Custom pipeline
24
+ >>> pipeline = (
25
+ ... EncryptionPipeline()
26
+ ... .add_compression("zstd", level=CompressionLevel.HIGH)
27
+ ... .add_encryption("aes-256-gcm", key=key)
28
+ ... )
29
+ """
30
+
31
+ from __future__ import annotations
32
+
33
+ import time
34
+ from abc import ABC, abstractmethod
35
+ from dataclasses import dataclass, field
36
+ from datetime import datetime, timezone
37
+ from enum import Enum, auto
38
+ from typing import Any, Callable
39
+
40
+ from truthound.stores.encryption.base import (
41
+ DecryptionError,
42
+ EncryptionAlgorithm,
43
+ EncryptionConfig,
44
+ EncryptionError,
45
+ EncryptionHeader,
46
+ EncryptionMetrics,
47
+ KeyDerivation,
48
+ generate_nonce,
49
+ generate_salt,
50
+ )
51
+
52
+
53
+ # =============================================================================
54
+ # Pipeline Stage Types
55
+ # =============================================================================
56
+
57
+
58
+ class StageType(Enum):
59
+ """Type of pipeline stage."""
60
+
61
+ COMPRESSION = auto()
62
+ ENCRYPTION = auto()
63
+ TRANSFORM = auto()
64
+ CHECKSUM = auto()
65
+
66
+
67
+ @dataclass
68
+ class StageMetrics:
69
+ """Metrics for a single pipeline stage.
70
+
71
+ Attributes:
72
+ stage_name: Name of the stage.
73
+ stage_type: Type of stage.
74
+ input_size: Input data size.
75
+ output_size: Output data size.
76
+ time_ms: Processing time in milliseconds.
77
+ extra: Additional stage-specific metrics.
78
+ """
79
+
80
+ stage_name: str
81
+ stage_type: StageType
82
+ input_size: int = 0
83
+ output_size: int = 0
84
+ time_ms: float = 0.0
85
+ extra: dict[str, Any] = field(default_factory=dict)
86
+
87
+ @property
88
+ def size_change_percent(self) -> float:
89
+ """Calculate size change percentage."""
90
+ if self.input_size == 0:
91
+ return 0.0
92
+ return ((self.output_size - self.input_size) / self.input_size) * 100
93
+
94
+ def to_dict(self) -> dict[str, Any]:
95
+ """Convert to dictionary."""
96
+ return {
97
+ "stage_name": self.stage_name,
98
+ "stage_type": self.stage_type.name,
99
+ "input_size": self.input_size,
100
+ "output_size": self.output_size,
101
+ "size_change_percent": round(self.size_change_percent, 2),
102
+ "time_ms": round(self.time_ms, 2),
103
+ **self.extra,
104
+ }
105
+
106
+
107
+ @dataclass
108
+ class PipelineMetrics:
109
+ """Aggregated metrics for the entire pipeline.
110
+
111
+ Attributes:
112
+ stages: Metrics for each stage.
113
+ total_input_size: Original input size.
114
+ total_output_size: Final output size.
115
+ total_time_ms: Total processing time.
116
+ """
117
+
118
+ stages: list[StageMetrics] = field(default_factory=list)
119
+ total_input_size: int = 0
120
+ total_output_size: int = 0
121
+ total_time_ms: float = 0.0
122
+
123
+ @property
124
+ def compression_ratio(self) -> float:
125
+ """Overall compression ratio (before encryption overhead)."""
126
+ compression_stages = [
127
+ s for s in self.stages if s.stage_type == StageType.COMPRESSION
128
+ ]
129
+ if not compression_stages or compression_stages[0].input_size == 0:
130
+ return 1.0
131
+ return compression_stages[0].input_size / compression_stages[0].output_size
132
+
133
+ @property
134
+ def overhead_percent(self) -> float:
135
+ """Encryption overhead percentage."""
136
+ if self.total_input_size == 0:
137
+ return 0.0
138
+ # Find size after compression
139
+ compression_stages = [
140
+ s for s in self.stages if s.stage_type == StageType.COMPRESSION
141
+ ]
142
+ compressed_size = (
143
+ compression_stages[-1].output_size
144
+ if compression_stages
145
+ else self.total_input_size
146
+ )
147
+ return ((self.total_output_size - compressed_size) / compressed_size) * 100
148
+
149
+ def to_dict(self) -> dict[str, Any]:
150
+ """Convert to dictionary."""
151
+ return {
152
+ "total_input_size": self.total_input_size,
153
+ "total_output_size": self.total_output_size,
154
+ "compression_ratio": round(self.compression_ratio, 2),
155
+ "overhead_percent": round(self.overhead_percent, 2),
156
+ "total_time_ms": round(self.total_time_ms, 2),
157
+ "stages": [s.to_dict() for s in self.stages],
158
+ }
159
+
160
+
161
+ # =============================================================================
162
+ # Pipeline Result
163
+ # =============================================================================
164
+
165
+
166
+ @dataclass
167
+ class PipelineResult:
168
+ """Result from pipeline processing.
169
+
170
+ Attributes:
171
+ data: Processed data.
172
+ metrics: Pipeline metrics.
173
+ header: Pipeline header for decryption.
174
+ """
175
+
176
+ data: bytes
177
+ metrics: PipelineMetrics
178
+ header: "PipelineHeader"
179
+
180
+ def to_bytes(self) -> bytes:
181
+ """Serialize result with header."""
182
+ header_bytes = self.header.to_bytes()
183
+ return header_bytes + self.data
184
+
185
+ @classmethod
186
+ def from_bytes(cls, data: bytes) -> "PipelineResult":
187
+ """Deserialize result from bytes."""
188
+ header, offset = PipelineHeader.from_bytes(data)
189
+ return cls(
190
+ data=data[offset:],
191
+ metrics=PipelineMetrics(), # Metrics not preserved
192
+ header=header,
193
+ )
194
+
195
+
196
+ # =============================================================================
197
+ # Pipeline Header
198
+ # =============================================================================
199
+
200
+
201
+ @dataclass
202
+ class PipelineHeader:
203
+ """Header describing the pipeline configuration.
204
+
205
+ This header enables self-describing encrypted data that can be
206
+ decrypted without knowing the original pipeline configuration.
207
+
208
+ Format:
209
+ - Magic: 4 bytes ("THEP")
210
+ - Version: 1 byte
211
+ - Flags: 1 byte
212
+ - Stage count: 1 byte
213
+ - Reserved: 1 byte
214
+ - For each stage:
215
+ - Stage type: 1 byte
216
+ - Config length: 2 bytes
217
+ - Config data: variable
218
+ - Header checksum: 4 bytes
219
+ """
220
+
221
+ version: int = 1
222
+ stages: list[dict[str, Any]] = field(default_factory=list)
223
+ flags: int = 0
224
+
225
+ MAGIC = b"THEP" # TrutHound Encryption Pipeline
226
+
227
+ def to_bytes(self) -> bytes:
228
+ """Serialize header to bytes."""
229
+ import json
230
+ import zlib
231
+
232
+ header = (
233
+ self.MAGIC
234
+ + bytes([self.version, self.flags, len(self.stages), 0])
235
+ )
236
+
237
+ for stage in self.stages:
238
+ stage_type = stage["type"]
239
+ config = json.dumps(stage["config"]).encode()
240
+ header += bytes([stage_type]) + len(config).to_bytes(2, "big") + config
241
+
242
+ checksum = zlib.crc32(header).to_bytes(4, "big")
243
+ return header + checksum
244
+
245
+ @classmethod
246
+ def from_bytes(cls, data: bytes) -> tuple["PipelineHeader", int]:
247
+ """Deserialize header from bytes.
248
+
249
+ Returns:
250
+ Tuple of (header, bytes_consumed).
251
+ """
252
+ import json
253
+ import zlib
254
+
255
+ if data[:4] != cls.MAGIC:
256
+ raise DecryptionError("Invalid pipeline header")
257
+
258
+ version = data[4]
259
+ flags = data[5]
260
+ stage_count = data[6]
261
+
262
+ offset = 8
263
+ stages = []
264
+
265
+ for _ in range(stage_count):
266
+ stage_type = data[offset]
267
+ offset += 1
268
+
269
+ config_len = int.from_bytes(data[offset : offset + 2], "big")
270
+ offset += 2
271
+
272
+ config = json.loads(data[offset : offset + config_len].decode())
273
+ offset += config_len
274
+
275
+ stages.append({"type": stage_type, "config": config})
276
+
277
+ # Verify checksum
278
+ expected_checksum = data[offset : offset + 4]
279
+ actual_checksum = zlib.crc32(data[:offset]).to_bytes(4, "big")
280
+ if expected_checksum != actual_checksum:
281
+ raise DecryptionError("Pipeline header checksum mismatch")
282
+
283
+ return (
284
+ cls(version=version, flags=flags, stages=stages),
285
+ offset + 4,
286
+ )
287
+
288
+
289
+ # =============================================================================
290
+ # Pipeline Stages
291
+ # =============================================================================
292
+
293
+
294
+ class PipelineStage(ABC):
295
+ """Base class for pipeline stages."""
296
+
297
+ @property
298
+ @abstractmethod
299
+ def stage_type(self) -> StageType:
300
+ """Get the stage type."""
301
+ ...
302
+
303
+ @property
304
+ @abstractmethod
305
+ def name(self) -> str:
306
+ """Get the stage name."""
307
+ ...
308
+
309
+ @abstractmethod
310
+ def process(self, data: bytes) -> tuple[bytes, dict[str, Any]]:
311
+ """Process data forward through the stage.
312
+
313
+ Args:
314
+ data: Input data.
315
+
316
+ Returns:
317
+ Tuple of (processed_data, config_for_reverse).
318
+ """
319
+ ...
320
+
321
+ @abstractmethod
322
+ def reverse(self, data: bytes, config: dict[str, Any]) -> bytes:
323
+ """Process data backward through the stage.
324
+
325
+ Args:
326
+ data: Processed data.
327
+ config: Configuration from forward pass.
328
+
329
+ Returns:
330
+ Original data.
331
+ """
332
+ ...
333
+
334
+
335
+ class CompressionStage(PipelineStage):
336
+ """Pipeline stage for compression."""
337
+
338
+ def __init__(
339
+ self,
340
+ algorithm: str = "gzip",
341
+ level: Any = None,
342
+ ) -> None:
343
+ """Initialize compression stage.
344
+
345
+ Args:
346
+ algorithm: Compression algorithm name.
347
+ level: Compression level.
348
+ """
349
+ self._algorithm = algorithm
350
+ self._level = level
351
+ self._compressor: Any = None
352
+
353
+ @property
354
+ def stage_type(self) -> StageType:
355
+ return StageType.COMPRESSION
356
+
357
+ @property
358
+ def name(self) -> str:
359
+ return f"compress_{self._algorithm}"
360
+
361
+ def _get_compressor(self) -> Any:
362
+ """Get compressor instance."""
363
+ if self._compressor is None:
364
+ from truthound.stores.compression import get_compressor
365
+
366
+ self._compressor = get_compressor(self._algorithm, level=self._level)
367
+ return self._compressor
368
+
369
+ def process(self, data: bytes) -> tuple[bytes, dict[str, Any]]:
370
+ """Compress data."""
371
+ compressor = self._get_compressor()
372
+ compressed = compressor.compress(data)
373
+ config = {
374
+ "algorithm": self._algorithm,
375
+ "original_size": len(data),
376
+ }
377
+ return compressed, config
378
+
379
+ def reverse(self, data: bytes, config: dict[str, Any]) -> bytes:
380
+ """Decompress data."""
381
+ compressor = self._get_compressor()
382
+ return compressor.decompress(data)
383
+
384
+
385
+ class EncryptionStage(PipelineStage):
386
+ """Pipeline stage for encryption."""
387
+
388
+ def __init__(
389
+ self,
390
+ algorithm: EncryptionAlgorithm | str = EncryptionAlgorithm.AES_256_GCM,
391
+ key: bytes | None = None,
392
+ aad: bytes | None = None,
393
+ ) -> None:
394
+ """Initialize encryption stage.
395
+
396
+ Args:
397
+ algorithm: Encryption algorithm.
398
+ key: Encryption key.
399
+ aad: Additional authenticated data.
400
+ """
401
+ if isinstance(algorithm, str):
402
+ algorithm = EncryptionAlgorithm(algorithm)
403
+ self._algorithm = algorithm
404
+ self._key = key
405
+ self._aad = aad
406
+ self._encryptor: Any = None
407
+
408
+ @property
409
+ def stage_type(self) -> StageType:
410
+ return StageType.ENCRYPTION
411
+
412
+ @property
413
+ def name(self) -> str:
414
+ return f"encrypt_{self._algorithm.value}"
415
+
416
+ def set_key(self, key: bytes) -> None:
417
+ """Set the encryption key."""
418
+ self._key = key
419
+ self._encryptor = None
420
+
421
+ def _get_encryptor(self) -> Any:
422
+ """Get encryptor instance."""
423
+ if self._encryptor is None:
424
+ from truthound.stores.encryption.providers import get_encryptor
425
+
426
+ self._encryptor = get_encryptor(self._algorithm)
427
+ return self._encryptor
428
+
429
+ def process(self, data: bytes) -> tuple[bytes, dict[str, Any]]:
430
+ """Encrypt data."""
431
+ if self._key is None:
432
+ raise EncryptionError("Encryption key not set")
433
+
434
+ encryptor = self._get_encryptor()
435
+ encrypted = encryptor.encrypt(data, self._key, aad=self._aad)
436
+
437
+ config = {
438
+ "algorithm": self._algorithm.value,
439
+ "nonce_size": self._algorithm.nonce_size,
440
+ "tag_size": self._algorithm.tag_size,
441
+ }
442
+ return encrypted, config
443
+
444
+ def reverse(self, data: bytes, config: dict[str, Any]) -> bytes:
445
+ """Decrypt data."""
446
+ if self._key is None:
447
+ raise DecryptionError("Decryption key not set")
448
+
449
+ encryptor = self._get_encryptor()
450
+ return encryptor.decrypt(data, self._key, aad=self._aad)
451
+
452
+
453
+ class ChecksumStage(PipelineStage):
454
+ """Pipeline stage for checksum verification."""
455
+
456
+ def __init__(self, algorithm: str = "sha256") -> None:
457
+ """Initialize checksum stage.
458
+
459
+ Args:
460
+ algorithm: Hash algorithm (sha256, sha512, blake2b).
461
+ """
462
+ self._algorithm = algorithm
463
+
464
+ @property
465
+ def stage_type(self) -> StageType:
466
+ return StageType.CHECKSUM
467
+
468
+ @property
469
+ def name(self) -> str:
470
+ return f"checksum_{self._algorithm}"
471
+
472
+ def _hash(self, data: bytes) -> bytes:
473
+ """Compute hash of data."""
474
+ import hashlib
475
+
476
+ if self._algorithm == "blake2b":
477
+ return hashlib.blake2b(data, digest_size=32).digest()
478
+ return hashlib.new(self._algorithm, data).digest()
479
+
480
+ def process(self, data: bytes) -> tuple[bytes, dict[str, Any]]:
481
+ """Add checksum to data."""
482
+ checksum = self._hash(data)
483
+ config = {
484
+ "algorithm": self._algorithm,
485
+ "checksum": checksum.hex(),
486
+ }
487
+ # Prepend checksum length and checksum
488
+ return bytes([len(checksum)]) + checksum + data, config
489
+
490
+ def reverse(self, data: bytes, config: dict[str, Any]) -> bytes:
491
+ """Verify and remove checksum."""
492
+ checksum_len = data[0]
493
+ stored_checksum = data[1 : 1 + checksum_len]
494
+ actual_data = data[1 + checksum_len :]
495
+
496
+ computed_checksum = self._hash(actual_data)
497
+ if stored_checksum != computed_checksum:
498
+ raise DecryptionError(
499
+ f"Checksum verification failed: expected {stored_checksum.hex()}, "
500
+ f"got {computed_checksum.hex()}"
501
+ )
502
+
503
+ return actual_data
504
+
505
+
506
+ # =============================================================================
507
+ # Encryption Pipeline
508
+ # =============================================================================
509
+
510
+
511
+ class EncryptionPipeline:
512
+ """Pipeline for combining compression and encryption.
513
+
514
+ Provides a fluent interface for building secure data processing
515
+ pipelines with compression, encryption, and integrity verification.
516
+
517
+ Example:
518
+ >>> pipeline = (
519
+ ... EncryptionPipeline()
520
+ ... .add_compression("zstd", level=CompressionLevel.HIGH)
521
+ ... .add_encryption("aes-256-gcm", key=my_key)
522
+ ... .add_checksum("sha256")
523
+ ... )
524
+ >>>
525
+ >>> result = pipeline.process(sensitive_data)
526
+ >>> original = pipeline.reverse(result.data, result.header)
527
+ """
528
+
529
+ def __init__(self) -> None:
530
+ """Initialize empty pipeline."""
531
+ self._stages: list[PipelineStage] = []
532
+
533
+ def add_stage(self, stage: PipelineStage) -> "EncryptionPipeline":
534
+ """Add a stage to the pipeline.
535
+
536
+ Args:
537
+ stage: Pipeline stage to add.
538
+
539
+ Returns:
540
+ Self for chaining.
541
+ """
542
+ self._stages.append(stage)
543
+ return self
544
+
545
+ def add_compression(
546
+ self,
547
+ algorithm: str = "gzip",
548
+ level: Any = None,
549
+ ) -> "EncryptionPipeline":
550
+ """Add compression stage.
551
+
552
+ Args:
553
+ algorithm: Compression algorithm.
554
+ level: Compression level.
555
+
556
+ Returns:
557
+ Self for chaining.
558
+ """
559
+ return self.add_stage(CompressionStage(algorithm, level))
560
+
561
+ def add_encryption(
562
+ self,
563
+ algorithm: EncryptionAlgorithm | str = EncryptionAlgorithm.AES_256_GCM,
564
+ key: bytes | None = None,
565
+ aad: bytes | None = None,
566
+ ) -> "EncryptionPipeline":
567
+ """Add encryption stage.
568
+
569
+ Args:
570
+ algorithm: Encryption algorithm.
571
+ key: Encryption key.
572
+ aad: Additional authenticated data.
573
+
574
+ Returns:
575
+ Self for chaining.
576
+ """
577
+ return self.add_stage(EncryptionStage(algorithm, key, aad))
578
+
579
+ def add_checksum(self, algorithm: str = "sha256") -> "EncryptionPipeline":
580
+ """Add checksum verification stage.
581
+
582
+ Args:
583
+ algorithm: Hash algorithm.
584
+
585
+ Returns:
586
+ Self for chaining.
587
+ """
588
+ return self.add_stage(ChecksumStage(algorithm))
589
+
590
+ def set_key(self, key: bytes) -> "EncryptionPipeline":
591
+ """Set encryption key for all encryption stages.
592
+
593
+ Args:
594
+ key: Encryption key.
595
+
596
+ Returns:
597
+ Self for chaining.
598
+ """
599
+ for stage in self._stages:
600
+ if isinstance(stage, EncryptionStage):
601
+ stage.set_key(key)
602
+ return self
603
+
604
+ def process(self, data: bytes) -> PipelineResult:
605
+ """Process data through all stages.
606
+
607
+ Args:
608
+ data: Input data.
609
+
610
+ Returns:
611
+ Pipeline result with encrypted data and metadata.
612
+ """
613
+ metrics = PipelineMetrics(total_input_size=len(data))
614
+ header_stages: list[dict[str, Any]] = []
615
+
616
+ current_data = data
617
+ total_start = time.perf_counter()
618
+
619
+ for stage in self._stages:
620
+ start_time = time.perf_counter()
621
+ input_size = len(current_data)
622
+
623
+ current_data, config = stage.process(current_data)
624
+
625
+ elapsed_ms = (time.perf_counter() - start_time) * 1000
626
+ output_size = len(current_data)
627
+
628
+ stage_metrics = StageMetrics(
629
+ stage_name=stage.name,
630
+ stage_type=stage.stage_type,
631
+ input_size=input_size,
632
+ output_size=output_size,
633
+ time_ms=elapsed_ms,
634
+ )
635
+ metrics.stages.append(stage_metrics)
636
+
637
+ header_stages.append({
638
+ "type": stage.stage_type.value,
639
+ "config": config,
640
+ })
641
+
642
+ metrics.total_output_size = len(current_data)
643
+ metrics.total_time_ms = (time.perf_counter() - total_start) * 1000
644
+
645
+ header = PipelineHeader(stages=header_stages)
646
+
647
+ return PipelineResult(
648
+ data=current_data,
649
+ metrics=metrics,
650
+ header=header,
651
+ )
652
+
653
+ def reverse(self, data: bytes, header: PipelineHeader | None = None) -> bytes:
654
+ """Reverse process data through all stages.
655
+
656
+ Args:
657
+ data: Processed data.
658
+ header: Pipeline header (if not embedded in data).
659
+
660
+ Returns:
661
+ Original data.
662
+ """
663
+ # If header not provided, try to extract from data
664
+ if header is None:
665
+ header, offset = PipelineHeader.from_bytes(data)
666
+ data = data[offset:]
667
+
668
+ current_data = data
669
+
670
+ # Process stages in reverse order
671
+ for stage, stage_config in zip(
672
+ reversed(self._stages),
673
+ reversed(header.stages),
674
+ ):
675
+ current_data = stage.reverse(current_data, stage_config["config"])
676
+
677
+ return current_data
678
+
679
+ def process_to_bytes(self, data: bytes) -> bytes:
680
+ """Process data and return bytes with embedded header.
681
+
682
+ Args:
683
+ data: Input data.
684
+
685
+ Returns:
686
+ Processed data with header.
687
+ """
688
+ result = self.process(data)
689
+ return result.to_bytes()
690
+
691
+ def reverse_from_bytes(self, data: bytes) -> bytes:
692
+ """Reverse process data with embedded header.
693
+
694
+ Args:
695
+ data: Processed data with header.
696
+
697
+ Returns:
698
+ Original data.
699
+ """
700
+ result = PipelineResult.from_bytes(data)
701
+ return self.reverse(result.data, result.header)
702
+
703
+
704
+ # =============================================================================
705
+ # Pre-built Pipelines
706
+ # =============================================================================
707
+
708
+
709
+ def create_secure_pipeline(
710
+ key: bytes,
711
+ compression: str = "gzip",
712
+ encryption: EncryptionAlgorithm = EncryptionAlgorithm.AES_256_GCM,
713
+ include_checksum: bool = True,
714
+ ) -> EncryptionPipeline:
715
+ """Create a secure compress-then-encrypt pipeline.
716
+
717
+ Args:
718
+ key: Encryption key.
719
+ compression: Compression algorithm.
720
+ encryption: Encryption algorithm.
721
+ include_checksum: Whether to include checksum verification.
722
+
723
+ Returns:
724
+ Configured pipeline.
725
+ """
726
+ pipeline = (
727
+ EncryptionPipeline()
728
+ .add_compression(compression)
729
+ .add_encryption(encryption, key=key)
730
+ )
731
+
732
+ if include_checksum:
733
+ pipeline.add_checksum()
734
+
735
+ return pipeline
736
+
737
+
738
+ def create_fast_pipeline(
739
+ key: bytes,
740
+ compression: str = "lz4",
741
+ ) -> EncryptionPipeline:
742
+ """Create a fast pipeline optimized for speed.
743
+
744
+ Uses LZ4 compression and ChaCha20-Poly1305 encryption
745
+ for maximum throughput.
746
+
747
+ Args:
748
+ key: Encryption key.
749
+ compression: Compression algorithm (default: lz4).
750
+
751
+ Returns:
752
+ Configured pipeline.
753
+ """
754
+ return (
755
+ EncryptionPipeline()
756
+ .add_compression(compression)
757
+ .add_encryption(EncryptionAlgorithm.CHACHA20_POLY1305, key=key)
758
+ )
759
+
760
+
761
+ def create_max_compression_pipeline(
762
+ key: bytes,
763
+ compression: str = "zstd",
764
+ ) -> EncryptionPipeline:
765
+ """Create a pipeline optimized for maximum compression.
766
+
767
+ Uses Zstandard with high compression level.
768
+
769
+ Args:
770
+ key: Encryption key.
771
+ compression: Compression algorithm (default: zstd).
772
+
773
+ Returns:
774
+ Configured pipeline.
775
+ """
776
+ from truthound.stores.compression import CompressionLevel
777
+
778
+ return (
779
+ EncryptionPipeline()
780
+ .add_compression(compression, level=CompressionLevel.HIGH)
781
+ .add_encryption(EncryptionAlgorithm.AES_256_GCM, key=key)
782
+ .add_checksum()
783
+ )
784
+
785
+
786
+ def create_password_pipeline(
787
+ password: str,
788
+ compression: str = "gzip",
789
+ kdf: KeyDerivation = KeyDerivation.ARGON2ID,
790
+ ) -> tuple[EncryptionPipeline, bytes]:
791
+ """Create a pipeline with password-derived key.
792
+
793
+ Args:
794
+ password: Password for key derivation.
795
+ compression: Compression algorithm.
796
+ kdf: Key derivation function.
797
+
798
+ Returns:
799
+ Tuple of (pipeline, salt). Salt must be stored with the data.
800
+ """
801
+ from truthound.stores.encryption.keys import derive_key
802
+
803
+ key, salt = derive_key(password, kdf=kdf)
804
+
805
+ pipeline = (
806
+ EncryptionPipeline()
807
+ .add_compression(compression)
808
+ .add_encryption(EncryptionAlgorithm.AES_256_GCM, key=key)
809
+ .add_checksum()
810
+ )
811
+
812
+ return pipeline, salt
813
+
814
+
815
+ # =============================================================================
816
+ # Streaming Pipeline
817
+ # =============================================================================
818
+
819
+
820
+ class StreamingPipeline:
821
+ """Streaming version of encryption pipeline for large data.
822
+
823
+ Combines streaming compression and streaming encryption for
824
+ memory-efficient processing of large datasets.
825
+
826
+ Example:
827
+ >>> pipeline = StreamingPipeline(key, "output.enc")
828
+ >>> with pipeline as p:
829
+ ... for chunk in read_large_file():
830
+ ... p.write(chunk)
831
+ """
832
+
833
+ def __init__(
834
+ self,
835
+ key: bytes,
836
+ output: Any, # str | Path | BinaryIO
837
+ compression: str = "gzip",
838
+ encryption: EncryptionAlgorithm = EncryptionAlgorithm.AES_256_GCM,
839
+ chunk_size: int = 64 * 1024,
840
+ ) -> None:
841
+ """Initialize streaming pipeline.
842
+
843
+ Args:
844
+ key: Encryption key.
845
+ output: Output file path or stream.
846
+ compression: Compression algorithm.
847
+ encryption: Encryption algorithm.
848
+ chunk_size: Processing chunk size.
849
+ """
850
+ self._key = key
851
+ self._output = output
852
+ self._compression = compression
853
+ self._encryption = encryption
854
+ self._chunk_size = chunk_size
855
+
856
+ self._compressor: Any = None
857
+ self._encryptor: Any = None
858
+ self._buffer = b""
859
+
860
+ def __enter__(self) -> "StreamingPipeline":
861
+ """Start the streaming pipeline."""
862
+ from truthound.stores.compression import get_compressor
863
+ from truthound.stores.encryption.streaming import StreamingEncryptor
864
+
865
+ import io
866
+ self._compressed_buffer = io.BytesIO()
867
+
868
+ # Initialize compressor
869
+ self._compressor = get_compressor(self._compression)
870
+
871
+ # Initialize encryptor
872
+ self._encryptor = StreamingEncryptor(
873
+ self._key,
874
+ self._output,
875
+ self._encryption,
876
+ self._chunk_size,
877
+ )
878
+
879
+ return self
880
+
881
+ def write(self, data: bytes) -> int:
882
+ """Write data to the pipeline.
883
+
884
+ Args:
885
+ data: Data to process.
886
+
887
+ Returns:
888
+ Number of bytes written.
889
+ """
890
+ # Compress data
891
+ compressed = self._compressor.compress(data)
892
+
893
+ # Write compressed data to encryptor
894
+ self._encryptor.write(compressed)
895
+
896
+ return len(data)
897
+
898
+ def __exit__(self, *args: Any) -> None:
899
+ """Finalize and close the pipeline."""
900
+ # Finalize compression (flush any remaining data)
901
+ # Note: Some compressors need explicit finalization
902
+ self._encryptor.finalize()
903
+ self._encryptor.close()