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,677 @@
1
+ """Backpressure strategy implementations.
2
+
3
+ This module provides various backpressure strategies:
4
+ - MemoryBasedBackpressure: Based on memory usage
5
+ - QueueDepthBackpressure: Based on queue depth
6
+ - LatencyBasedBackpressure: Based on operation latency
7
+ - TokenBucketBackpressure: Token bucket rate limiting
8
+ - AdaptiveBackpressure: Adaptive multi-factor strategy
9
+ - CompositeBackpressure: Combines multiple strategies
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import asyncio
15
+ import time
16
+ from dataclasses import dataclass, field
17
+ from datetime import datetime
18
+ from typing import TYPE_CHECKING
19
+
20
+ from truthound.stores.backpressure.base import (
21
+ BackpressureConfig,
22
+ BackpressureMetrics,
23
+ BackpressureState,
24
+ BaseBackpressure,
25
+ PressureLevel,
26
+ )
27
+
28
+ if TYPE_CHECKING:
29
+ pass
30
+
31
+
32
+ class MemoryBasedBackpressure(BaseBackpressure):
33
+ """Backpressure based on memory usage.
34
+
35
+ Monitors memory usage and applies backpressure when memory
36
+ exceeds configured thresholds.
37
+
38
+ Example:
39
+ >>> config = BackpressureConfig(memory_threshold_percent=75.0)
40
+ >>> bp = MemoryBasedBackpressure(config)
41
+ >>> bp.update_metrics(memory_percent=80.0)
42
+ >>> bp.should_pause()
43
+ True
44
+ """
45
+
46
+ def __init__(
47
+ self,
48
+ config: BackpressureConfig | None = None,
49
+ memory_provider: callable | None = None,
50
+ ) -> None:
51
+ """Initialize memory-based backpressure.
52
+
53
+ Args:
54
+ config: Backpressure configuration.
55
+ memory_provider: Optional callable that returns current memory percent.
56
+ """
57
+ super().__init__(config)
58
+ self._memory_provider = memory_provider or self._default_memory_provider
59
+
60
+ @staticmethod
61
+ def _default_memory_provider() -> float:
62
+ """Get current memory usage percentage."""
63
+ try:
64
+ import psutil
65
+
66
+ return psutil.virtual_memory().percent
67
+ except ImportError:
68
+ return 0.0
69
+
70
+ def _update_pressure_level(self) -> None:
71
+ """Update pressure level based on memory usage."""
72
+ mem = self._metrics.current_memory_percent
73
+ threshold = self._config.memory_threshold_percent
74
+
75
+ if mem >= threshold + 15:
76
+ level = PressureLevel.CRITICAL
77
+ elif mem >= threshold + 10:
78
+ level = PressureLevel.HIGH
79
+ elif mem >= threshold + 5:
80
+ level = PressureLevel.MEDIUM
81
+ elif mem >= threshold:
82
+ level = PressureLevel.LOW
83
+ else:
84
+ level = PressureLevel.NONE
85
+
86
+ self._state.update_pressure(level)
87
+ self._metrics.pressure_level = level
88
+
89
+ def should_pause(self) -> bool:
90
+ """Check if should pause based on memory."""
91
+ # Auto-update from provider
92
+ current = self._memory_provider()
93
+ self.update_metrics(memory_percent=current)
94
+
95
+ return self._state.pressure_level in (
96
+ PressureLevel.HIGH,
97
+ PressureLevel.CRITICAL,
98
+ )
99
+
100
+ def calculate_pause_duration(self) -> float:
101
+ """Calculate pause duration based on memory pressure."""
102
+ mem = self._metrics.current_memory_percent
103
+ threshold = self._config.memory_threshold_percent
104
+
105
+ if mem <= threshold:
106
+ return 0.0
107
+
108
+ # Linear scaling based on how much over threshold
109
+ excess = (mem - threshold) / (100 - threshold)
110
+ duration_ms = self._config.min_pause_ms + (
111
+ excess * (self._config.max_pause_ms - self._config.min_pause_ms)
112
+ )
113
+
114
+ return duration_ms / 1000.0
115
+
116
+ def calculate_rate(self) -> float:
117
+ """Calculate allowed rate based on memory pressure."""
118
+ mem = self._metrics.current_memory_percent
119
+ threshold = self._config.memory_threshold_percent
120
+
121
+ if mem <= threshold:
122
+ return self._config.base_rate
123
+
124
+ # Reduce rate as memory increases
125
+ excess = (mem - threshold) / (100 - threshold)
126
+ reduction = 1.0 - (excess * 0.9) # Max 90% reduction
127
+
128
+ new_rate = self._config.base_rate * reduction
129
+ return max(new_rate, self._config.min_rate)
130
+
131
+
132
+ class QueueDepthBackpressure(BaseBackpressure):
133
+ """Backpressure based on queue depth.
134
+
135
+ Monitors queue depth and applies backpressure when the queue
136
+ exceeds configured thresholds.
137
+
138
+ Example:
139
+ >>> config = BackpressureConfig(queue_depth_threshold=5000)
140
+ >>> bp = QueueDepthBackpressure(config)
141
+ >>> bp.update_metrics(queue_depth=7500)
142
+ >>> bp.calculate_rate() # Returns reduced rate
143
+ """
144
+
145
+ def __init__(
146
+ self,
147
+ config: BackpressureConfig | None = None,
148
+ queue_provider: callable | None = None,
149
+ ) -> None:
150
+ """Initialize queue-depth-based backpressure.
151
+
152
+ Args:
153
+ config: Backpressure configuration.
154
+ queue_provider: Optional callable that returns current queue depth.
155
+ """
156
+ super().__init__(config)
157
+ self._queue_provider = queue_provider
158
+
159
+ def _update_pressure_level(self) -> None:
160
+ """Update pressure level based on queue depth."""
161
+ depth = self._metrics.current_queue_depth
162
+ threshold = self._config.queue_depth_threshold
163
+
164
+ if depth >= threshold * 2:
165
+ level = PressureLevel.CRITICAL
166
+ elif depth >= threshold * 1.5:
167
+ level = PressureLevel.HIGH
168
+ elif depth >= threshold * 1.2:
169
+ level = PressureLevel.MEDIUM
170
+ elif depth >= threshold:
171
+ level = PressureLevel.LOW
172
+ else:
173
+ level = PressureLevel.NONE
174
+
175
+ self._state.update_pressure(level)
176
+ self._metrics.pressure_level = level
177
+
178
+ def should_pause(self) -> bool:
179
+ """Check if should pause based on queue depth."""
180
+ if self._queue_provider:
181
+ current = self._queue_provider()
182
+ self.update_metrics(queue_depth=current)
183
+
184
+ return self._state.pressure_level in (
185
+ PressureLevel.HIGH,
186
+ PressureLevel.CRITICAL,
187
+ )
188
+
189
+ def calculate_pause_duration(self) -> float:
190
+ """Calculate pause duration based on queue depth."""
191
+ depth = self._metrics.current_queue_depth
192
+ threshold = self._config.queue_depth_threshold
193
+
194
+ if depth <= threshold:
195
+ return 0.0
196
+
197
+ # Exponential backoff based on queue depth
198
+ excess_ratio = depth / threshold
199
+ duration_ms = self._config.min_pause_ms * (2 ** min(excess_ratio - 1, 4))
200
+
201
+ return min(duration_ms, self._config.max_pause_ms) / 1000.0
202
+
203
+ def calculate_rate(self) -> float:
204
+ """Calculate allowed rate based on queue depth."""
205
+ depth = self._metrics.current_queue_depth
206
+ threshold = self._config.queue_depth_threshold
207
+
208
+ if depth <= threshold * 0.5:
209
+ # Queue is low, can increase rate
210
+ return min(
211
+ self._config.base_rate * 1.2,
212
+ self._config.base_rate,
213
+ )
214
+ elif depth <= threshold:
215
+ return self._config.base_rate
216
+
217
+ # Reduce rate inversely proportional to queue depth
218
+ reduction = threshold / depth
219
+ new_rate = self._config.base_rate * reduction
220
+
221
+ return max(new_rate, self._config.min_rate)
222
+
223
+
224
+ class LatencyBasedBackpressure(BaseBackpressure):
225
+ """Backpressure based on operation latency.
226
+
227
+ Monitors operation latency and applies backpressure when
228
+ latency exceeds configured thresholds.
229
+
230
+ Example:
231
+ >>> config = BackpressureConfig(latency_threshold_ms=50.0)
232
+ >>> bp = LatencyBasedBackpressure(config)
233
+ >>> bp.update_metrics(latency_ms=100.0)
234
+ >>> bp.should_pause()
235
+ True
236
+ """
237
+
238
+ def __init__(self, config: BackpressureConfig | None = None) -> None:
239
+ """Initialize latency-based backpressure."""
240
+ super().__init__(config)
241
+ self._latency_window: list[float] = []
242
+ self._window_size = config.adaptive_window_size if config else 100
243
+
244
+ def record_latency(self, latency_ms: float) -> None:
245
+ """Record a latency sample."""
246
+ self._latency_window.append(latency_ms)
247
+ if len(self._latency_window) > self._window_size:
248
+ self._latency_window.pop(0)
249
+
250
+ # Use moving average for stability
251
+ avg_latency = sum(self._latency_window) / len(self._latency_window)
252
+ self.update_metrics(latency_ms=avg_latency)
253
+
254
+ def _update_pressure_level(self) -> None:
255
+ """Update pressure level based on latency."""
256
+ latency = self._metrics.current_latency_ms
257
+ threshold = self._config.latency_threshold_ms
258
+
259
+ if latency >= threshold * 4:
260
+ level = PressureLevel.CRITICAL
261
+ elif latency >= threshold * 2:
262
+ level = PressureLevel.HIGH
263
+ elif latency >= threshold * 1.5:
264
+ level = PressureLevel.MEDIUM
265
+ elif latency >= threshold:
266
+ level = PressureLevel.LOW
267
+ else:
268
+ level = PressureLevel.NONE
269
+
270
+ self._state.update_pressure(level)
271
+ self._metrics.pressure_level = level
272
+
273
+ def should_pause(self) -> bool:
274
+ """Check if should pause based on latency."""
275
+ return self._state.pressure_level in (
276
+ PressureLevel.HIGH,
277
+ PressureLevel.CRITICAL,
278
+ )
279
+
280
+ def calculate_pause_duration(self) -> float:
281
+ """Calculate pause duration based on latency."""
282
+ latency = self._metrics.current_latency_ms
283
+ threshold = self._config.latency_threshold_ms
284
+
285
+ if latency <= threshold:
286
+ return 0.0
287
+
288
+ # Pause proportional to excess latency
289
+ excess_ratio = latency / threshold
290
+ duration_ms = self._config.min_pause_ms * excess_ratio
291
+
292
+ return min(duration_ms, self._config.max_pause_ms) / 1000.0
293
+
294
+ def calculate_rate(self) -> float:
295
+ """Calculate allowed rate based on latency."""
296
+ latency = self._metrics.current_latency_ms
297
+ threshold = self._config.latency_threshold_ms
298
+
299
+ if latency <= threshold * 0.5:
300
+ # Latency is good, can try higher rate
301
+ return min(
302
+ self._state.current_rate * (1 + self._config.recovery_rate),
303
+ self._config.base_rate,
304
+ )
305
+ elif latency <= threshold:
306
+ return self._state.current_rate
307
+
308
+ # Reduce rate to bring latency down
309
+ reduction = threshold / latency
310
+ new_rate = self._state.current_rate * reduction
311
+
312
+ return max(new_rate, self._config.min_rate)
313
+
314
+
315
+ @dataclass
316
+ class TokenBucketState:
317
+ """State for token bucket rate limiter."""
318
+
319
+ tokens: float
320
+ last_refill: float = field(default_factory=time.monotonic)
321
+
322
+
323
+ class TokenBucketBackpressure(BaseBackpressure):
324
+ """Token bucket rate limiting backpressure.
325
+
326
+ Implements the token bucket algorithm for smooth rate limiting.
327
+ Tokens are added at a steady rate and consumed per operation.
328
+
329
+ Example:
330
+ >>> config = BackpressureConfig(base_rate=1000.0)
331
+ >>> bp = TokenBucketBackpressure(config)
332
+ >>> await bp.acquire() # Waits if no tokens available
333
+ """
334
+
335
+ def __init__(
336
+ self,
337
+ config: BackpressureConfig | None = None,
338
+ bucket_size: float | None = None,
339
+ ) -> None:
340
+ """Initialize token bucket backpressure.
341
+
342
+ Args:
343
+ config: Backpressure configuration.
344
+ bucket_size: Maximum tokens in bucket. Defaults to base_rate.
345
+ """
346
+ super().__init__(config)
347
+ self._bucket_size = bucket_size or self._config.base_rate
348
+ self._bucket = TokenBucketState(tokens=self._bucket_size)
349
+
350
+ def _refill_tokens(self) -> None:
351
+ """Refill tokens based on elapsed time."""
352
+ now = time.monotonic()
353
+ elapsed = now - self._bucket.last_refill
354
+ tokens_to_add = elapsed * self._state.current_rate
355
+
356
+ self._bucket.tokens = min(
357
+ self._bucket.tokens + tokens_to_add,
358
+ self._bucket_size,
359
+ )
360
+ self._bucket.last_refill = now
361
+
362
+ def _update_pressure_level(self) -> None:
363
+ """Update pressure level based on token availability."""
364
+ self._refill_tokens()
365
+ token_ratio = self._bucket.tokens / self._bucket_size
366
+
367
+ if token_ratio <= 0.1:
368
+ level = PressureLevel.CRITICAL
369
+ elif token_ratio <= 0.25:
370
+ level = PressureLevel.HIGH
371
+ elif token_ratio <= 0.5:
372
+ level = PressureLevel.MEDIUM
373
+ elif token_ratio <= 0.75:
374
+ level = PressureLevel.LOW
375
+ else:
376
+ level = PressureLevel.NONE
377
+
378
+ self._state.update_pressure(level)
379
+ self._metrics.pressure_level = level
380
+
381
+ def should_pause(self) -> bool:
382
+ """Check if should pause (no tokens available)."""
383
+ self._refill_tokens()
384
+ return self._bucket.tokens < 1.0
385
+
386
+ def calculate_pause_duration(self) -> float:
387
+ """Calculate time to wait for next token."""
388
+ if self._bucket.tokens >= 1.0:
389
+ return 0.0
390
+
391
+ # Time to get 1 token
392
+ tokens_needed = 1.0 - self._bucket.tokens
393
+ wait_time = tokens_needed / self._state.current_rate
394
+
395
+ return min(wait_time, self._config.max_pause_ms / 1000.0)
396
+
397
+ def calculate_rate(self) -> float:
398
+ """Calculate current rate (based on external factors if updated)."""
399
+ return self._state.current_rate
400
+
401
+ async def acquire(self) -> bool:
402
+ """Acquire a token, waiting if necessary."""
403
+ if not self._config.enabled:
404
+ return True
405
+
406
+ async with self._lock:
407
+ self._refill_tokens()
408
+
409
+ while self._bucket.tokens < 1.0:
410
+ wait_time = self.calculate_pause_duration()
411
+ self._metrics.record_pause(wait_time * 1000)
412
+ await asyncio.sleep(wait_time)
413
+ self._refill_tokens()
414
+
415
+ self._bucket.tokens -= 1.0
416
+ self._update_pressure_level()
417
+ return True
418
+
419
+ def try_acquire(self) -> bool:
420
+ """Try to acquire a token without waiting."""
421
+ self._refill_tokens()
422
+ if self._bucket.tokens >= 1.0:
423
+ self._bucket.tokens -= 1.0
424
+ return True
425
+ return False
426
+
427
+
428
+ class AdaptiveBackpressure(BaseBackpressure):
429
+ """Adaptive multi-factor backpressure strategy.
430
+
431
+ Combines memory, queue depth, and latency factors with
432
+ adaptive rate adjustment based on system behavior.
433
+
434
+ Example:
435
+ >>> bp = AdaptiveBackpressure()
436
+ >>> bp.update_metrics(
437
+ ... memory_percent=70.0,
438
+ ... queue_depth=5000,
439
+ ... latency_ms=80.0,
440
+ ... )
441
+ >>> rate = bp.calculate_rate()
442
+ """
443
+
444
+ def __init__(
445
+ self,
446
+ config: BackpressureConfig | None = None,
447
+ memory_weight: float = 0.4,
448
+ queue_weight: float = 0.3,
449
+ latency_weight: float = 0.3,
450
+ ) -> None:
451
+ """Initialize adaptive backpressure.
452
+
453
+ Args:
454
+ config: Backpressure configuration.
455
+ memory_weight: Weight for memory factor (0-1).
456
+ queue_weight: Weight for queue depth factor (0-1).
457
+ latency_weight: Weight for latency factor (0-1).
458
+ """
459
+ super().__init__(config)
460
+
461
+ # Normalize weights
462
+ total = memory_weight + queue_weight + latency_weight
463
+ self._memory_weight = memory_weight / total
464
+ self._queue_weight = queue_weight / total
465
+ self._latency_weight = latency_weight / total
466
+
467
+ # Track rate history for adaptation
468
+ self._rate_history: list[tuple[float, float]] = [] # (time, rate)
469
+ self._pressure_history: list[tuple[float, PressureLevel]] = []
470
+
471
+ def _calculate_pressure_score(self) -> float:
472
+ """Calculate combined pressure score (0-1)."""
473
+ memory_score = 0.0
474
+ queue_score = 0.0
475
+ latency_score = 0.0
476
+
477
+ # Memory pressure
478
+ mem = self._metrics.current_memory_percent
479
+ mem_threshold = self._config.memory_threshold_percent
480
+ if mem > mem_threshold:
481
+ memory_score = min((mem - mem_threshold) / (100 - mem_threshold), 1.0)
482
+
483
+ # Queue pressure
484
+ queue = self._metrics.current_queue_depth
485
+ queue_threshold = self._config.queue_depth_threshold
486
+ if queue > queue_threshold:
487
+ queue_score = min((queue - queue_threshold) / queue_threshold, 1.0)
488
+
489
+ # Latency pressure
490
+ latency = self._metrics.current_latency_ms
491
+ latency_threshold = self._config.latency_threshold_ms
492
+ if latency > latency_threshold:
493
+ latency_score = min(
494
+ (latency - latency_threshold) / latency_threshold, 1.0
495
+ )
496
+
497
+ # Weighted combination
498
+ return (
499
+ self._memory_weight * memory_score
500
+ + self._queue_weight * queue_score
501
+ + self._latency_weight * latency_score
502
+ )
503
+
504
+ def _update_pressure_level(self) -> None:
505
+ """Update pressure level based on combined score."""
506
+ score = self._calculate_pressure_score()
507
+
508
+ if score >= 0.8:
509
+ level = PressureLevel.CRITICAL
510
+ elif score >= 0.6:
511
+ level = PressureLevel.HIGH
512
+ elif score >= 0.4:
513
+ level = PressureLevel.MEDIUM
514
+ elif score >= 0.2:
515
+ level = PressureLevel.LOW
516
+ else:
517
+ level = PressureLevel.NONE
518
+
519
+ self._state.update_pressure(level)
520
+ self._metrics.pressure_level = level
521
+
522
+ # Track history
523
+ now = time.monotonic()
524
+ self._pressure_history.append((now, level))
525
+ if len(self._pressure_history) > self._config.adaptive_window_size:
526
+ self._pressure_history.pop(0)
527
+
528
+ def should_pause(self) -> bool:
529
+ """Check if should pause based on combined pressure."""
530
+ self._update_pressure_level()
531
+ return self._state.pressure_level in (
532
+ PressureLevel.HIGH,
533
+ PressureLevel.CRITICAL,
534
+ )
535
+
536
+ def calculate_pause_duration(self) -> float:
537
+ """Calculate adaptive pause duration."""
538
+ score = self._calculate_pressure_score()
539
+ if score <= 0.2:
540
+ return 0.0
541
+
542
+ # Base duration from score
543
+ duration_ms = self._config.min_pause_ms + (
544
+ score * (self._config.max_pause_ms - self._config.min_pause_ms)
545
+ )
546
+
547
+ # Adjust based on consecutive high pressure
548
+ if self._state.consecutive_high_pressure > 3:
549
+ duration_ms *= 1.5
550
+
551
+ return min(duration_ms, self._config.max_pause_ms) / 1000.0
552
+
553
+ def calculate_rate(self) -> float:
554
+ """Calculate adaptive rate based on system behavior."""
555
+ score = self._calculate_pressure_score()
556
+ current_rate = self._state.current_rate
557
+
558
+ if score <= 0.1 and self._state.consecutive_low_pressure > 3:
559
+ # System is healthy, gradually increase rate
560
+ new_rate = current_rate * (1 + self._config.recovery_rate)
561
+ elif score >= 0.6:
562
+ # High pressure, reduce rate significantly
563
+ reduction = 1.0 - (score * 0.8)
564
+ new_rate = current_rate * reduction
565
+ elif score >= 0.3:
566
+ # Moderate pressure, slight reduction
567
+ reduction = 1.0 - (score * 0.5)
568
+ new_rate = current_rate * reduction
569
+ else:
570
+ # Low pressure, maintain or slight increase
571
+ new_rate = current_rate * (1 + self._config.recovery_rate * 0.5)
572
+
573
+ # Clamp to bounds
574
+ new_rate = max(min(new_rate, self._config.base_rate), self._config.min_rate)
575
+
576
+ # Track history
577
+ now = time.monotonic()
578
+ self._rate_history.append((now, new_rate))
579
+ if len(self._rate_history) > self._config.adaptive_window_size:
580
+ self._rate_history.pop(0)
581
+
582
+ self._state.adjust_rate(new_rate)
583
+ return new_rate
584
+
585
+
586
+ class CompositeBackpressure(BaseBackpressure):
587
+ """Composite backpressure combining multiple strategies.
588
+
589
+ Combines multiple backpressure strategies and applies the
590
+ most restrictive policy.
591
+
592
+ Example:
593
+ >>> memory_bp = MemoryBasedBackpressure()
594
+ >>> queue_bp = QueueDepthBackpressure()
595
+ >>> composite = CompositeBackpressure([memory_bp, queue_bp])
596
+ >>> await composite.acquire()
597
+ """
598
+
599
+ def __init__(
600
+ self,
601
+ strategies: list[BaseBackpressure],
602
+ config: BackpressureConfig | None = None,
603
+ ) -> None:
604
+ """Initialize composite backpressure.
605
+
606
+ Args:
607
+ strategies: List of backpressure strategies to combine.
608
+ config: Optional override configuration.
609
+ """
610
+ super().__init__(config)
611
+ self._strategies = strategies
612
+
613
+ def _update_pressure_level(self) -> None:
614
+ """Update pressure level to highest among strategies."""
615
+ max_level = PressureLevel.NONE
616
+ level_order = [
617
+ PressureLevel.NONE,
618
+ PressureLevel.LOW,
619
+ PressureLevel.MEDIUM,
620
+ PressureLevel.HIGH,
621
+ PressureLevel.CRITICAL,
622
+ ]
623
+
624
+ for strategy in self._strategies:
625
+ strategy._update_pressure_level()
626
+ if level_order.index(strategy.state.pressure_level) > level_order.index(
627
+ max_level
628
+ ):
629
+ max_level = strategy.state.pressure_level
630
+
631
+ self._state.update_pressure(max_level)
632
+ self._metrics.pressure_level = max_level
633
+
634
+ def should_pause(self) -> bool:
635
+ """Check if any strategy says to pause."""
636
+ return any(s.should_pause() for s in self._strategies)
637
+
638
+ def calculate_pause_duration(self) -> float:
639
+ """Calculate maximum pause duration among strategies."""
640
+ durations = [s.calculate_pause_duration() for s in self._strategies]
641
+ return max(durations) if durations else 0.0
642
+
643
+ def calculate_rate(self) -> float:
644
+ """Calculate minimum rate among strategies."""
645
+ rates = [s.calculate_rate() for s in self._strategies]
646
+ return min(rates) if rates else self._config.base_rate
647
+
648
+ def update_metrics(
649
+ self,
650
+ memory_percent: float | None = None,
651
+ queue_depth: int | None = None,
652
+ latency_ms: float | None = None,
653
+ ) -> None:
654
+ """Update metrics on all strategies."""
655
+ super().update_metrics(memory_percent, queue_depth, latency_ms)
656
+ for strategy in self._strategies:
657
+ strategy.update_metrics(memory_percent, queue_depth, latency_ms)
658
+
659
+ async def acquire(self) -> bool:
660
+ """Acquire from all strategies."""
661
+ results = await asyncio.gather(
662
+ *[s.acquire() for s in self._strategies],
663
+ return_exceptions=True,
664
+ )
665
+ return all(r is True for r in results if not isinstance(r, Exception))
666
+
667
+ def release(self) -> None:
668
+ """Release on all strategies."""
669
+ super().release()
670
+ for strategy in self._strategies:
671
+ strategy.release()
672
+
673
+ def reset(self) -> None:
674
+ """Reset all strategies."""
675
+ super().reset()
676
+ for strategy in self._strategies:
677
+ strategy.reset()