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,855 @@
1
+ """i18n Protocol Definitions and Base Abstractions.
2
+
3
+ This module defines the core protocols (interfaces) for the i18n system,
4
+ enabling extensibility and loose coupling between components.
5
+
6
+ Protocols:
7
+ - PluralRuleProvider: CLDR plural rule handling
8
+ - NumberFormatter: Locale-aware number formatting
9
+ - DateFormatter: Locale-aware date/time formatting
10
+ - TextDirectionProvider: RTL/LTR text direction
11
+ - MessageResolver: Message resolution with context
12
+ - CatalogLoader: Dynamic catalog loading
13
+ - TranslationService: External TMS integration
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from abc import ABC, abstractmethod
19
+ from dataclasses import dataclass, field
20
+ from datetime import datetime, date, time
21
+ from decimal import Decimal
22
+ from enum import Enum
23
+ from typing import Any, Protocol, TypeVar, runtime_checkable
24
+
25
+
26
+ # ==============================================================================
27
+ # Enums and Type Definitions
28
+ # ==============================================================================
29
+
30
+ class PluralCategory(str, Enum):
31
+ """CLDR plural categories.
32
+
33
+ Based on Unicode CLDR plural rules:
34
+ https://cldr.unicode.org/index/cldr-spec/plural-rules
35
+ """
36
+ ZERO = "zero" # 0 items
37
+ ONE = "one" # 1 item (singular)
38
+ TWO = "two" # 2 items (dual)
39
+ FEW = "few" # Small number (e.g., 2-4 in Slavic languages)
40
+ MANY = "many" # Larger number (e.g., 5+ in Slavic languages)
41
+ OTHER = "other" # Default/fallback
42
+
43
+
44
+ class TextDirection(str, Enum):
45
+ """Text direction for layout."""
46
+ LTR = "ltr" # Left-to-right (English, Korean, etc.)
47
+ RTL = "rtl" # Right-to-left (Arabic, Hebrew, etc.)
48
+ AUTO = "auto" # Automatic detection
49
+
50
+
51
+ class NumberStyle(str, Enum):
52
+ """Number formatting style."""
53
+ DECIMAL = "decimal"
54
+ CURRENCY = "currency"
55
+ PERCENT = "percent"
56
+ SCIENTIFIC = "scientific"
57
+ COMPACT = "compact"
58
+ ORDINAL = "ordinal"
59
+
60
+
61
+ class DateStyle(str, Enum):
62
+ """Date formatting style."""
63
+ SHORT = "short" # 12/31/24
64
+ MEDIUM = "medium" # Dec 31, 2024
65
+ LONG = "long" # December 31, 2024
66
+ FULL = "full" # Tuesday, December 31, 2024
67
+ ISO = "iso" # 2024-12-31
68
+ RELATIVE = "relative" # 2 days ago
69
+
70
+
71
+ class TimeStyle(str, Enum):
72
+ """Time formatting style."""
73
+ SHORT = "short" # 3:30 PM
74
+ MEDIUM = "medium" # 3:30:00 PM
75
+ LONG = "long" # 3:30:00 PM UTC
76
+ FULL = "full" # 3:30:00 PM Coordinated Universal Time
77
+
78
+
79
+ class MessageContext(str, Enum):
80
+ """Context for message selection."""
81
+ FORMAL = "formal"
82
+ INFORMAL = "informal"
83
+ TECHNICAL = "technical"
84
+ LEGAL = "legal"
85
+ MARKETING = "marketing"
86
+
87
+
88
+ # ==============================================================================
89
+ # Data Classes
90
+ # ==============================================================================
91
+
92
+ @dataclass(frozen=True)
93
+ class LocaleInfo:
94
+ """Complete locale information.
95
+
96
+ Attributes:
97
+ language: ISO 639-1 language code (e.g., "en", "ko")
98
+ region: ISO 3166-1 region code (e.g., "US", "GB")
99
+ script: ISO 15924 script code (e.g., "Latn", "Hans")
100
+ variant: Locale variant (e.g., "formal", "informal")
101
+ """
102
+ language: str
103
+ region: str | None = None
104
+ script: str | None = None
105
+ variant: str | None = None
106
+
107
+ @property
108
+ def tag(self) -> str:
109
+ """Get BCP 47 language tag."""
110
+ parts = [self.language]
111
+ if self.script:
112
+ parts.append(self.script)
113
+ if self.region:
114
+ parts.append(self.region)
115
+ if self.variant:
116
+ parts.append(self.variant)
117
+ return "-".join(parts)
118
+
119
+ @property
120
+ def direction(self) -> TextDirection:
121
+ """Get default text direction for this locale."""
122
+ rtl_languages = {"ar", "he", "fa", "ur", "yi", "ps", "sd"}
123
+ if self.language in rtl_languages:
124
+ return TextDirection.RTL
125
+ return TextDirection.LTR
126
+
127
+ @classmethod
128
+ def parse(cls, tag: str) -> "LocaleInfo":
129
+ """Parse a locale tag.
130
+
131
+ Supports formats:
132
+ - Simple: "en", "ko"
133
+ - With region: "en-US", "ko-KR", "en_US", "ko_KR"
134
+ - With script: "zh-Hans", "zh-Hant"
135
+ - Full: "zh-Hans-CN", "sr-Latn-RS"
136
+
137
+ Args:
138
+ tag: Locale tag string
139
+
140
+ Returns:
141
+ Parsed LocaleInfo
142
+ """
143
+ # Normalize separator
144
+ parts = tag.replace("_", "-").split("-")
145
+
146
+ language = parts[0].lower()
147
+ region = None
148
+ script = None
149
+ variant = None
150
+
151
+ for part in parts[1:]:
152
+ if len(part) == 4 and part.isalpha():
153
+ # Script code (4 letters)
154
+ script = part.capitalize()
155
+ elif len(part) == 2 and part.isalpha():
156
+ # Region code (2 letters)
157
+ region = part.upper()
158
+ elif len(part) == 3 and part.isdigit():
159
+ # UN M.49 region code (3 digits)
160
+ region = part
161
+ else:
162
+ # Variant or extension
163
+ variant = part.lower()
164
+
165
+ return cls(
166
+ language=language,
167
+ region=region,
168
+ script=script,
169
+ variant=variant,
170
+ )
171
+
172
+ def matches(self, other: "LocaleInfo", strict: bool = False) -> bool:
173
+ """Check if this locale matches another.
174
+
175
+ Args:
176
+ other: Locale to compare with
177
+ strict: If True, require exact match
178
+
179
+ Returns:
180
+ True if locales match
181
+ """
182
+ if strict:
183
+ return (
184
+ self.language == other.language
185
+ and self.region == other.region
186
+ and self.script == other.script
187
+ and self.variant == other.variant
188
+ )
189
+
190
+ # Non-strict: language must match, others are optional
191
+ if self.language != other.language:
192
+ return False
193
+
194
+ if other.region and self.region != other.region:
195
+ return False
196
+
197
+ if other.script and self.script != other.script:
198
+ return False
199
+
200
+ return True
201
+
202
+
203
+ @dataclass
204
+ class FormattedNumber:
205
+ """Result of number formatting.
206
+
207
+ Attributes:
208
+ value: Original numeric value
209
+ formatted: Formatted string representation
210
+ direction: Text direction
211
+ parts: Component parts (for advanced rendering)
212
+ """
213
+ value: float | int | Decimal
214
+ formatted: str
215
+ direction: TextDirection = TextDirection.LTR
216
+ parts: dict[str, str] = field(default_factory=dict)
217
+
218
+
219
+ @dataclass
220
+ class FormattedDate:
221
+ """Result of date/time formatting.
222
+
223
+ Attributes:
224
+ value: Original datetime value
225
+ formatted: Formatted string representation
226
+ direction: Text direction
227
+ calendar: Calendar system used
228
+ """
229
+ value: datetime | date | time
230
+ formatted: str
231
+ direction: TextDirection = TextDirection.LTR
232
+ calendar: str = "gregorian"
233
+
234
+
235
+ @dataclass
236
+ class PluralizedMessage:
237
+ """Result of message pluralization.
238
+
239
+ Attributes:
240
+ message: Formatted message
241
+ count: Original count value
242
+ category: Plural category used
243
+ """
244
+ message: str
245
+ count: float | int
246
+ category: PluralCategory
247
+
248
+
249
+ @dataclass
250
+ class ResolvedMessage:
251
+ """Result of message resolution.
252
+
253
+ Attributes:
254
+ key: Original message key
255
+ message: Resolved and formatted message
256
+ locale: Locale used
257
+ context: Context used
258
+ fallback: Whether fallback was used
259
+ """
260
+ key: str
261
+ message: str
262
+ locale: LocaleInfo
263
+ context: MessageContext | None = None
264
+ fallback: bool = False
265
+
266
+
267
+ # ==============================================================================
268
+ # Protocols (Interfaces)
269
+ # ==============================================================================
270
+
271
+ @runtime_checkable
272
+ class PluralRuleProvider(Protocol):
273
+ """Protocol for plural rule handling.
274
+
275
+ Implementations should follow CLDR plural rules:
276
+ https://cldr.unicode.org/index/cldr-spec/plural-rules
277
+ """
278
+
279
+ def get_category(
280
+ self,
281
+ count: float | int,
282
+ locale: LocaleInfo,
283
+ ordinal: bool = False,
284
+ ) -> PluralCategory:
285
+ """Get the plural category for a number.
286
+
287
+ Args:
288
+ count: The number to categorize
289
+ locale: Target locale
290
+ ordinal: If True, use ordinal rules (1st, 2nd, 3rd...)
291
+
292
+ Returns:
293
+ Appropriate plural category
294
+ """
295
+ ...
296
+
297
+ def get_plural_form(
298
+ self,
299
+ count: float | int,
300
+ forms: dict[PluralCategory, str],
301
+ locale: LocaleInfo,
302
+ ) -> str:
303
+ """Select appropriate plural form.
304
+
305
+ Args:
306
+ count: The number to pluralize
307
+ forms: Dictionary of category -> message template
308
+ locale: Target locale
309
+
310
+ Returns:
311
+ Selected message template
312
+ """
313
+ ...
314
+
315
+
316
+ @runtime_checkable
317
+ class NumberFormatter(Protocol):
318
+ """Protocol for locale-aware number formatting."""
319
+
320
+ def format(
321
+ self,
322
+ value: float | int | Decimal,
323
+ locale: LocaleInfo,
324
+ style: NumberStyle = NumberStyle.DECIMAL,
325
+ **options: Any,
326
+ ) -> FormattedNumber:
327
+ """Format a number according to locale rules.
328
+
329
+ Args:
330
+ value: Number to format
331
+ locale: Target locale
332
+ style: Formatting style
333
+ **options: Additional options (currency, precision, etc.)
334
+
335
+ Returns:
336
+ Formatted number result
337
+ """
338
+ ...
339
+
340
+ def parse(
341
+ self,
342
+ text: str,
343
+ locale: LocaleInfo,
344
+ style: NumberStyle = NumberStyle.DECIMAL,
345
+ ) -> float | int | Decimal | None:
346
+ """Parse a localized number string.
347
+
348
+ Args:
349
+ text: Localized number string
350
+ locale: Source locale
351
+ style: Expected format style
352
+
353
+ Returns:
354
+ Parsed number or None if invalid
355
+ """
356
+ ...
357
+
358
+
359
+ @runtime_checkable
360
+ class DateFormatter(Protocol):
361
+ """Protocol for locale-aware date/time formatting."""
362
+
363
+ def format_date(
364
+ self,
365
+ value: datetime | date,
366
+ locale: LocaleInfo,
367
+ style: DateStyle = DateStyle.MEDIUM,
368
+ **options: Any,
369
+ ) -> FormattedDate:
370
+ """Format a date according to locale rules.
371
+
372
+ Args:
373
+ value: Date to format
374
+ locale: Target locale
375
+ style: Formatting style
376
+ **options: Additional options (timezone, calendar, etc.)
377
+
378
+ Returns:
379
+ Formatted date result
380
+ """
381
+ ...
382
+
383
+ def format_time(
384
+ self,
385
+ value: datetime | time,
386
+ locale: LocaleInfo,
387
+ style: TimeStyle = TimeStyle.MEDIUM,
388
+ **options: Any,
389
+ ) -> FormattedDate:
390
+ """Format a time according to locale rules.
391
+
392
+ Args:
393
+ value: Time to format
394
+ locale: Target locale
395
+ style: Formatting style
396
+ **options: Additional options (timezone, etc.)
397
+
398
+ Returns:
399
+ Formatted time result
400
+ """
401
+ ...
402
+
403
+ def format_datetime(
404
+ self,
405
+ value: datetime,
406
+ locale: LocaleInfo,
407
+ date_style: DateStyle = DateStyle.MEDIUM,
408
+ time_style: TimeStyle = TimeStyle.MEDIUM,
409
+ **options: Any,
410
+ ) -> FormattedDate:
411
+ """Format a datetime according to locale rules.
412
+
413
+ Args:
414
+ value: Datetime to format
415
+ locale: Target locale
416
+ date_style: Date formatting style
417
+ time_style: Time formatting style
418
+ **options: Additional options
419
+
420
+ Returns:
421
+ Formatted datetime result
422
+ """
423
+ ...
424
+
425
+ def format_relative(
426
+ self,
427
+ value: datetime | date,
428
+ reference: datetime | date | None = None,
429
+ locale: LocaleInfo | None = None,
430
+ ) -> FormattedDate:
431
+ """Format a relative date (e.g., "2 days ago").
432
+
433
+ Args:
434
+ value: Date to format
435
+ reference: Reference date (default: now)
436
+ locale: Target locale
437
+
438
+ Returns:
439
+ Formatted relative date
440
+ """
441
+ ...
442
+
443
+
444
+ @runtime_checkable
445
+ class TextDirectionProvider(Protocol):
446
+ """Protocol for text direction handling."""
447
+
448
+ def get_direction(self, locale: LocaleInfo) -> TextDirection:
449
+ """Get text direction for a locale.
450
+
451
+ Args:
452
+ locale: Target locale
453
+
454
+ Returns:
455
+ Text direction
456
+ """
457
+ ...
458
+
459
+ def wrap_bidi(
460
+ self,
461
+ text: str,
462
+ direction: TextDirection,
463
+ embed: bool = True,
464
+ ) -> str:
465
+ """Wrap text with bidirectional control characters.
466
+
467
+ Args:
468
+ text: Text to wrap
469
+ direction: Intended direction
470
+ embed: If True, use embedding; otherwise use override
471
+
472
+ Returns:
473
+ Text with bidi controls
474
+ """
475
+ ...
476
+
477
+
478
+ @runtime_checkable
479
+ class MessageResolver(Protocol):
480
+ """Protocol for context-aware message resolution."""
481
+
482
+ def resolve(
483
+ self,
484
+ key: str,
485
+ locale: LocaleInfo,
486
+ context: MessageContext | None = None,
487
+ **params: Any,
488
+ ) -> ResolvedMessage:
489
+ """Resolve a message with context.
490
+
491
+ Args:
492
+ key: Message key
493
+ locale: Target locale
494
+ context: Message context
495
+ **params: Format parameters
496
+
497
+ Returns:
498
+ Resolved message
499
+ """
500
+ ...
501
+
502
+ def resolve_plural(
503
+ self,
504
+ key: str,
505
+ count: float | int,
506
+ locale: LocaleInfo,
507
+ context: MessageContext | None = None,
508
+ **params: Any,
509
+ ) -> PluralizedMessage:
510
+ """Resolve a pluralized message.
511
+
512
+ Args:
513
+ key: Message key (base, without plural suffix)
514
+ count: Number for pluralization
515
+ locale: Target locale
516
+ context: Message context
517
+ **params: Additional format parameters
518
+
519
+ Returns:
520
+ Pluralized message
521
+ """
522
+ ...
523
+
524
+
525
+ @runtime_checkable
526
+ class CatalogLoader(Protocol):
527
+ """Protocol for dynamic message catalog loading."""
528
+
529
+ def load(
530
+ self,
531
+ locale: LocaleInfo,
532
+ namespace: str | None = None,
533
+ ) -> dict[str, str]:
534
+ """Load message catalog for a locale.
535
+
536
+ Args:
537
+ locale: Target locale
538
+ namespace: Optional namespace (e.g., "validators", "errors")
539
+
540
+ Returns:
541
+ Dictionary of message key -> template
542
+ """
543
+ ...
544
+
545
+ def is_loaded(self, locale: LocaleInfo) -> bool:
546
+ """Check if a locale catalog is loaded.
547
+
548
+ Args:
549
+ locale: Locale to check
550
+
551
+ Returns:
552
+ True if loaded
553
+ """
554
+ ...
555
+
556
+ def unload(self, locale: LocaleInfo) -> None:
557
+ """Unload a locale catalog from memory.
558
+
559
+ Args:
560
+ locale: Locale to unload
561
+ """
562
+ ...
563
+
564
+ def get_available_locales(self) -> list[LocaleInfo]:
565
+ """Get list of available locales.
566
+
567
+ Returns:
568
+ List of available LocaleInfo
569
+ """
570
+ ...
571
+
572
+
573
+ @runtime_checkable
574
+ class TranslationService(Protocol):
575
+ """Protocol for external Translation Management System (TMS) integration."""
576
+
577
+ def sync_catalog(
578
+ self,
579
+ locale: LocaleInfo,
580
+ catalog: dict[str, str],
581
+ ) -> dict[str, str]:
582
+ """Sync local catalog with TMS.
583
+
584
+ Args:
585
+ locale: Target locale
586
+ catalog: Local message catalog
587
+
588
+ Returns:
589
+ Updated catalog with TMS translations
590
+ """
591
+ ...
592
+
593
+ def push_new_keys(
594
+ self,
595
+ keys: list[str],
596
+ source_locale: LocaleInfo,
597
+ source_messages: dict[str, str],
598
+ ) -> bool:
599
+ """Push new message keys to TMS for translation.
600
+
601
+ Args:
602
+ keys: New message keys
603
+ source_locale: Source locale (usually "en")
604
+ source_messages: Source message templates
605
+
606
+ Returns:
607
+ True if successful
608
+ """
609
+ ...
610
+
611
+ def get_translation_status(
612
+ self,
613
+ locale: LocaleInfo,
614
+ ) -> dict[str, float]:
615
+ """Get translation completion status.
616
+
617
+ Args:
618
+ locale: Target locale
619
+
620
+ Returns:
621
+ Dictionary with completion percentages by namespace
622
+ """
623
+ ...
624
+
625
+
626
+ # ==============================================================================
627
+ # Abstract Base Classes
628
+ # ==============================================================================
629
+
630
+ class BasePluralRuleProvider(ABC):
631
+ """Abstract base class for plural rule providers."""
632
+
633
+ @abstractmethod
634
+ def get_category(
635
+ self,
636
+ count: float | int,
637
+ locale: LocaleInfo,
638
+ ordinal: bool = False,
639
+ ) -> PluralCategory:
640
+ """Get the plural category for a number."""
641
+ pass
642
+
643
+ def get_plural_form(
644
+ self,
645
+ count: float | int,
646
+ forms: dict[PluralCategory, str],
647
+ locale: LocaleInfo,
648
+ ) -> str:
649
+ """Select appropriate plural form."""
650
+ category = self.get_category(count, locale)
651
+
652
+ # Try exact match first
653
+ if category in forms:
654
+ return forms[category]
655
+
656
+ # Fallback to OTHER
657
+ if PluralCategory.OTHER in forms:
658
+ return forms[PluralCategory.OTHER]
659
+
660
+ # Last resort: return first available form
661
+ return next(iter(forms.values()))
662
+
663
+
664
+ class BaseNumberFormatter(ABC):
665
+ """Abstract base class for number formatters."""
666
+
667
+ @abstractmethod
668
+ def format(
669
+ self,
670
+ value: float | int | Decimal,
671
+ locale: LocaleInfo,
672
+ style: NumberStyle = NumberStyle.DECIMAL,
673
+ **options: Any,
674
+ ) -> FormattedNumber:
675
+ """Format a number according to locale rules."""
676
+ pass
677
+
678
+ def parse(
679
+ self,
680
+ text: str,
681
+ locale: LocaleInfo,
682
+ style: NumberStyle = NumberStyle.DECIMAL,
683
+ ) -> float | int | Decimal | None:
684
+ """Parse a localized number string."""
685
+ # Default implementation: try to parse after cleaning
686
+ try:
687
+ # Remove common thousands separators and normalize decimal
688
+ cleaned = text.strip()
689
+ # Basic implementation - subclasses should override
690
+ return float(cleaned.replace(",", "").replace(" ", ""))
691
+ except ValueError:
692
+ return None
693
+
694
+
695
+ class BaseDateFormatter(ABC):
696
+ """Abstract base class for date formatters."""
697
+
698
+ @abstractmethod
699
+ def format_date(
700
+ self,
701
+ value: datetime | date,
702
+ locale: LocaleInfo,
703
+ style: DateStyle = DateStyle.MEDIUM,
704
+ **options: Any,
705
+ ) -> FormattedDate:
706
+ """Format a date according to locale rules."""
707
+ pass
708
+
709
+ @abstractmethod
710
+ def format_time(
711
+ self,
712
+ value: datetime | time,
713
+ locale: LocaleInfo,
714
+ style: TimeStyle = TimeStyle.MEDIUM,
715
+ **options: Any,
716
+ ) -> FormattedDate:
717
+ """Format a time according to locale rules."""
718
+ pass
719
+
720
+ def format_datetime(
721
+ self,
722
+ value: datetime,
723
+ locale: LocaleInfo,
724
+ date_style: DateStyle = DateStyle.MEDIUM,
725
+ time_style: TimeStyle = TimeStyle.MEDIUM,
726
+ **options: Any,
727
+ ) -> FormattedDate:
728
+ """Format a datetime according to locale rules."""
729
+ date_result = self.format_date(value, locale, date_style, **options)
730
+ time_result = self.format_time(value, locale, time_style, **options)
731
+
732
+ # Combine date and time
733
+ combined = f"{date_result.formatted} {time_result.formatted}"
734
+
735
+ return FormattedDate(
736
+ value=value,
737
+ formatted=combined,
738
+ direction=date_result.direction,
739
+ calendar=date_result.calendar,
740
+ )
741
+
742
+ def format_relative(
743
+ self,
744
+ value: datetime | date,
745
+ reference: datetime | date | None = None,
746
+ locale: LocaleInfo | None = None,
747
+ ) -> FormattedDate:
748
+ """Format a relative date (e.g., "2 days ago")."""
749
+ if reference is None:
750
+ reference = datetime.now()
751
+
752
+ if isinstance(value, date) and not isinstance(value, datetime):
753
+ value = datetime.combine(value, time.min)
754
+ if isinstance(reference, date) and not isinstance(reference, datetime):
755
+ reference = datetime.combine(reference, time.min)
756
+
757
+ delta = value - reference
758
+ days = delta.days
759
+
760
+ # Basic English implementation - subclasses should override
761
+ if days == 0:
762
+ return FormattedDate(value=value, formatted="today")
763
+ elif days == 1:
764
+ return FormattedDate(value=value, formatted="tomorrow")
765
+ elif days == -1:
766
+ return FormattedDate(value=value, formatted="yesterday")
767
+ elif days > 0:
768
+ return FormattedDate(value=value, formatted=f"in {days} days")
769
+ else:
770
+ return FormattedDate(value=value, formatted=f"{-days} days ago")
771
+
772
+
773
+ class BaseCatalogLoader(ABC):
774
+ """Abstract base class for catalog loaders."""
775
+
776
+ def __init__(self) -> None:
777
+ self._loaded_catalogs: dict[str, dict[str, str]] = {}
778
+
779
+ @abstractmethod
780
+ def _do_load(
781
+ self,
782
+ locale: LocaleInfo,
783
+ namespace: str | None = None,
784
+ ) -> dict[str, str]:
785
+ """Internal load implementation."""
786
+ pass
787
+
788
+ def load(
789
+ self,
790
+ locale: LocaleInfo,
791
+ namespace: str | None = None,
792
+ ) -> dict[str, str]:
793
+ """Load message catalog for a locale."""
794
+ cache_key = f"{locale.tag}:{namespace or 'default'}"
795
+
796
+ if cache_key not in self._loaded_catalogs:
797
+ self._loaded_catalogs[cache_key] = self._do_load(locale, namespace)
798
+
799
+ return self._loaded_catalogs[cache_key]
800
+
801
+ def is_loaded(self, locale: LocaleInfo) -> bool:
802
+ """Check if a locale catalog is loaded."""
803
+ return any(
804
+ key.startswith(locale.tag)
805
+ for key in self._loaded_catalogs
806
+ )
807
+
808
+ def unload(self, locale: LocaleInfo) -> None:
809
+ """Unload a locale catalog from memory."""
810
+ keys_to_remove = [
811
+ key for key in self._loaded_catalogs
812
+ if key.startswith(locale.tag)
813
+ ]
814
+ for key in keys_to_remove:
815
+ del self._loaded_catalogs[key]
816
+
817
+ @abstractmethod
818
+ def get_available_locales(self) -> list[LocaleInfo]:
819
+ """Get list of available locales."""
820
+ pass
821
+
822
+
823
+ class BaseTranslationService(ABC):
824
+ """Abstract base class for TMS integrations."""
825
+
826
+ def __init__(self, api_key: str | None = None, project_id: str | None = None):
827
+ self.api_key = api_key
828
+ self.project_id = project_id
829
+
830
+ @abstractmethod
831
+ def sync_catalog(
832
+ self,
833
+ locale: LocaleInfo,
834
+ catalog: dict[str, str],
835
+ ) -> dict[str, str]:
836
+ """Sync local catalog with TMS."""
837
+ pass
838
+
839
+ @abstractmethod
840
+ def push_new_keys(
841
+ self,
842
+ keys: list[str],
843
+ source_locale: LocaleInfo,
844
+ source_messages: dict[str, str],
845
+ ) -> bool:
846
+ """Push new message keys to TMS for translation."""
847
+ pass
848
+
849
+ @abstractmethod
850
+ def get_translation_status(
851
+ self,
852
+ locale: LocaleInfo,
853
+ ) -> dict[str, float]:
854
+ """Get translation completion status."""
855
+ pass