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,774 @@
1
+ """Base Classes for Distributed Checkpoint Orchestration.
2
+
3
+ This module provides abstract base classes that backends can extend
4
+ to implement distributed checkpoint execution.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import asyncio
10
+ import logging
11
+ import threading
12
+ import time
13
+ from abc import ABC, abstractmethod
14
+ from concurrent.futures import ThreadPoolExecutor, Future
15
+ from contextlib import contextmanager
16
+ from dataclasses import dataclass, field
17
+ from datetime import datetime, timedelta
18
+ from typing import TYPE_CHECKING, Any, Callable, Generic, Iterator, TypeVar
19
+ from queue import Queue, Empty
20
+
21
+ from truthound.checkpoint.distributed.protocols import (
22
+ BackendCapability,
23
+ ClusterState,
24
+ DistributedBackendProtocol,
25
+ DistributedConfig,
26
+ DistributedError,
27
+ DistributedTask,
28
+ DistributedTaskProtocol,
29
+ DistributedTaskResult,
30
+ TaskCancelledError,
31
+ TaskPriority,
32
+ TaskState,
33
+ TaskSubmissionError,
34
+ TaskTimeoutError,
35
+ WorkerInfo,
36
+ WorkerState,
37
+ WorkerNotAvailableError,
38
+ BackendNotAvailableError,
39
+ )
40
+
41
+ if TYPE_CHECKING:
42
+ from truthound.checkpoint.checkpoint import Checkpoint, CheckpointResult
43
+
44
+
45
+ logger = logging.getLogger(__name__)
46
+
47
+
48
+ T = TypeVar("T")
49
+
50
+
51
+ # =============================================================================
52
+ # Metrics Collection
53
+ # =============================================================================
54
+
55
+
56
+ @dataclass
57
+ class TaskMetrics:
58
+ """Metrics for task execution.
59
+
60
+ Attributes:
61
+ tasks_submitted: Total tasks submitted.
62
+ tasks_succeeded: Tasks that succeeded.
63
+ tasks_failed: Tasks that failed.
64
+ tasks_cancelled: Tasks that were cancelled.
65
+ tasks_timed_out: Tasks that timed out.
66
+ total_execution_time_ms: Total execution time in milliseconds.
67
+ total_queue_time_ms: Total time spent in queue.
68
+ retries: Total retry attempts.
69
+ """
70
+
71
+ tasks_submitted: int = 0
72
+ tasks_succeeded: int = 0
73
+ tasks_failed: int = 0
74
+ tasks_cancelled: int = 0
75
+ tasks_timed_out: int = 0
76
+ total_execution_time_ms: float = 0.0
77
+ total_queue_time_ms: float = 0.0
78
+ retries: int = 0
79
+
80
+ @property
81
+ def tasks_completed(self) -> int:
82
+ """Total completed tasks (success + failed)."""
83
+ return self.tasks_succeeded + self.tasks_failed
84
+
85
+ @property
86
+ def success_rate(self) -> float:
87
+ """Success rate (0.0 to 1.0)."""
88
+ if self.tasks_completed == 0:
89
+ return 0.0
90
+ return self.tasks_succeeded / self.tasks_completed
91
+
92
+ @property
93
+ def average_execution_time_ms(self) -> float:
94
+ """Average execution time in milliseconds."""
95
+ if self.tasks_completed == 0:
96
+ return 0.0
97
+ return self.total_execution_time_ms / self.tasks_completed
98
+
99
+ @property
100
+ def average_queue_time_ms(self) -> float:
101
+ """Average queue time in milliseconds."""
102
+ if self.tasks_completed == 0:
103
+ return 0.0
104
+ return self.total_queue_time_ms / self.tasks_completed
105
+
106
+ def record_submission(self) -> None:
107
+ """Record a task submission."""
108
+ self.tasks_submitted += 1
109
+
110
+ def record_completion(self, result: DistributedTaskResult) -> None:
111
+ """Record a task completion."""
112
+ if result.state == TaskState.SUCCEEDED:
113
+ self.tasks_succeeded += 1
114
+ elif result.state == TaskState.FAILED:
115
+ self.tasks_failed += 1
116
+ elif result.state == TaskState.CANCELLED:
117
+ self.tasks_cancelled += 1
118
+ elif result.state == TaskState.TIMEOUT:
119
+ self.tasks_timed_out += 1
120
+
121
+ if result.duration_ms:
122
+ self.total_execution_time_ms += result.duration_ms
123
+ if result.queue_time_ms:
124
+ self.total_queue_time_ms += result.queue_time_ms
125
+ self.retries += result.retries
126
+
127
+ def to_dict(self) -> dict[str, Any]:
128
+ """Convert to dictionary."""
129
+ return {
130
+ "tasks_submitted": self.tasks_submitted,
131
+ "tasks_succeeded": self.tasks_succeeded,
132
+ "tasks_failed": self.tasks_failed,
133
+ "tasks_cancelled": self.tasks_cancelled,
134
+ "tasks_timed_out": self.tasks_timed_out,
135
+ "tasks_completed": self.tasks_completed,
136
+ "success_rate": self.success_rate,
137
+ "average_execution_time_ms": self.average_execution_time_ms,
138
+ "average_queue_time_ms": self.average_queue_time_ms,
139
+ "total_retries": self.retries,
140
+ }
141
+
142
+ def to_prometheus(self) -> str:
143
+ """Export as Prometheus metrics."""
144
+ lines = [
145
+ f"truthound_distributed_tasks_submitted_total {self.tasks_submitted}",
146
+ f"truthound_distributed_tasks_succeeded_total {self.tasks_succeeded}",
147
+ f"truthound_distributed_tasks_failed_total {self.tasks_failed}",
148
+ f"truthound_distributed_tasks_cancelled_total {self.tasks_cancelled}",
149
+ f"truthound_distributed_tasks_timed_out_total {self.tasks_timed_out}",
150
+ f"truthound_distributed_task_execution_time_ms_total {self.total_execution_time_ms}",
151
+ f"truthound_distributed_task_queue_time_ms_total {self.total_queue_time_ms}",
152
+ f"truthound_distributed_task_retries_total {self.retries}",
153
+ ]
154
+ return "\n".join(lines)
155
+
156
+
157
+ # =============================================================================
158
+ # Base Backend Implementation
159
+ # =============================================================================
160
+
161
+
162
+ class BaseDistributedBackend(ABC):
163
+ """Abstract base class for distributed backends.
164
+
165
+ This provides common functionality that all backends can use,
166
+ including metrics collection, retry logic, and task tracking.
167
+
168
+ Subclasses must implement:
169
+ - _do_submit(): Actual task submission logic
170
+ - _do_connect(): Backend connection logic
171
+ - _do_disconnect(): Backend disconnection logic
172
+ - _do_get_cluster_state(): Get cluster state
173
+ - _do_get_workers(): Get worker list
174
+ """
175
+
176
+ def __init__(
177
+ self,
178
+ config: DistributedConfig | None = None,
179
+ **kwargs: Any,
180
+ ) -> None:
181
+ """Initialize the backend.
182
+
183
+ Args:
184
+ config: Distributed configuration.
185
+ **kwargs: Additional backend-specific options.
186
+ """
187
+ self._config = config or DistributedConfig()
188
+
189
+ # Apply kwargs to backend_options
190
+ for key, value in kwargs.items():
191
+ self._config.backend_options[key] = value
192
+
193
+ self._connected = False
194
+ self._lock = threading.RLock()
195
+ self._tasks: dict[str, DistributedTask[Any]] = {}
196
+ self._metrics = TaskMetrics()
197
+
198
+ # Callbacks
199
+ self._on_task_complete: list[Callable[[DistributedTaskResult], None]] = []
200
+ self._on_task_error: list[Callable[[str, Exception], None]] = []
201
+
202
+ @property
203
+ @abstractmethod
204
+ def name(self) -> str:
205
+ """Get backend name."""
206
+ ...
207
+
208
+ @property
209
+ @abstractmethod
210
+ def capabilities(self) -> BackendCapability:
211
+ """Get backend capabilities."""
212
+ ...
213
+
214
+ @property
215
+ def is_connected(self) -> bool:
216
+ """Check if backend is connected."""
217
+ return self._connected
218
+
219
+ @property
220
+ def config(self) -> DistributedConfig:
221
+ """Get backend configuration."""
222
+ return self._config
223
+
224
+ @property
225
+ def metrics(self) -> TaskMetrics:
226
+ """Get task metrics."""
227
+ return self._metrics
228
+
229
+ # -------------------------------------------------------------------------
230
+ # Connection Management
231
+ # -------------------------------------------------------------------------
232
+
233
+ def connect(self, **kwargs: Any) -> None:
234
+ """Connect to the backend."""
235
+ with self._lock:
236
+ if self._connected:
237
+ return
238
+
239
+ try:
240
+ self._do_connect(**kwargs)
241
+ self._connected = True
242
+ logger.info(f"Connected to {self.name} backend")
243
+ except Exception as e:
244
+ raise BackendNotAvailableError(
245
+ self.name,
246
+ reason=str(e),
247
+ )
248
+
249
+ def disconnect(self) -> None:
250
+ """Disconnect from the backend."""
251
+ with self._lock:
252
+ if not self._connected:
253
+ return
254
+
255
+ try:
256
+ self._do_disconnect()
257
+ finally:
258
+ self._connected = False
259
+ logger.info(f"Disconnected from {self.name} backend")
260
+
261
+ @abstractmethod
262
+ def _do_connect(self, **kwargs: Any) -> None:
263
+ """Perform actual connection (implemented by subclass)."""
264
+ ...
265
+
266
+ @abstractmethod
267
+ def _do_disconnect(self) -> None:
268
+ """Perform actual disconnection (implemented by subclass)."""
269
+ ...
270
+
271
+ @contextmanager
272
+ def connection(self, **kwargs: Any) -> Iterator[None]:
273
+ """Context manager for connection lifecycle."""
274
+ self.connect(**kwargs)
275
+ try:
276
+ yield
277
+ finally:
278
+ self.disconnect()
279
+
280
+ # -------------------------------------------------------------------------
281
+ # Task Submission
282
+ # -------------------------------------------------------------------------
283
+
284
+ def submit(
285
+ self,
286
+ checkpoint: "Checkpoint",
287
+ priority: TaskPriority = TaskPriority.NORMAL,
288
+ timeout: float | None = None,
289
+ context: dict[str, Any] | None = None,
290
+ **kwargs: Any,
291
+ ) -> DistributedTaskProtocol["CheckpointResult"]:
292
+ """Submit a checkpoint for execution."""
293
+ if not self._connected:
294
+ raise TaskSubmissionError(
295
+ "Backend not connected",
296
+ checkpoint_name=checkpoint.name,
297
+ reason="Call connect() first",
298
+ )
299
+
300
+ # Create task
301
+ task: DistributedTask["CheckpointResult"] = DistributedTask.create(
302
+ checkpoint=checkpoint,
303
+ backend=self,
304
+ )
305
+ task._metadata["priority"] = priority.value
306
+ task._metadata["context"] = context or {}
307
+
308
+ timeout = timeout or self._config.task_timeout_seconds
309
+
310
+ with self._lock:
311
+ self._tasks[task.task_id] = task
312
+ self._metrics.record_submission()
313
+
314
+ try:
315
+ # Submit to backend
316
+ task._set_state(TaskState.SUBMITTED)
317
+ self._do_submit(task, checkpoint, priority, timeout, context, **kwargs)
318
+ task._set_state(TaskState.QUEUED)
319
+ logger.debug(f"Task {task.task_id} submitted for checkpoint {checkpoint.name}")
320
+ return task
321
+
322
+ except Exception as e:
323
+ task._set_error(str(e), e)
324
+ raise TaskSubmissionError(
325
+ f"Failed to submit task: {e}",
326
+ checkpoint_name=checkpoint.name,
327
+ reason=str(e),
328
+ )
329
+
330
+ def submit_batch(
331
+ self,
332
+ checkpoints: list["Checkpoint"],
333
+ priority: TaskPriority = TaskPriority.NORMAL,
334
+ timeout: float | None = None,
335
+ context: dict[str, Any] | None = None,
336
+ **kwargs: Any,
337
+ ) -> list[DistributedTaskProtocol["CheckpointResult"]]:
338
+ """Submit multiple checkpoints for execution."""
339
+ # Check capability
340
+ if not (self.capabilities & BackendCapability.BATCH_SUBMIT):
341
+ # Fall back to sequential submission
342
+ return [
343
+ self.submit(cp, priority, timeout, context, **kwargs)
344
+ for cp in checkpoints
345
+ ]
346
+
347
+ tasks = []
348
+ for checkpoint in checkpoints:
349
+ try:
350
+ task = self.submit(checkpoint, priority, timeout, context, **kwargs)
351
+ tasks.append(task)
352
+ except TaskSubmissionError as e:
353
+ logger.error(f"Failed to submit {checkpoint.name}: {e}")
354
+ # Continue with other checkpoints
355
+
356
+ return tasks
357
+
358
+ @abstractmethod
359
+ def _do_submit(
360
+ self,
361
+ task: DistributedTask["CheckpointResult"],
362
+ checkpoint: "Checkpoint",
363
+ priority: TaskPriority,
364
+ timeout: float,
365
+ context: dict[str, Any] | None,
366
+ **kwargs: Any,
367
+ ) -> None:
368
+ """Perform actual task submission (implemented by subclass)."""
369
+ ...
370
+
371
+ # -------------------------------------------------------------------------
372
+ # Task Management
373
+ # -------------------------------------------------------------------------
374
+
375
+ def get_task(self, task_id: str) -> DistributedTaskProtocol["CheckpointResult"] | None:
376
+ """Get a task by ID."""
377
+ with self._lock:
378
+ return self._tasks.get(task_id)
379
+
380
+ def cancel_task(self, task_id: str, terminate: bool = False) -> bool:
381
+ """Cancel a task."""
382
+ with self._lock:
383
+ task = self._tasks.get(task_id)
384
+ if task is None:
385
+ return False
386
+ return task.cancel(terminate=terminate)
387
+
388
+ def _complete_task(
389
+ self,
390
+ task_id: str,
391
+ result: "CheckpointResult | None" = None,
392
+ error: str | None = None,
393
+ exception: Exception | None = None,
394
+ ) -> None:
395
+ """Mark a task as complete (internal use)."""
396
+ with self._lock:
397
+ task = self._tasks.get(task_id)
398
+ if task is None:
399
+ return
400
+
401
+ if error:
402
+ task._set_error(error, exception)
403
+ elif result:
404
+ task._set_result(result)
405
+
406
+ # Record metrics
407
+ self._metrics.record_completion(task.to_result())
408
+
409
+ # Invoke callbacks
410
+ task_result = task.to_result()
411
+ for callback in self._on_task_complete:
412
+ try:
413
+ callback(task_result)
414
+ except Exception as e:
415
+ logger.error(f"Callback error: {e}")
416
+
417
+ # -------------------------------------------------------------------------
418
+ # Cluster State
419
+ # -------------------------------------------------------------------------
420
+
421
+ def get_cluster_state(self) -> ClusterState:
422
+ """Get current cluster state."""
423
+ if not self._connected:
424
+ return ClusterState(
425
+ backend_name=self.name,
426
+ is_healthy=False,
427
+ )
428
+ return self._do_get_cluster_state()
429
+
430
+ @abstractmethod
431
+ def _do_get_cluster_state(self) -> ClusterState:
432
+ """Get cluster state (implemented by subclass)."""
433
+ ...
434
+
435
+ def get_workers(self) -> list[WorkerInfo]:
436
+ """Get list of workers."""
437
+ if not self._connected:
438
+ return []
439
+ return self._do_get_workers()
440
+
441
+ @abstractmethod
442
+ def _do_get_workers(self) -> list[WorkerInfo]:
443
+ """Get workers (implemented by subclass)."""
444
+ ...
445
+
446
+ def scale_workers(self, count: int) -> bool:
447
+ """Scale the number of workers."""
448
+ if not (self.capabilities & BackendCapability.WORKER_SCALING):
449
+ return False
450
+ return self._do_scale_workers(count)
451
+
452
+ def _do_scale_workers(self, count: int) -> bool:
453
+ """Scale workers (override if supported)."""
454
+ return False
455
+
456
+ def health_check(self) -> bool:
457
+ """Perform health check."""
458
+ if not self._connected:
459
+ return False
460
+ try:
461
+ state = self.get_cluster_state()
462
+ return state.is_healthy
463
+ except Exception:
464
+ return False
465
+
466
+ # -------------------------------------------------------------------------
467
+ # Callbacks
468
+ # -------------------------------------------------------------------------
469
+
470
+ def on_task_complete(
471
+ self,
472
+ callback: Callable[[DistributedTaskResult], None],
473
+ ) -> None:
474
+ """Register a task completion callback."""
475
+ self._on_task_complete.append(callback)
476
+
477
+ def on_task_error(
478
+ self,
479
+ callback: Callable[[str, Exception], None],
480
+ ) -> None:
481
+ """Register a task error callback."""
482
+ self._on_task_error.append(callback)
483
+
484
+ # -------------------------------------------------------------------------
485
+ # Utilities
486
+ # -------------------------------------------------------------------------
487
+
488
+ def _calculate_retry_delay(self, attempt: int) -> float:
489
+ """Calculate retry delay with exponential backoff."""
490
+ delay = self._config.retry_delay_seconds * (
491
+ self._config.retry_backoff_multiplier ** attempt
492
+ )
493
+ return min(delay, self._config.retry_max_delay_seconds)
494
+
495
+
496
+ # =============================================================================
497
+ # Base Orchestrator Implementation
498
+ # =============================================================================
499
+
500
+
501
+ class BaseDistributedOrchestrator:
502
+ """Base class for distributed checkpoint orchestrators.
503
+
504
+ The orchestrator provides a high-level API for submitting and
505
+ managing distributed checkpoint execution across multiple backends.
506
+ """
507
+
508
+ def __init__(
509
+ self,
510
+ backend: BaseDistributedBackend,
511
+ config: DistributedConfig | None = None,
512
+ ) -> None:
513
+ """Initialize the orchestrator.
514
+
515
+ Args:
516
+ backend: The distributed backend to use.
517
+ config: Configuration options.
518
+ """
519
+ self._backend = backend
520
+ self._config = config or backend.config
521
+ self._lock = threading.RLock()
522
+ self._executor: ThreadPoolExecutor | None = None
523
+
524
+ @property
525
+ def backend(self) -> BaseDistributedBackend:
526
+ """Get the backend."""
527
+ return self._backend
528
+
529
+ @property
530
+ def is_connected(self) -> bool:
531
+ """Check if connected to backend."""
532
+ return self._backend.is_connected
533
+
534
+ @property
535
+ def metrics(self) -> TaskMetrics:
536
+ """Get execution metrics."""
537
+ return self._backend.metrics
538
+
539
+ # -------------------------------------------------------------------------
540
+ # Connection
541
+ # -------------------------------------------------------------------------
542
+
543
+ def connect(self, **kwargs: Any) -> "BaseDistributedOrchestrator":
544
+ """Connect to the backend."""
545
+ self._backend.connect(**kwargs)
546
+ return self
547
+
548
+ def disconnect(self) -> None:
549
+ """Disconnect from the backend."""
550
+ self._backend.disconnect()
551
+ if self._executor:
552
+ self._executor.shutdown(wait=False)
553
+ self._executor = None
554
+
555
+ def __enter__(self) -> "BaseDistributedOrchestrator":
556
+ self.connect()
557
+ return self
558
+
559
+ def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
560
+ self.disconnect()
561
+
562
+ # -------------------------------------------------------------------------
563
+ # Task Submission
564
+ # -------------------------------------------------------------------------
565
+
566
+ def submit(
567
+ self,
568
+ checkpoint: "Checkpoint",
569
+ priority: int | TaskPriority = TaskPriority.NORMAL,
570
+ timeout: float | None = None,
571
+ context: dict[str, Any] | None = None,
572
+ **kwargs: Any,
573
+ ) -> DistributedTaskProtocol["CheckpointResult"]:
574
+ """Submit a checkpoint for distributed execution.
575
+
576
+ Args:
577
+ checkpoint: Checkpoint to execute.
578
+ priority: Task priority (0-10 or TaskPriority).
579
+ timeout: Task timeout in seconds.
580
+ context: Additional context for the run.
581
+ **kwargs: Backend-specific options.
582
+
583
+ Returns:
584
+ Task handle for tracking execution.
585
+ """
586
+ if isinstance(priority, int):
587
+ priority = TaskPriority.from_int(priority)
588
+
589
+ return self._backend.submit(
590
+ checkpoint=checkpoint,
591
+ priority=priority,
592
+ timeout=timeout,
593
+ context=context,
594
+ **kwargs,
595
+ )
596
+
597
+ def submit_batch(
598
+ self,
599
+ checkpoints: list["Checkpoint"],
600
+ priority: int | TaskPriority = TaskPriority.NORMAL,
601
+ timeout: float | None = None,
602
+ context: dict[str, Any] | None = None,
603
+ **kwargs: Any,
604
+ ) -> list[DistributedTaskProtocol["CheckpointResult"]]:
605
+ """Submit multiple checkpoints for execution.
606
+
607
+ Args:
608
+ checkpoints: List of checkpoints to execute.
609
+ priority: Task priority.
610
+ timeout: Task timeout in seconds.
611
+ context: Additional context for all runs.
612
+ **kwargs: Backend-specific options.
613
+
614
+ Returns:
615
+ List of task handles.
616
+ """
617
+ if isinstance(priority, int):
618
+ priority = TaskPriority.from_int(priority)
619
+
620
+ return self._backend.submit_batch(
621
+ checkpoints=checkpoints,
622
+ priority=priority,
623
+ timeout=timeout,
624
+ context=context,
625
+ **kwargs,
626
+ )
627
+
628
+ # -------------------------------------------------------------------------
629
+ # Result Collection
630
+ # -------------------------------------------------------------------------
631
+
632
+ def gather(
633
+ self,
634
+ tasks: list[DistributedTaskProtocol["CheckpointResult"]],
635
+ timeout: float | None = None,
636
+ return_exceptions: bool = False,
637
+ ) -> list["CheckpointResult | Exception"]:
638
+ """Wait for all tasks to complete and return results.
639
+
640
+ Args:
641
+ tasks: List of tasks to wait for.
642
+ timeout: Maximum time to wait.
643
+ return_exceptions: If True, return exceptions instead of raising.
644
+
645
+ Returns:
646
+ List of results (or exceptions if return_exceptions=True).
647
+ """
648
+ results: list["CheckpointResult | Exception"] = []
649
+ deadline = time.time() + timeout if timeout else None
650
+
651
+ for task in tasks:
652
+ remaining = None
653
+ if deadline:
654
+ remaining = max(0, deadline - time.time())
655
+ if remaining == 0:
656
+ if return_exceptions:
657
+ results.append(
658
+ TaskTimeoutError("Gather timeout", task.task_id, timeout or 0)
659
+ )
660
+ continue
661
+ raise TaskTimeoutError("Gather timeout", task.task_id, timeout or 0)
662
+
663
+ try:
664
+ result = task.result(timeout=remaining)
665
+ results.append(result)
666
+ except Exception as e:
667
+ if return_exceptions:
668
+ results.append(e)
669
+ else:
670
+ raise
671
+
672
+ return results
673
+
674
+ async def gather_async(
675
+ self,
676
+ tasks: list[DistributedTaskProtocol["CheckpointResult"]],
677
+ timeout: float | None = None,
678
+ return_exceptions: bool = False,
679
+ ) -> list["CheckpointResult | Exception"]:
680
+ """Async version of gather()."""
681
+ results: list["CheckpointResult | Exception"] = []
682
+
683
+ async def get_result(
684
+ task: DistributedTaskProtocol["CheckpointResult"],
685
+ ) -> "CheckpointResult | Exception":
686
+ try:
687
+ return await task.result_async(timeout=timeout)
688
+ except Exception as e:
689
+ if return_exceptions:
690
+ return e
691
+ raise
692
+
693
+ gathered = await asyncio.gather(
694
+ *[get_result(t) for t in tasks],
695
+ return_exceptions=return_exceptions,
696
+ )
697
+ return list(gathered)
698
+
699
+ def as_completed(
700
+ self,
701
+ tasks: list[DistributedTaskProtocol["CheckpointResult"]],
702
+ timeout: float | None = None,
703
+ ) -> Iterator[DistributedTaskProtocol["CheckpointResult"]]:
704
+ """Yield tasks as they complete.
705
+
706
+ Args:
707
+ tasks: List of tasks to monitor.
708
+ timeout: Maximum time to wait for each task.
709
+
710
+ Yields:
711
+ Tasks as they complete.
712
+ """
713
+ pending = set(tasks)
714
+ deadline = time.time() + timeout if timeout else None
715
+
716
+ while pending:
717
+ completed = None
718
+ for task in pending:
719
+ if task.is_ready():
720
+ completed = task
721
+ break
722
+
723
+ if completed:
724
+ pending.remove(completed)
725
+ yield completed
726
+ else:
727
+ if deadline and time.time() > deadline:
728
+ return
729
+ time.sleep(0.05)
730
+
731
+ # -------------------------------------------------------------------------
732
+ # Cluster Management
733
+ # -------------------------------------------------------------------------
734
+
735
+ def get_cluster_state(self) -> ClusterState:
736
+ """Get current cluster state."""
737
+ return self._backend.get_cluster_state()
738
+
739
+ def get_workers(self) -> list[WorkerInfo]:
740
+ """Get list of workers."""
741
+ return self._backend.get_workers()
742
+
743
+ def scale_workers(self, count: int) -> bool:
744
+ """Scale the number of workers."""
745
+ return self._backend.scale_workers(count)
746
+
747
+ def health_check(self) -> bool:
748
+ """Check cluster health."""
749
+ return self._backend.health_check()
750
+
751
+ def wait_for_workers(
752
+ self,
753
+ min_workers: int = 1,
754
+ timeout: float = 60.0,
755
+ ) -> bool:
756
+ """Wait for minimum number of workers to be available.
757
+
758
+ Args:
759
+ min_workers: Minimum number of workers required.
760
+ timeout: Maximum time to wait.
761
+
762
+ Returns:
763
+ True if workers are available, False if timeout.
764
+ """
765
+ deadline = time.time() + timeout
766
+
767
+ while time.time() < deadline:
768
+ workers = self.get_workers()
769
+ available = len([w for w in workers if w.is_available])
770
+ if available >= min_workers:
771
+ return True
772
+ time.sleep(1.0)
773
+
774
+ return False