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.
- truthound/__init__.py +162 -0
- truthound/adapters.py +100 -0
- truthound/api.py +365 -0
- truthound/audit/__init__.py +248 -0
- truthound/audit/core.py +967 -0
- truthound/audit/filters.py +620 -0
- truthound/audit/formatters.py +707 -0
- truthound/audit/logger.py +902 -0
- truthound/audit/middleware.py +571 -0
- truthound/audit/storage.py +1083 -0
- truthound/benchmark/__init__.py +123 -0
- truthound/benchmark/base.py +757 -0
- truthound/benchmark/comparison.py +635 -0
- truthound/benchmark/generators.py +706 -0
- truthound/benchmark/reporters.py +718 -0
- truthound/benchmark/runner.py +635 -0
- truthound/benchmark/scenarios.py +712 -0
- truthound/cache.py +252 -0
- truthound/checkpoint/__init__.py +136 -0
- truthound/checkpoint/actions/__init__.py +164 -0
- truthound/checkpoint/actions/base.py +324 -0
- truthound/checkpoint/actions/custom.py +234 -0
- truthound/checkpoint/actions/discord_notify.py +290 -0
- truthound/checkpoint/actions/email_notify.py +405 -0
- truthound/checkpoint/actions/github_action.py +406 -0
- truthound/checkpoint/actions/opsgenie.py +1499 -0
- truthound/checkpoint/actions/pagerduty.py +226 -0
- truthound/checkpoint/actions/slack_notify.py +233 -0
- truthound/checkpoint/actions/store_result.py +249 -0
- truthound/checkpoint/actions/teams_notify.py +1570 -0
- truthound/checkpoint/actions/telegram_notify.py +419 -0
- truthound/checkpoint/actions/update_docs.py +552 -0
- truthound/checkpoint/actions/webhook.py +293 -0
- truthound/checkpoint/analytics/__init__.py +147 -0
- truthound/checkpoint/analytics/aggregations/__init__.py +23 -0
- truthound/checkpoint/analytics/aggregations/rollup.py +481 -0
- truthound/checkpoint/analytics/aggregations/time_bucket.py +306 -0
- truthound/checkpoint/analytics/analyzers/__init__.py +17 -0
- truthound/checkpoint/analytics/analyzers/anomaly.py +386 -0
- truthound/checkpoint/analytics/analyzers/base.py +270 -0
- truthound/checkpoint/analytics/analyzers/forecast.py +421 -0
- truthound/checkpoint/analytics/analyzers/trend.py +314 -0
- truthound/checkpoint/analytics/models.py +292 -0
- truthound/checkpoint/analytics/protocols.py +549 -0
- truthound/checkpoint/analytics/service.py +718 -0
- truthound/checkpoint/analytics/stores/__init__.py +16 -0
- truthound/checkpoint/analytics/stores/base.py +306 -0
- truthound/checkpoint/analytics/stores/memory_store.py +353 -0
- truthound/checkpoint/analytics/stores/sqlite_store.py +557 -0
- truthound/checkpoint/analytics/stores/timescale_store.py +501 -0
- truthound/checkpoint/async_actions.py +794 -0
- truthound/checkpoint/async_base.py +708 -0
- truthound/checkpoint/async_checkpoint.py +617 -0
- truthound/checkpoint/async_runner.py +639 -0
- truthound/checkpoint/checkpoint.py +527 -0
- truthound/checkpoint/ci/__init__.py +61 -0
- truthound/checkpoint/ci/detector.py +355 -0
- truthound/checkpoint/ci/reporter.py +436 -0
- truthound/checkpoint/ci/templates.py +454 -0
- truthound/checkpoint/circuitbreaker/__init__.py +133 -0
- truthound/checkpoint/circuitbreaker/breaker.py +542 -0
- truthound/checkpoint/circuitbreaker/core.py +252 -0
- truthound/checkpoint/circuitbreaker/detection.py +459 -0
- truthound/checkpoint/circuitbreaker/middleware.py +389 -0
- truthound/checkpoint/circuitbreaker/registry.py +357 -0
- truthound/checkpoint/distributed/__init__.py +139 -0
- truthound/checkpoint/distributed/backends/__init__.py +35 -0
- truthound/checkpoint/distributed/backends/celery_backend.py +503 -0
- truthound/checkpoint/distributed/backends/kubernetes_backend.py +696 -0
- truthound/checkpoint/distributed/backends/local_backend.py +397 -0
- truthound/checkpoint/distributed/backends/ray_backend.py +625 -0
- truthound/checkpoint/distributed/base.py +774 -0
- truthound/checkpoint/distributed/orchestrator.py +765 -0
- truthound/checkpoint/distributed/protocols.py +842 -0
- truthound/checkpoint/distributed/registry.py +449 -0
- truthound/checkpoint/idempotency/__init__.py +120 -0
- truthound/checkpoint/idempotency/core.py +295 -0
- truthound/checkpoint/idempotency/fingerprint.py +454 -0
- truthound/checkpoint/idempotency/locking.py +604 -0
- truthound/checkpoint/idempotency/service.py +592 -0
- truthound/checkpoint/idempotency/stores.py +653 -0
- truthound/checkpoint/monitoring/__init__.py +134 -0
- truthound/checkpoint/monitoring/aggregators/__init__.py +15 -0
- truthound/checkpoint/monitoring/aggregators/base.py +372 -0
- truthound/checkpoint/monitoring/aggregators/realtime.py +300 -0
- truthound/checkpoint/monitoring/aggregators/window.py +493 -0
- truthound/checkpoint/monitoring/collectors/__init__.py +17 -0
- truthound/checkpoint/monitoring/collectors/base.py +257 -0
- truthound/checkpoint/monitoring/collectors/memory_collector.py +617 -0
- truthound/checkpoint/monitoring/collectors/prometheus_collector.py +451 -0
- truthound/checkpoint/monitoring/collectors/redis_collector.py +518 -0
- truthound/checkpoint/monitoring/events.py +410 -0
- truthound/checkpoint/monitoring/protocols.py +636 -0
- truthound/checkpoint/monitoring/service.py +578 -0
- truthound/checkpoint/monitoring/views/__init__.py +17 -0
- truthound/checkpoint/monitoring/views/base.py +172 -0
- truthound/checkpoint/monitoring/views/queue_view.py +220 -0
- truthound/checkpoint/monitoring/views/task_view.py +240 -0
- truthound/checkpoint/monitoring/views/worker_view.py +263 -0
- truthound/checkpoint/registry.py +337 -0
- truthound/checkpoint/runner.py +356 -0
- truthound/checkpoint/transaction/__init__.py +133 -0
- truthound/checkpoint/transaction/base.py +389 -0
- truthound/checkpoint/transaction/compensatable.py +537 -0
- truthound/checkpoint/transaction/coordinator.py +576 -0
- truthound/checkpoint/transaction/executor.py +622 -0
- truthound/checkpoint/transaction/idempotency.py +534 -0
- truthound/checkpoint/transaction/saga/__init__.py +143 -0
- truthound/checkpoint/transaction/saga/builder.py +584 -0
- truthound/checkpoint/transaction/saga/definition.py +515 -0
- truthound/checkpoint/transaction/saga/event_store.py +542 -0
- truthound/checkpoint/transaction/saga/patterns.py +833 -0
- truthound/checkpoint/transaction/saga/runner.py +718 -0
- truthound/checkpoint/transaction/saga/state_machine.py +793 -0
- truthound/checkpoint/transaction/saga/strategies.py +780 -0
- truthound/checkpoint/transaction/saga/testing.py +886 -0
- truthound/checkpoint/triggers/__init__.py +58 -0
- truthound/checkpoint/triggers/base.py +237 -0
- truthound/checkpoint/triggers/event.py +385 -0
- truthound/checkpoint/triggers/schedule.py +355 -0
- truthound/cli.py +2358 -0
- truthound/cli_modules/__init__.py +124 -0
- truthound/cli_modules/advanced/__init__.py +45 -0
- truthound/cli_modules/advanced/benchmark.py +343 -0
- truthound/cli_modules/advanced/docs.py +225 -0
- truthound/cli_modules/advanced/lineage.py +209 -0
- truthound/cli_modules/advanced/ml.py +320 -0
- truthound/cli_modules/advanced/realtime.py +196 -0
- truthound/cli_modules/checkpoint/__init__.py +46 -0
- truthound/cli_modules/checkpoint/init.py +114 -0
- truthound/cli_modules/checkpoint/list.py +71 -0
- truthound/cli_modules/checkpoint/run.py +159 -0
- truthound/cli_modules/checkpoint/validate.py +67 -0
- truthound/cli_modules/common/__init__.py +71 -0
- truthound/cli_modules/common/errors.py +414 -0
- truthound/cli_modules/common/options.py +419 -0
- truthound/cli_modules/common/output.py +507 -0
- truthound/cli_modules/common/protocol.py +552 -0
- truthound/cli_modules/core/__init__.py +48 -0
- truthound/cli_modules/core/check.py +123 -0
- truthound/cli_modules/core/compare.py +104 -0
- truthound/cli_modules/core/learn.py +57 -0
- truthound/cli_modules/core/mask.py +77 -0
- truthound/cli_modules/core/profile.py +65 -0
- truthound/cli_modules/core/scan.py +61 -0
- truthound/cli_modules/profiler/__init__.py +51 -0
- truthound/cli_modules/profiler/auto_profile.py +175 -0
- truthound/cli_modules/profiler/metadata.py +107 -0
- truthound/cli_modules/profiler/suite.py +283 -0
- truthound/cli_modules/registry.py +431 -0
- truthound/cli_modules/scaffolding/__init__.py +89 -0
- truthound/cli_modules/scaffolding/base.py +631 -0
- truthound/cli_modules/scaffolding/commands.py +545 -0
- truthound/cli_modules/scaffolding/plugins.py +1072 -0
- truthound/cli_modules/scaffolding/reporters.py +594 -0
- truthound/cli_modules/scaffolding/validators.py +1127 -0
- truthound/common/__init__.py +18 -0
- truthound/common/resilience/__init__.py +130 -0
- truthound/common/resilience/bulkhead.py +266 -0
- truthound/common/resilience/circuit_breaker.py +516 -0
- truthound/common/resilience/composite.py +332 -0
- truthound/common/resilience/config.py +292 -0
- truthound/common/resilience/protocols.py +217 -0
- truthound/common/resilience/rate_limiter.py +404 -0
- truthound/common/resilience/retry.py +341 -0
- truthound/datadocs/__init__.py +260 -0
- truthound/datadocs/base.py +571 -0
- truthound/datadocs/builder.py +761 -0
- truthound/datadocs/charts.py +764 -0
- truthound/datadocs/dashboard/__init__.py +63 -0
- truthound/datadocs/dashboard/app.py +576 -0
- truthound/datadocs/dashboard/components.py +584 -0
- truthound/datadocs/dashboard/state.py +240 -0
- truthound/datadocs/engine/__init__.py +46 -0
- truthound/datadocs/engine/context.py +376 -0
- truthound/datadocs/engine/pipeline.py +618 -0
- truthound/datadocs/engine/registry.py +469 -0
- truthound/datadocs/exporters/__init__.py +49 -0
- truthound/datadocs/exporters/base.py +198 -0
- truthound/datadocs/exporters/html.py +178 -0
- truthound/datadocs/exporters/json_exporter.py +253 -0
- truthound/datadocs/exporters/markdown.py +284 -0
- truthound/datadocs/exporters/pdf.py +392 -0
- truthound/datadocs/i18n/__init__.py +86 -0
- truthound/datadocs/i18n/catalog.py +960 -0
- truthound/datadocs/i18n/formatting.py +505 -0
- truthound/datadocs/i18n/loader.py +256 -0
- truthound/datadocs/i18n/plurals.py +378 -0
- truthound/datadocs/renderers/__init__.py +42 -0
- truthound/datadocs/renderers/base.py +401 -0
- truthound/datadocs/renderers/custom.py +342 -0
- truthound/datadocs/renderers/jinja.py +697 -0
- truthound/datadocs/sections.py +736 -0
- truthound/datadocs/styles.py +931 -0
- truthound/datadocs/themes/__init__.py +101 -0
- truthound/datadocs/themes/base.py +336 -0
- truthound/datadocs/themes/default.py +417 -0
- truthound/datadocs/themes/enterprise.py +419 -0
- truthound/datadocs/themes/loader.py +336 -0
- truthound/datadocs/themes.py +301 -0
- truthound/datadocs/transformers/__init__.py +57 -0
- truthound/datadocs/transformers/base.py +268 -0
- truthound/datadocs/transformers/enrichers.py +544 -0
- truthound/datadocs/transformers/filters.py +447 -0
- truthound/datadocs/transformers/i18n.py +468 -0
- truthound/datadocs/versioning/__init__.py +62 -0
- truthound/datadocs/versioning/diff.py +639 -0
- truthound/datadocs/versioning/storage.py +497 -0
- truthound/datadocs/versioning/version.py +358 -0
- truthound/datasources/__init__.py +223 -0
- truthound/datasources/_async_protocols.py +222 -0
- truthound/datasources/_protocols.py +159 -0
- truthound/datasources/adapters.py +428 -0
- truthound/datasources/async_base.py +599 -0
- truthound/datasources/async_factory.py +511 -0
- truthound/datasources/base.py +516 -0
- truthound/datasources/factory.py +433 -0
- truthound/datasources/nosql/__init__.py +47 -0
- truthound/datasources/nosql/base.py +487 -0
- truthound/datasources/nosql/elasticsearch.py +801 -0
- truthound/datasources/nosql/mongodb.py +636 -0
- truthound/datasources/pandas_optimized.py +582 -0
- truthound/datasources/pandas_source.py +216 -0
- truthound/datasources/polars_source.py +395 -0
- truthound/datasources/spark_source.py +479 -0
- truthound/datasources/sql/__init__.py +154 -0
- truthound/datasources/sql/base.py +710 -0
- truthound/datasources/sql/bigquery.py +410 -0
- truthound/datasources/sql/cloud_base.py +199 -0
- truthound/datasources/sql/databricks.py +471 -0
- truthound/datasources/sql/mysql.py +316 -0
- truthound/datasources/sql/oracle.py +427 -0
- truthound/datasources/sql/postgresql.py +321 -0
- truthound/datasources/sql/redshift.py +479 -0
- truthound/datasources/sql/snowflake.py +439 -0
- truthound/datasources/sql/sqlite.py +286 -0
- truthound/datasources/sql/sqlserver.py +437 -0
- truthound/datasources/streaming/__init__.py +47 -0
- truthound/datasources/streaming/base.py +350 -0
- truthound/datasources/streaming/kafka.py +670 -0
- truthound/decorators.py +98 -0
- truthound/docs/__init__.py +69 -0
- truthound/docs/extractor.py +971 -0
- truthound/docs/generator.py +601 -0
- truthound/docs/parser.py +1037 -0
- truthound/docs/renderer.py +999 -0
- truthound/drift/__init__.py +22 -0
- truthound/drift/compare.py +189 -0
- truthound/drift/detectors.py +464 -0
- truthound/drift/report.py +160 -0
- truthound/execution/__init__.py +65 -0
- truthound/execution/_protocols.py +324 -0
- truthound/execution/base.py +576 -0
- truthound/execution/distributed/__init__.py +179 -0
- truthound/execution/distributed/aggregations.py +731 -0
- truthound/execution/distributed/arrow_bridge.py +817 -0
- truthound/execution/distributed/base.py +550 -0
- truthound/execution/distributed/dask_engine.py +976 -0
- truthound/execution/distributed/mixins.py +766 -0
- truthound/execution/distributed/protocols.py +756 -0
- truthound/execution/distributed/ray_engine.py +1127 -0
- truthound/execution/distributed/registry.py +446 -0
- truthound/execution/distributed/spark_engine.py +1011 -0
- truthound/execution/distributed/validator_adapter.py +682 -0
- truthound/execution/pandas_engine.py +401 -0
- truthound/execution/polars_engine.py +497 -0
- truthound/execution/pushdown/__init__.py +230 -0
- truthound/execution/pushdown/ast.py +1550 -0
- truthound/execution/pushdown/builder.py +1550 -0
- truthound/execution/pushdown/dialects.py +1072 -0
- truthound/execution/pushdown/executor.py +829 -0
- truthound/execution/pushdown/optimizer.py +1041 -0
- truthound/execution/sql_engine.py +518 -0
- truthound/infrastructure/__init__.py +189 -0
- truthound/infrastructure/audit.py +1515 -0
- truthound/infrastructure/config.py +1133 -0
- truthound/infrastructure/encryption.py +1132 -0
- truthound/infrastructure/logging.py +1503 -0
- truthound/infrastructure/metrics.py +1220 -0
- truthound/lineage/__init__.py +89 -0
- truthound/lineage/base.py +746 -0
- truthound/lineage/impact_analysis.py +474 -0
- truthound/lineage/integrations/__init__.py +22 -0
- truthound/lineage/integrations/openlineage.py +548 -0
- truthound/lineage/tracker.py +512 -0
- truthound/lineage/visualization/__init__.py +33 -0
- truthound/lineage/visualization/protocols.py +145 -0
- truthound/lineage/visualization/renderers/__init__.py +20 -0
- truthound/lineage/visualization/renderers/cytoscape.py +329 -0
- truthound/lineage/visualization/renderers/d3.py +331 -0
- truthound/lineage/visualization/renderers/graphviz.py +276 -0
- truthound/lineage/visualization/renderers/mermaid.py +308 -0
- truthound/maskers.py +113 -0
- truthound/ml/__init__.py +124 -0
- truthound/ml/anomaly_models/__init__.py +31 -0
- truthound/ml/anomaly_models/ensemble.py +362 -0
- truthound/ml/anomaly_models/isolation_forest.py +444 -0
- truthound/ml/anomaly_models/statistical.py +392 -0
- truthound/ml/base.py +1178 -0
- truthound/ml/drift_detection/__init__.py +26 -0
- truthound/ml/drift_detection/concept.py +381 -0
- truthound/ml/drift_detection/distribution.py +361 -0
- truthound/ml/drift_detection/feature.py +442 -0
- truthound/ml/drift_detection/multivariate.py +495 -0
- truthound/ml/monitoring/__init__.py +88 -0
- truthound/ml/monitoring/alerting/__init__.py +33 -0
- truthound/ml/monitoring/alerting/handlers.py +427 -0
- truthound/ml/monitoring/alerting/rules.py +508 -0
- truthound/ml/monitoring/collectors/__init__.py +19 -0
- truthound/ml/monitoring/collectors/composite.py +105 -0
- truthound/ml/monitoring/collectors/drift.py +324 -0
- truthound/ml/monitoring/collectors/performance.py +179 -0
- truthound/ml/monitoring/collectors/quality.py +369 -0
- truthound/ml/monitoring/monitor.py +536 -0
- truthound/ml/monitoring/protocols.py +451 -0
- truthound/ml/monitoring/stores/__init__.py +15 -0
- truthound/ml/monitoring/stores/memory.py +201 -0
- truthound/ml/monitoring/stores/prometheus.py +296 -0
- truthound/ml/rule_learning/__init__.py +25 -0
- truthound/ml/rule_learning/constraint_miner.py +443 -0
- truthound/ml/rule_learning/pattern_learner.py +499 -0
- truthound/ml/rule_learning/profile_learner.py +462 -0
- truthound/multitenancy/__init__.py +326 -0
- truthound/multitenancy/core.py +852 -0
- truthound/multitenancy/integration.py +597 -0
- truthound/multitenancy/isolation.py +630 -0
- truthound/multitenancy/manager.py +770 -0
- truthound/multitenancy/middleware.py +765 -0
- truthound/multitenancy/quota.py +537 -0
- truthound/multitenancy/resolvers.py +603 -0
- truthound/multitenancy/storage.py +703 -0
- truthound/observability/__init__.py +307 -0
- truthound/observability/context.py +531 -0
- truthound/observability/instrumentation.py +611 -0
- truthound/observability/logging.py +887 -0
- truthound/observability/metrics.py +1157 -0
- truthound/observability/tracing/__init__.py +178 -0
- truthound/observability/tracing/baggage.py +310 -0
- truthound/observability/tracing/config.py +426 -0
- truthound/observability/tracing/exporter.py +787 -0
- truthound/observability/tracing/integration.py +1018 -0
- truthound/observability/tracing/otel/__init__.py +146 -0
- truthound/observability/tracing/otel/adapter.py +982 -0
- truthound/observability/tracing/otel/bridge.py +1177 -0
- truthound/observability/tracing/otel/compat.py +681 -0
- truthound/observability/tracing/otel/config.py +691 -0
- truthound/observability/tracing/otel/detection.py +327 -0
- truthound/observability/tracing/otel/protocols.py +426 -0
- truthound/observability/tracing/processor.py +561 -0
- truthound/observability/tracing/propagator.py +757 -0
- truthound/observability/tracing/provider.py +569 -0
- truthound/observability/tracing/resource.py +515 -0
- truthound/observability/tracing/sampler.py +487 -0
- truthound/observability/tracing/span.py +676 -0
- truthound/plugins/__init__.py +198 -0
- truthound/plugins/base.py +599 -0
- truthound/plugins/cli.py +680 -0
- truthound/plugins/dependencies/__init__.py +42 -0
- truthound/plugins/dependencies/graph.py +422 -0
- truthound/plugins/dependencies/resolver.py +417 -0
- truthound/plugins/discovery.py +379 -0
- truthound/plugins/docs/__init__.py +46 -0
- truthound/plugins/docs/extractor.py +444 -0
- truthound/plugins/docs/renderer.py +499 -0
- truthound/plugins/enterprise_manager.py +877 -0
- truthound/plugins/examples/__init__.py +19 -0
- truthound/plugins/examples/custom_validators.py +317 -0
- truthound/plugins/examples/slack_notifier.py +312 -0
- truthound/plugins/examples/xml_reporter.py +254 -0
- truthound/plugins/hooks.py +558 -0
- truthound/plugins/lifecycle/__init__.py +43 -0
- truthound/plugins/lifecycle/hot_reload.py +402 -0
- truthound/plugins/lifecycle/manager.py +371 -0
- truthound/plugins/manager.py +736 -0
- truthound/plugins/registry.py +338 -0
- truthound/plugins/security/__init__.py +93 -0
- truthound/plugins/security/exceptions.py +332 -0
- truthound/plugins/security/policies.py +348 -0
- truthound/plugins/security/protocols.py +643 -0
- truthound/plugins/security/sandbox/__init__.py +45 -0
- truthound/plugins/security/sandbox/context.py +158 -0
- truthound/plugins/security/sandbox/engines/__init__.py +19 -0
- truthound/plugins/security/sandbox/engines/container.py +379 -0
- truthound/plugins/security/sandbox/engines/noop.py +144 -0
- truthound/plugins/security/sandbox/engines/process.py +336 -0
- truthound/plugins/security/sandbox/factory.py +211 -0
- truthound/plugins/security/signing/__init__.py +57 -0
- truthound/plugins/security/signing/service.py +330 -0
- truthound/plugins/security/signing/trust_store.py +368 -0
- truthound/plugins/security/signing/verifier.py +459 -0
- truthound/plugins/versioning/__init__.py +41 -0
- truthound/plugins/versioning/constraints.py +297 -0
- truthound/plugins/versioning/resolver.py +329 -0
- truthound/profiler/__init__.py +1729 -0
- truthound/profiler/_lazy.py +452 -0
- truthound/profiler/ab_testing/__init__.py +80 -0
- truthound/profiler/ab_testing/analysis.py +449 -0
- truthound/profiler/ab_testing/base.py +257 -0
- truthound/profiler/ab_testing/experiment.py +395 -0
- truthound/profiler/ab_testing/tracking.py +368 -0
- truthound/profiler/auto_threshold.py +1170 -0
- truthound/profiler/base.py +579 -0
- truthound/profiler/cache_patterns.py +911 -0
- truthound/profiler/caching.py +1303 -0
- truthound/profiler/column_profiler.py +712 -0
- truthound/profiler/comparison.py +1007 -0
- truthound/profiler/custom_patterns.py +1170 -0
- truthound/profiler/dashboard/__init__.py +50 -0
- truthound/profiler/dashboard/app.py +476 -0
- truthound/profiler/dashboard/components.py +457 -0
- truthound/profiler/dashboard/config.py +72 -0
- truthound/profiler/distributed/__init__.py +83 -0
- truthound/profiler/distributed/base.py +281 -0
- truthound/profiler/distributed/dask_backend.py +498 -0
- truthound/profiler/distributed/local_backend.py +293 -0
- truthound/profiler/distributed/profiler.py +304 -0
- truthound/profiler/distributed/ray_backend.py +374 -0
- truthound/profiler/distributed/spark_backend.py +375 -0
- truthound/profiler/distributed.py +1366 -0
- truthound/profiler/enterprise_sampling.py +1065 -0
- truthound/profiler/errors.py +488 -0
- truthound/profiler/evolution/__init__.py +91 -0
- truthound/profiler/evolution/alerts.py +426 -0
- truthound/profiler/evolution/changes.py +206 -0
- truthound/profiler/evolution/compatibility.py +365 -0
- truthound/profiler/evolution/detector.py +372 -0
- truthound/profiler/evolution/protocols.py +121 -0
- truthound/profiler/generators/__init__.py +48 -0
- truthound/profiler/generators/base.py +384 -0
- truthound/profiler/generators/ml_rules.py +375 -0
- truthound/profiler/generators/pattern_rules.py +384 -0
- truthound/profiler/generators/schema_rules.py +267 -0
- truthound/profiler/generators/stats_rules.py +324 -0
- truthound/profiler/generators/suite_generator.py +857 -0
- truthound/profiler/i18n.py +1542 -0
- truthound/profiler/incremental.py +554 -0
- truthound/profiler/incremental_validation.py +1710 -0
- truthound/profiler/integration/__init__.py +73 -0
- truthound/profiler/integration/adapters.py +345 -0
- truthound/profiler/integration/context.py +371 -0
- truthound/profiler/integration/executor.py +527 -0
- truthound/profiler/integration/naming.py +75 -0
- truthound/profiler/integration/protocols.py +243 -0
- truthound/profiler/memory.py +1185 -0
- truthound/profiler/migration/__init__.py +60 -0
- truthound/profiler/migration/base.py +345 -0
- truthound/profiler/migration/manager.py +444 -0
- truthound/profiler/migration/v1_0_to_v1_1.py +484 -0
- truthound/profiler/ml/__init__.py +73 -0
- truthound/profiler/ml/base.py +244 -0
- truthound/profiler/ml/classifier.py +507 -0
- truthound/profiler/ml/feature_extraction.py +604 -0
- truthound/profiler/ml/pretrained.py +448 -0
- truthound/profiler/ml_inference.py +1276 -0
- truthound/profiler/native_patterns.py +815 -0
- truthound/profiler/observability.py +1184 -0
- truthound/profiler/process_timeout.py +1566 -0
- truthound/profiler/progress.py +568 -0
- truthound/profiler/progress_callbacks.py +1734 -0
- truthound/profiler/quality.py +1345 -0
- truthound/profiler/resilience.py +1180 -0
- truthound/profiler/sampled_matcher.py +794 -0
- truthound/profiler/sampling.py +1288 -0
- truthound/profiler/scheduling/__init__.py +82 -0
- truthound/profiler/scheduling/protocols.py +214 -0
- truthound/profiler/scheduling/scheduler.py +474 -0
- truthound/profiler/scheduling/storage.py +457 -0
- truthound/profiler/scheduling/triggers.py +449 -0
- truthound/profiler/schema.py +603 -0
- truthound/profiler/streaming.py +685 -0
- truthound/profiler/streaming_patterns.py +1354 -0
- truthound/profiler/suite_cli.py +625 -0
- truthound/profiler/suite_config.py +789 -0
- truthound/profiler/suite_export.py +1268 -0
- truthound/profiler/table_profiler.py +547 -0
- truthound/profiler/timeout.py +565 -0
- truthound/profiler/validation.py +1532 -0
- truthound/profiler/visualization/__init__.py +118 -0
- truthound/profiler/visualization/base.py +346 -0
- truthound/profiler/visualization/generator.py +1259 -0
- truthound/profiler/visualization/plotly_renderer.py +811 -0
- truthound/profiler/visualization/renderers.py +669 -0
- truthound/profiler/visualization/sections.py +540 -0
- truthound/profiler/visualization.py +2122 -0
- truthound/profiler/yaml_validation.py +1151 -0
- truthound/py.typed +0 -0
- truthound/ratelimit/__init__.py +248 -0
- truthound/ratelimit/algorithms.py +1108 -0
- truthound/ratelimit/core.py +573 -0
- truthound/ratelimit/integration.py +532 -0
- truthound/ratelimit/limiter.py +663 -0
- truthound/ratelimit/middleware.py +700 -0
- truthound/ratelimit/policy.py +792 -0
- truthound/ratelimit/storage.py +763 -0
- truthound/rbac/__init__.py +340 -0
- truthound/rbac/core.py +976 -0
- truthound/rbac/integration.py +760 -0
- truthound/rbac/manager.py +1052 -0
- truthound/rbac/middleware.py +842 -0
- truthound/rbac/policy.py +954 -0
- truthound/rbac/storage.py +878 -0
- truthound/realtime/__init__.py +141 -0
- truthound/realtime/adapters/__init__.py +43 -0
- truthound/realtime/adapters/base.py +533 -0
- truthound/realtime/adapters/kafka.py +487 -0
- truthound/realtime/adapters/kinesis.py +479 -0
- truthound/realtime/adapters/mock.py +243 -0
- truthound/realtime/base.py +553 -0
- truthound/realtime/factory.py +382 -0
- truthound/realtime/incremental.py +660 -0
- truthound/realtime/processing/__init__.py +67 -0
- truthound/realtime/processing/exactly_once.py +575 -0
- truthound/realtime/processing/state.py +547 -0
- truthound/realtime/processing/windows.py +647 -0
- truthound/realtime/protocols.py +569 -0
- truthound/realtime/streaming.py +605 -0
- truthound/realtime/testing/__init__.py +32 -0
- truthound/realtime/testing/containers.py +615 -0
- truthound/realtime/testing/fixtures.py +484 -0
- truthound/report.py +280 -0
- truthound/reporters/__init__.py +46 -0
- truthound/reporters/_protocols.py +30 -0
- truthound/reporters/base.py +324 -0
- truthound/reporters/ci/__init__.py +66 -0
- truthound/reporters/ci/azure.py +436 -0
- truthound/reporters/ci/base.py +509 -0
- truthound/reporters/ci/bitbucket.py +567 -0
- truthound/reporters/ci/circleci.py +547 -0
- truthound/reporters/ci/detection.py +364 -0
- truthound/reporters/ci/factory.py +182 -0
- truthound/reporters/ci/github.py +388 -0
- truthound/reporters/ci/gitlab.py +471 -0
- truthound/reporters/ci/jenkins.py +525 -0
- truthound/reporters/console_reporter.py +299 -0
- truthound/reporters/factory.py +211 -0
- truthound/reporters/html_reporter.py +524 -0
- truthound/reporters/json_reporter.py +256 -0
- truthound/reporters/markdown_reporter.py +280 -0
- truthound/reporters/sdk/__init__.py +174 -0
- truthound/reporters/sdk/builder.py +558 -0
- truthound/reporters/sdk/mixins.py +1150 -0
- truthound/reporters/sdk/schema.py +1493 -0
- truthound/reporters/sdk/templates.py +666 -0
- truthound/reporters/sdk/testing.py +968 -0
- truthound/scanners.py +170 -0
- truthound/scheduling/__init__.py +122 -0
- truthound/scheduling/cron.py +1136 -0
- truthound/scheduling/presets.py +212 -0
- truthound/schema.py +275 -0
- truthound/secrets/__init__.py +173 -0
- truthound/secrets/base.py +618 -0
- truthound/secrets/cloud.py +682 -0
- truthound/secrets/integration.py +507 -0
- truthound/secrets/manager.py +633 -0
- truthound/secrets/oidc/__init__.py +172 -0
- truthound/secrets/oidc/base.py +902 -0
- truthound/secrets/oidc/credential_provider.py +623 -0
- truthound/secrets/oidc/exchangers.py +1001 -0
- truthound/secrets/oidc/github/__init__.py +110 -0
- truthound/secrets/oidc/github/claims.py +718 -0
- truthound/secrets/oidc/github/enhanced_provider.py +693 -0
- truthound/secrets/oidc/github/trust_policy.py +742 -0
- truthound/secrets/oidc/github/verification.py +723 -0
- truthound/secrets/oidc/github/workflow.py +691 -0
- truthound/secrets/oidc/providers.py +825 -0
- truthound/secrets/providers.py +506 -0
- truthound/secrets/resolver.py +495 -0
- truthound/stores/__init__.py +177 -0
- truthound/stores/backends/__init__.py +18 -0
- truthound/stores/backends/_protocols.py +340 -0
- truthound/stores/backends/azure_blob.py +530 -0
- truthound/stores/backends/concurrent_filesystem.py +915 -0
- truthound/stores/backends/connection_pool.py +1365 -0
- truthound/stores/backends/database.py +743 -0
- truthound/stores/backends/filesystem.py +538 -0
- truthound/stores/backends/gcs.py +399 -0
- truthound/stores/backends/memory.py +354 -0
- truthound/stores/backends/s3.py +434 -0
- truthound/stores/backpressure/__init__.py +84 -0
- truthound/stores/backpressure/base.py +375 -0
- truthound/stores/backpressure/circuit_breaker.py +434 -0
- truthound/stores/backpressure/monitor.py +376 -0
- truthound/stores/backpressure/strategies.py +677 -0
- truthound/stores/base.py +551 -0
- truthound/stores/batching/__init__.py +65 -0
- truthound/stores/batching/base.py +305 -0
- truthound/stores/batching/buffer.py +370 -0
- truthound/stores/batching/store.py +248 -0
- truthound/stores/batching/writer.py +521 -0
- truthound/stores/caching/__init__.py +60 -0
- truthound/stores/caching/backends.py +684 -0
- truthound/stores/caching/base.py +356 -0
- truthound/stores/caching/store.py +305 -0
- truthound/stores/compression/__init__.py +193 -0
- truthound/stores/compression/adaptive.py +694 -0
- truthound/stores/compression/base.py +514 -0
- truthound/stores/compression/pipeline.py +868 -0
- truthound/stores/compression/providers.py +672 -0
- truthound/stores/compression/streaming.py +832 -0
- truthound/stores/concurrency/__init__.py +81 -0
- truthound/stores/concurrency/atomic.py +556 -0
- truthound/stores/concurrency/index.py +775 -0
- truthound/stores/concurrency/locks.py +576 -0
- truthound/stores/concurrency/manager.py +482 -0
- truthound/stores/encryption/__init__.py +297 -0
- truthound/stores/encryption/base.py +952 -0
- truthound/stores/encryption/keys.py +1191 -0
- truthound/stores/encryption/pipeline.py +903 -0
- truthound/stores/encryption/providers.py +953 -0
- truthound/stores/encryption/streaming.py +950 -0
- truthound/stores/expectations.py +227 -0
- truthound/stores/factory.py +246 -0
- truthound/stores/migration/__init__.py +75 -0
- truthound/stores/migration/base.py +480 -0
- truthound/stores/migration/manager.py +347 -0
- truthound/stores/migration/registry.py +382 -0
- truthound/stores/migration/store.py +559 -0
- truthound/stores/observability/__init__.py +106 -0
- truthound/stores/observability/audit.py +718 -0
- truthound/stores/observability/config.py +270 -0
- truthound/stores/observability/factory.py +208 -0
- truthound/stores/observability/metrics.py +636 -0
- truthound/stores/observability/protocols.py +410 -0
- truthound/stores/observability/store.py +570 -0
- truthound/stores/observability/tracing.py +784 -0
- truthound/stores/replication/__init__.py +76 -0
- truthound/stores/replication/base.py +260 -0
- truthound/stores/replication/monitor.py +269 -0
- truthound/stores/replication/store.py +439 -0
- truthound/stores/replication/syncer.py +391 -0
- truthound/stores/results.py +359 -0
- truthound/stores/retention/__init__.py +77 -0
- truthound/stores/retention/base.py +378 -0
- truthound/stores/retention/policies.py +621 -0
- truthound/stores/retention/scheduler.py +279 -0
- truthound/stores/retention/store.py +526 -0
- truthound/stores/streaming/__init__.py +138 -0
- truthound/stores/streaming/base.py +801 -0
- truthound/stores/streaming/database.py +984 -0
- truthound/stores/streaming/filesystem.py +719 -0
- truthound/stores/streaming/reader.py +629 -0
- truthound/stores/streaming/s3.py +843 -0
- truthound/stores/streaming/writer.py +790 -0
- truthound/stores/tiering/__init__.py +108 -0
- truthound/stores/tiering/base.py +462 -0
- truthound/stores/tiering/manager.py +249 -0
- truthound/stores/tiering/policies.py +692 -0
- truthound/stores/tiering/store.py +526 -0
- truthound/stores/versioning/__init__.py +56 -0
- truthound/stores/versioning/base.py +376 -0
- truthound/stores/versioning/store.py +660 -0
- truthound/stores/versioning/strategies.py +353 -0
- truthound/types.py +56 -0
- truthound/validators/__init__.py +774 -0
- truthound/validators/aggregate/__init__.py +27 -0
- truthound/validators/aggregate/central.py +116 -0
- truthound/validators/aggregate/extremes.py +116 -0
- truthound/validators/aggregate/spread.py +118 -0
- truthound/validators/aggregate/sum.py +64 -0
- truthound/validators/aggregate/type.py +78 -0
- truthound/validators/anomaly/__init__.py +93 -0
- truthound/validators/anomaly/base.py +431 -0
- truthound/validators/anomaly/ml_based.py +1190 -0
- truthound/validators/anomaly/multivariate.py +647 -0
- truthound/validators/anomaly/statistical.py +599 -0
- truthound/validators/base.py +1089 -0
- truthound/validators/business_rule/__init__.py +46 -0
- truthound/validators/business_rule/base.py +147 -0
- truthound/validators/business_rule/checksum.py +509 -0
- truthound/validators/business_rule/financial.py +526 -0
- truthound/validators/cache.py +733 -0
- truthound/validators/completeness/__init__.py +39 -0
- truthound/validators/completeness/conditional.py +73 -0
- truthound/validators/completeness/default.py +98 -0
- truthound/validators/completeness/empty.py +103 -0
- truthound/validators/completeness/nan.py +337 -0
- truthound/validators/completeness/null.py +152 -0
- truthound/validators/cross_table/__init__.py +17 -0
- truthound/validators/cross_table/aggregate.py +333 -0
- truthound/validators/cross_table/row_count.py +122 -0
- truthound/validators/datetime/__init__.py +29 -0
- truthound/validators/datetime/format.py +78 -0
- truthound/validators/datetime/freshness.py +269 -0
- truthound/validators/datetime/order.py +73 -0
- truthound/validators/datetime/parseable.py +185 -0
- truthound/validators/datetime/range.py +202 -0
- truthound/validators/datetime/timezone.py +69 -0
- truthound/validators/distribution/__init__.py +49 -0
- truthound/validators/distribution/distribution.py +128 -0
- truthound/validators/distribution/monotonic.py +119 -0
- truthound/validators/distribution/outlier.py +178 -0
- truthound/validators/distribution/quantile.py +80 -0
- truthound/validators/distribution/range.py +254 -0
- truthound/validators/distribution/set.py +125 -0
- truthound/validators/distribution/statistical.py +459 -0
- truthound/validators/drift/__init__.py +79 -0
- truthound/validators/drift/base.py +427 -0
- truthound/validators/drift/multi_feature.py +401 -0
- truthound/validators/drift/numeric.py +395 -0
- truthound/validators/drift/psi.py +446 -0
- truthound/validators/drift/statistical.py +510 -0
- truthound/validators/enterprise.py +1658 -0
- truthound/validators/geospatial/__init__.py +80 -0
- truthound/validators/geospatial/base.py +97 -0
- truthound/validators/geospatial/boundary.py +238 -0
- truthound/validators/geospatial/coordinate.py +351 -0
- truthound/validators/geospatial/distance.py +399 -0
- truthound/validators/geospatial/polygon.py +665 -0
- truthound/validators/i18n/__init__.py +308 -0
- truthound/validators/i18n/bidi.py +571 -0
- truthound/validators/i18n/catalogs.py +570 -0
- truthound/validators/i18n/dialects.py +763 -0
- truthound/validators/i18n/extended_catalogs.py +549 -0
- truthound/validators/i18n/formatting.py +1434 -0
- truthound/validators/i18n/loader.py +1020 -0
- truthound/validators/i18n/messages.py +521 -0
- truthound/validators/i18n/plural.py +683 -0
- truthound/validators/i18n/protocols.py +855 -0
- truthound/validators/i18n/tms.py +1162 -0
- truthound/validators/localization/__init__.py +53 -0
- truthound/validators/localization/base.py +122 -0
- truthound/validators/localization/chinese.py +362 -0
- truthound/validators/localization/japanese.py +275 -0
- truthound/validators/localization/korean.py +524 -0
- truthound/validators/memory/__init__.py +94 -0
- truthound/validators/memory/approximate_knn.py +506 -0
- truthound/validators/memory/base.py +547 -0
- truthound/validators/memory/sgd_online.py +719 -0
- truthound/validators/memory/streaming_ecdf.py +753 -0
- truthound/validators/ml_feature/__init__.py +54 -0
- truthound/validators/ml_feature/base.py +249 -0
- truthound/validators/ml_feature/correlation.py +299 -0
- truthound/validators/ml_feature/leakage.py +344 -0
- truthound/validators/ml_feature/null_impact.py +270 -0
- truthound/validators/ml_feature/scale.py +264 -0
- truthound/validators/multi_column/__init__.py +89 -0
- truthound/validators/multi_column/arithmetic.py +284 -0
- truthound/validators/multi_column/base.py +231 -0
- truthound/validators/multi_column/comparison.py +273 -0
- truthound/validators/multi_column/consistency.py +312 -0
- truthound/validators/multi_column/statistical.py +299 -0
- truthound/validators/optimization/__init__.py +164 -0
- truthound/validators/optimization/aggregation.py +563 -0
- truthound/validators/optimization/covariance.py +556 -0
- truthound/validators/optimization/geo.py +626 -0
- truthound/validators/optimization/graph.py +587 -0
- truthound/validators/optimization/orchestrator.py +970 -0
- truthound/validators/optimization/profiling.py +1312 -0
- truthound/validators/privacy/__init__.py +223 -0
- truthound/validators/privacy/base.py +635 -0
- truthound/validators/privacy/ccpa.py +670 -0
- truthound/validators/privacy/gdpr.py +728 -0
- truthound/validators/privacy/global_patterns.py +604 -0
- truthound/validators/privacy/plugins.py +867 -0
- truthound/validators/profiling/__init__.py +52 -0
- truthound/validators/profiling/base.py +175 -0
- truthound/validators/profiling/cardinality.py +312 -0
- truthound/validators/profiling/entropy.py +391 -0
- truthound/validators/profiling/frequency.py +455 -0
- truthound/validators/pushdown_support.py +660 -0
- truthound/validators/query/__init__.py +91 -0
- truthound/validators/query/aggregate.py +346 -0
- truthound/validators/query/base.py +246 -0
- truthound/validators/query/column.py +249 -0
- truthound/validators/query/expression.py +274 -0
- truthound/validators/query/result.py +323 -0
- truthound/validators/query/row_count.py +264 -0
- truthound/validators/referential/__init__.py +80 -0
- truthound/validators/referential/base.py +395 -0
- truthound/validators/referential/cascade.py +391 -0
- truthound/validators/referential/circular.py +563 -0
- truthound/validators/referential/foreign_key.py +624 -0
- truthound/validators/referential/orphan.py +485 -0
- truthound/validators/registry.py +112 -0
- truthound/validators/schema/__init__.py +41 -0
- truthound/validators/schema/column_count.py +142 -0
- truthound/validators/schema/column_exists.py +80 -0
- truthound/validators/schema/column_order.py +82 -0
- truthound/validators/schema/column_pair.py +85 -0
- truthound/validators/schema/column_pair_set.py +195 -0
- truthound/validators/schema/column_type.py +94 -0
- truthound/validators/schema/multi_column.py +53 -0
- truthound/validators/schema/multi_column_aggregate.py +175 -0
- truthound/validators/schema/referential.py +274 -0
- truthound/validators/schema/table_schema.py +91 -0
- truthound/validators/schema_validator.py +219 -0
- truthound/validators/sdk/__init__.py +250 -0
- truthound/validators/sdk/builder.py +680 -0
- truthound/validators/sdk/decorators.py +474 -0
- truthound/validators/sdk/enterprise/__init__.py +211 -0
- truthound/validators/sdk/enterprise/docs.py +725 -0
- truthound/validators/sdk/enterprise/fuzzing.py +659 -0
- truthound/validators/sdk/enterprise/licensing.py +709 -0
- truthound/validators/sdk/enterprise/manager.py +543 -0
- truthound/validators/sdk/enterprise/resources.py +628 -0
- truthound/validators/sdk/enterprise/sandbox.py +766 -0
- truthound/validators/sdk/enterprise/signing.py +603 -0
- truthound/validators/sdk/enterprise/templates.py +865 -0
- truthound/validators/sdk/enterprise/versioning.py +659 -0
- truthound/validators/sdk/templates.py +757 -0
- truthound/validators/sdk/testing.py +807 -0
- truthound/validators/security/__init__.py +181 -0
- truthound/validators/security/redos/__init__.py +182 -0
- truthound/validators/security/redos/core.py +861 -0
- truthound/validators/security/redos/cpu_monitor.py +593 -0
- truthound/validators/security/redos/cve_database.py +791 -0
- truthound/validators/security/redos/ml/__init__.py +155 -0
- truthound/validators/security/redos/ml/base.py +785 -0
- truthound/validators/security/redos/ml/datasets.py +618 -0
- truthound/validators/security/redos/ml/features.py +359 -0
- truthound/validators/security/redos/ml/models.py +1000 -0
- truthound/validators/security/redos/ml/predictor.py +507 -0
- truthound/validators/security/redos/ml/storage.py +632 -0
- truthound/validators/security/redos/ml/training.py +571 -0
- truthound/validators/security/redos/ml_analyzer.py +937 -0
- truthound/validators/security/redos/optimizer.py +674 -0
- truthound/validators/security/redos/profiler.py +682 -0
- truthound/validators/security/redos/re2_engine.py +709 -0
- truthound/validators/security/redos.py +886 -0
- truthound/validators/security/sql_security.py +1247 -0
- truthound/validators/streaming/__init__.py +126 -0
- truthound/validators/streaming/base.py +292 -0
- truthound/validators/streaming/completeness.py +210 -0
- truthound/validators/streaming/mixin.py +575 -0
- truthound/validators/streaming/range.py +308 -0
- truthound/validators/streaming/sources.py +846 -0
- truthound/validators/string/__init__.py +57 -0
- truthound/validators/string/casing.py +158 -0
- truthound/validators/string/charset.py +96 -0
- truthound/validators/string/format.py +501 -0
- truthound/validators/string/json.py +77 -0
- truthound/validators/string/json_schema.py +184 -0
- truthound/validators/string/length.py +104 -0
- truthound/validators/string/like_pattern.py +237 -0
- truthound/validators/string/regex.py +202 -0
- truthound/validators/string/regex_extended.py +435 -0
- truthound/validators/table/__init__.py +88 -0
- truthound/validators/table/base.py +78 -0
- truthound/validators/table/column_count.py +198 -0
- truthound/validators/table/freshness.py +362 -0
- truthound/validators/table/row_count.py +251 -0
- truthound/validators/table/schema.py +333 -0
- truthound/validators/table/size.py +285 -0
- truthound/validators/timeout/__init__.py +102 -0
- truthound/validators/timeout/advanced/__init__.py +247 -0
- truthound/validators/timeout/advanced/circuit_breaker.py +675 -0
- truthound/validators/timeout/advanced/prediction.py +773 -0
- truthound/validators/timeout/advanced/priority.py +618 -0
- truthound/validators/timeout/advanced/redis_backend.py +770 -0
- truthound/validators/timeout/advanced/retry.py +721 -0
- truthound/validators/timeout/advanced/sampling.py +788 -0
- truthound/validators/timeout/advanced/sla.py +661 -0
- truthound/validators/timeout/advanced/telemetry.py +804 -0
- truthound/validators/timeout/cascade.py +477 -0
- truthound/validators/timeout/deadline.py +657 -0
- truthound/validators/timeout/degradation.py +525 -0
- truthound/validators/timeout/distributed.py +597 -0
- truthound/validators/timeseries/__init__.py +89 -0
- truthound/validators/timeseries/base.py +326 -0
- truthound/validators/timeseries/completeness.py +617 -0
- truthound/validators/timeseries/gap.py +485 -0
- truthound/validators/timeseries/monotonic.py +310 -0
- truthound/validators/timeseries/seasonality.py +422 -0
- truthound/validators/timeseries/trend.py +510 -0
- truthound/validators/uniqueness/__init__.py +59 -0
- truthound/validators/uniqueness/approximate.py +475 -0
- truthound/validators/uniqueness/distinct_values.py +253 -0
- truthound/validators/uniqueness/duplicate.py +118 -0
- truthound/validators/uniqueness/primary_key.py +140 -0
- truthound/validators/uniqueness/unique.py +191 -0
- truthound/validators/uniqueness/within_record.py +599 -0
- truthound/validators/utils.py +756 -0
- truthound-1.0.8.dist-info/METADATA +474 -0
- truthound-1.0.8.dist-info/RECORD +877 -0
- truthound-1.0.8.dist-info/WHEEL +4 -0
- truthound-1.0.8.dist-info/entry_points.txt +2 -0
- truthound-1.0.8.dist-info/licenses/LICENSE +190 -0
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
"""Secret Reference Resolver - Template and configuration resolution.
|
|
2
|
+
|
|
3
|
+
This module provides utilities for resolving secret references in various
|
|
4
|
+
contexts: strings, configuration files, and data structures.
|
|
5
|
+
|
|
6
|
+
Supports:
|
|
7
|
+
- Template strings with ${secrets:KEY} syntax
|
|
8
|
+
- YAML/JSON config files with embedded references
|
|
9
|
+
- Environment variable expansion
|
|
10
|
+
- Default value fallbacks
|
|
11
|
+
- Nested reference resolution
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
import re
|
|
18
|
+
from dataclasses import dataclass, field
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Any, TypeVar
|
|
21
|
+
|
|
22
|
+
from truthound.secrets.base import SecretNotFoundError, SecretReference
|
|
23
|
+
from truthound.secrets.manager import SecretManager, get_secret_manager
|
|
24
|
+
|
|
25
|
+
T = TypeVar("T")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# =============================================================================
|
|
29
|
+
# Resolver Configuration
|
|
30
|
+
# =============================================================================
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass
|
|
34
|
+
class ResolverConfig:
|
|
35
|
+
"""Configuration for SecretResolver.
|
|
36
|
+
|
|
37
|
+
Attributes:
|
|
38
|
+
strict: Raise on unresolved references.
|
|
39
|
+
max_depth: Maximum nesting depth for recursive resolution.
|
|
40
|
+
preserve_unresolved: Keep ${...} format for unresolved refs.
|
|
41
|
+
resolve_env: Resolve ${env:VAR} references.
|
|
42
|
+
resolve_file: Resolve ${file:path} references.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
strict: bool = True
|
|
46
|
+
max_depth: int = 10
|
|
47
|
+
preserve_unresolved: bool = False
|
|
48
|
+
resolve_env: bool = True
|
|
49
|
+
resolve_file: bool = True
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# =============================================================================
|
|
53
|
+
# Secret Resolver
|
|
54
|
+
# =============================================================================
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class SecretResolver:
|
|
58
|
+
"""Resolves secret references in templates and configurations.
|
|
59
|
+
|
|
60
|
+
SecretResolver handles the resolution of secret references embedded in
|
|
61
|
+
strings, configuration files, and data structures.
|
|
62
|
+
|
|
63
|
+
Reference Formats:
|
|
64
|
+
- ${secrets:KEY} - Default provider
|
|
65
|
+
- ${secrets:provider/KEY} - Specific provider
|
|
66
|
+
- ${env:VAR_NAME} - Environment variable
|
|
67
|
+
- ${file:/path/to/file} - File contents
|
|
68
|
+
- ${secrets:KEY|default} - With default value
|
|
69
|
+
|
|
70
|
+
Example:
|
|
71
|
+
>>> resolver = SecretResolver()
|
|
72
|
+
>>> config = {
|
|
73
|
+
... "database": {
|
|
74
|
+
... "url": "${secrets:DATABASE_URL}",
|
|
75
|
+
... "password": "${vault:db/password}",
|
|
76
|
+
... },
|
|
77
|
+
... "api_key": "${env:API_KEY|default-key}",
|
|
78
|
+
... }
|
|
79
|
+
>>> resolved = resolver.resolve_config(config)
|
|
80
|
+
|
|
81
|
+
>>> # Template string
|
|
82
|
+
>>> template = "postgresql://${secrets:DB_USER}:${secrets:DB_PASS}@localhost/db"
|
|
83
|
+
>>> connection_string = resolver.resolve_template(template)
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
# Pattern for all supported reference formats
|
|
87
|
+
REFERENCE_PATTERN = re.compile(
|
|
88
|
+
r"\$\{(?P<type>[a-zA-Z_]+):(?P<content>[^}]+)\}"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
def __init__(
|
|
92
|
+
self,
|
|
93
|
+
manager: SecretManager | None = None,
|
|
94
|
+
config: ResolverConfig | None = None,
|
|
95
|
+
) -> None:
|
|
96
|
+
"""Initialize resolver.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
manager: SecretManager to use. Uses global if None.
|
|
100
|
+
config: Resolver configuration.
|
|
101
|
+
"""
|
|
102
|
+
self._manager = manager
|
|
103
|
+
self._config = config or ResolverConfig()
|
|
104
|
+
self._resolution_cache: dict[str, str] = {}
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def manager(self) -> SecretManager:
|
|
108
|
+
"""Get the secret manager."""
|
|
109
|
+
if self._manager is None:
|
|
110
|
+
self._manager = get_secret_manager()
|
|
111
|
+
return self._manager
|
|
112
|
+
|
|
113
|
+
def resolve_template(
|
|
114
|
+
self,
|
|
115
|
+
template: str,
|
|
116
|
+
*,
|
|
117
|
+
context: dict[str, Any] | None = None,
|
|
118
|
+
) -> str:
|
|
119
|
+
"""Resolve all references in a template string.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
template: String with ${...} references.
|
|
123
|
+
context: Additional context variables for resolution.
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
String with references resolved.
|
|
127
|
+
"""
|
|
128
|
+
if not template or "${" not in template:
|
|
129
|
+
return template
|
|
130
|
+
|
|
131
|
+
result = template
|
|
132
|
+
depth = 0
|
|
133
|
+
|
|
134
|
+
# Iterate until no more references or max depth
|
|
135
|
+
while "${" in result and depth < self._config.max_depth:
|
|
136
|
+
new_result = self._resolve_pass(result, context)
|
|
137
|
+
if new_result == result:
|
|
138
|
+
break
|
|
139
|
+
result = new_result
|
|
140
|
+
depth += 1
|
|
141
|
+
|
|
142
|
+
return result
|
|
143
|
+
|
|
144
|
+
def _resolve_pass(
|
|
145
|
+
self,
|
|
146
|
+
text: str,
|
|
147
|
+
context: dict[str, Any] | None = None,
|
|
148
|
+
) -> str:
|
|
149
|
+
"""Single pass of reference resolution."""
|
|
150
|
+
|
|
151
|
+
def replacer(match: re.Match[str]) -> str:
|
|
152
|
+
ref_type = match.group("type")
|
|
153
|
+
content = match.group("content")
|
|
154
|
+
full_ref = match.group(0)
|
|
155
|
+
|
|
156
|
+
try:
|
|
157
|
+
return self._resolve_reference(ref_type, content, context)
|
|
158
|
+
except SecretNotFoundError:
|
|
159
|
+
if self._config.preserve_unresolved:
|
|
160
|
+
return full_ref
|
|
161
|
+
if self._config.strict:
|
|
162
|
+
raise
|
|
163
|
+
return full_ref
|
|
164
|
+
|
|
165
|
+
return self.REFERENCE_PATTERN.sub(replacer, text)
|
|
166
|
+
|
|
167
|
+
def _resolve_reference(
|
|
168
|
+
self,
|
|
169
|
+
ref_type: str,
|
|
170
|
+
content: str,
|
|
171
|
+
context: dict[str, Any] | None = None,
|
|
172
|
+
) -> str:
|
|
173
|
+
"""Resolve a single reference."""
|
|
174
|
+
# Parse content for key and default
|
|
175
|
+
if "|" in content:
|
|
176
|
+
key_part, default = content.split("|", 1)
|
|
177
|
+
else:
|
|
178
|
+
key_part = content
|
|
179
|
+
default = None
|
|
180
|
+
|
|
181
|
+
# Handle different reference types
|
|
182
|
+
if ref_type == "secrets":
|
|
183
|
+
return self._resolve_secrets_ref(key_part, default)
|
|
184
|
+
|
|
185
|
+
elif ref_type == "env":
|
|
186
|
+
return self._resolve_env_ref(key_part, default)
|
|
187
|
+
|
|
188
|
+
elif ref_type == "vault":
|
|
189
|
+
return self._resolve_provider_ref("vault", key_part, default)
|
|
190
|
+
|
|
191
|
+
elif ref_type == "aws":
|
|
192
|
+
return self._resolve_provider_ref("aws", key_part, default)
|
|
193
|
+
|
|
194
|
+
elif ref_type == "azure":
|
|
195
|
+
return self._resolve_provider_ref("azure", key_part, default)
|
|
196
|
+
|
|
197
|
+
elif ref_type == "gcp":
|
|
198
|
+
return self._resolve_provider_ref("gcp", key_part, default)
|
|
199
|
+
|
|
200
|
+
elif ref_type == "file":
|
|
201
|
+
return self._resolve_file_ref(key_part, default)
|
|
202
|
+
|
|
203
|
+
elif ref_type == "ctx" and context:
|
|
204
|
+
# Context variable resolution
|
|
205
|
+
if key_part in context:
|
|
206
|
+
return str(context[key_part])
|
|
207
|
+
if default is not None:
|
|
208
|
+
return default
|
|
209
|
+
raise SecretNotFoundError(key_part, "context")
|
|
210
|
+
|
|
211
|
+
else:
|
|
212
|
+
# Unknown type, try as provider name
|
|
213
|
+
return self._resolve_provider_ref(ref_type, key_part, default)
|
|
214
|
+
|
|
215
|
+
def _resolve_secrets_ref(self, key: str, default: str | None) -> str:
|
|
216
|
+
"""Resolve ${secrets:...} reference."""
|
|
217
|
+
# Check for provider prefix (e.g., vault/key)
|
|
218
|
+
if "/" in key:
|
|
219
|
+
parts = key.split("/", 1)
|
|
220
|
+
if len(parts) == 2 and not parts[0].startswith("."):
|
|
221
|
+
provider, actual_key = parts
|
|
222
|
+
return self._resolve_provider_ref(provider, actual_key, default)
|
|
223
|
+
|
|
224
|
+
# Use default provider chain
|
|
225
|
+
secret = self.manager.get(key, default=default)
|
|
226
|
+
if secret:
|
|
227
|
+
return secret.get_value()
|
|
228
|
+
|
|
229
|
+
raise SecretNotFoundError(key, "manager")
|
|
230
|
+
|
|
231
|
+
def _resolve_env_ref(self, key: str, default: str | None) -> str:
|
|
232
|
+
"""Resolve ${env:...} reference."""
|
|
233
|
+
import os
|
|
234
|
+
|
|
235
|
+
if not self._config.resolve_env:
|
|
236
|
+
raise SecretNotFoundError(key, "env (disabled)")
|
|
237
|
+
|
|
238
|
+
value = os.environ.get(key)
|
|
239
|
+
if value is not None:
|
|
240
|
+
return value
|
|
241
|
+
|
|
242
|
+
if default is not None:
|
|
243
|
+
return default
|
|
244
|
+
|
|
245
|
+
raise SecretNotFoundError(key, "env")
|
|
246
|
+
|
|
247
|
+
def _resolve_provider_ref(
|
|
248
|
+
self,
|
|
249
|
+
provider: str,
|
|
250
|
+
key: str,
|
|
251
|
+
default: str | None,
|
|
252
|
+
) -> str:
|
|
253
|
+
"""Resolve provider-specific reference."""
|
|
254
|
+
# Handle field extraction (key#field)
|
|
255
|
+
field = None
|
|
256
|
+
if "#" in key:
|
|
257
|
+
key, field = key.split("#", 1)
|
|
258
|
+
|
|
259
|
+
secret = self.manager.get(key, provider=provider, field=field, default=default)
|
|
260
|
+
if secret:
|
|
261
|
+
return secret.get_value()
|
|
262
|
+
|
|
263
|
+
raise SecretNotFoundError(key, provider)
|
|
264
|
+
|
|
265
|
+
def _resolve_file_ref(self, path: str, default: str | None) -> str:
|
|
266
|
+
"""Resolve ${file:...} reference."""
|
|
267
|
+
if not self._config.resolve_file:
|
|
268
|
+
raise SecretNotFoundError(path, "file (disabled)")
|
|
269
|
+
|
|
270
|
+
file_path = Path(path)
|
|
271
|
+
|
|
272
|
+
if not file_path.exists():
|
|
273
|
+
if default is not None:
|
|
274
|
+
return default
|
|
275
|
+
raise SecretNotFoundError(path, "file")
|
|
276
|
+
|
|
277
|
+
try:
|
|
278
|
+
return file_path.read_text().strip()
|
|
279
|
+
except Exception as e:
|
|
280
|
+
if default is not None:
|
|
281
|
+
return default
|
|
282
|
+
raise SecretNotFoundError(path, f"file ({e})")
|
|
283
|
+
|
|
284
|
+
def resolve_config(
|
|
285
|
+
self,
|
|
286
|
+
config: dict[str, Any],
|
|
287
|
+
*,
|
|
288
|
+
context: dict[str, Any] | None = None,
|
|
289
|
+
) -> dict[str, Any]:
|
|
290
|
+
"""Resolve references in a configuration dictionary.
|
|
291
|
+
|
|
292
|
+
Args:
|
|
293
|
+
config: Configuration dictionary.
|
|
294
|
+
context: Additional context variables.
|
|
295
|
+
|
|
296
|
+
Returns:
|
|
297
|
+
Resolved configuration dictionary.
|
|
298
|
+
"""
|
|
299
|
+
return self._resolve_value(config, context, depth=0)
|
|
300
|
+
|
|
301
|
+
def _resolve_value(
|
|
302
|
+
self,
|
|
303
|
+
value: Any,
|
|
304
|
+
context: dict[str, Any] | None,
|
|
305
|
+
depth: int,
|
|
306
|
+
) -> Any:
|
|
307
|
+
"""Recursively resolve a value."""
|
|
308
|
+
if depth > self._config.max_depth:
|
|
309
|
+
return value
|
|
310
|
+
|
|
311
|
+
if isinstance(value, str):
|
|
312
|
+
return self.resolve_template(value, context=context)
|
|
313
|
+
|
|
314
|
+
elif isinstance(value, dict):
|
|
315
|
+
return {
|
|
316
|
+
k: self._resolve_value(v, context, depth + 1)
|
|
317
|
+
for k, v in value.items()
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
elif isinstance(value, list):
|
|
321
|
+
return [
|
|
322
|
+
self._resolve_value(item, context, depth + 1) for item in value
|
|
323
|
+
]
|
|
324
|
+
|
|
325
|
+
return value
|
|
326
|
+
|
|
327
|
+
def resolve_file(
|
|
328
|
+
self,
|
|
329
|
+
path: str | Path,
|
|
330
|
+
*,
|
|
331
|
+
context: dict[str, Any] | None = None,
|
|
332
|
+
) -> dict[str, Any]:
|
|
333
|
+
"""Resolve references in a configuration file.
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
path: Path to JSON or YAML configuration file.
|
|
337
|
+
context: Additional context variables.
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
Resolved configuration dictionary.
|
|
341
|
+
"""
|
|
342
|
+
path = Path(path)
|
|
343
|
+
|
|
344
|
+
if not path.exists():
|
|
345
|
+
raise FileNotFoundError(f"Configuration file not found: {path}")
|
|
346
|
+
|
|
347
|
+
content = path.read_text()
|
|
348
|
+
suffix = path.suffix.lower()
|
|
349
|
+
|
|
350
|
+
if suffix == ".json":
|
|
351
|
+
config = json.loads(content)
|
|
352
|
+
elif suffix in (".yaml", ".yml"):
|
|
353
|
+
try:
|
|
354
|
+
import yaml
|
|
355
|
+
|
|
356
|
+
config = yaml.safe_load(content)
|
|
357
|
+
except ImportError:
|
|
358
|
+
raise ImportError("PyYAML required for YAML config files")
|
|
359
|
+
else:
|
|
360
|
+
raise ValueError(f"Unsupported config format: {suffix}")
|
|
361
|
+
|
|
362
|
+
return self.resolve_config(config, context=context)
|
|
363
|
+
|
|
364
|
+
def clear_cache(self) -> None:
|
|
365
|
+
"""Clear the resolution cache."""
|
|
366
|
+
self._resolution_cache.clear()
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
# =============================================================================
|
|
370
|
+
# Convenience Functions
|
|
371
|
+
# =============================================================================
|
|
372
|
+
|
|
373
|
+
_global_resolver: SecretResolver | None = None
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def get_resolver() -> SecretResolver:
|
|
377
|
+
"""Get the global secret resolver.
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
Global SecretResolver instance.
|
|
381
|
+
"""
|
|
382
|
+
global _global_resolver
|
|
383
|
+
if _global_resolver is None:
|
|
384
|
+
_global_resolver = SecretResolver()
|
|
385
|
+
return _global_resolver
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def set_resolver(resolver: SecretResolver) -> None:
|
|
389
|
+
"""Set the global secret resolver.
|
|
390
|
+
|
|
391
|
+
Args:
|
|
392
|
+
resolver: SecretResolver to use globally.
|
|
393
|
+
"""
|
|
394
|
+
global _global_resolver
|
|
395
|
+
_global_resolver = resolver
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def resolve_template(
|
|
399
|
+
template: str,
|
|
400
|
+
*,
|
|
401
|
+
context: dict[str, Any] | None = None,
|
|
402
|
+
) -> str:
|
|
403
|
+
"""Resolve references in a template string.
|
|
404
|
+
|
|
405
|
+
Uses the global resolver.
|
|
406
|
+
|
|
407
|
+
Args:
|
|
408
|
+
template: Template string with ${...} references.
|
|
409
|
+
context: Additional context variables.
|
|
410
|
+
|
|
411
|
+
Returns:
|
|
412
|
+
Resolved string.
|
|
413
|
+
"""
|
|
414
|
+
return get_resolver().resolve_template(template, context=context)
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def resolve_config(
|
|
418
|
+
config: dict[str, Any],
|
|
419
|
+
*,
|
|
420
|
+
context: dict[str, Any] | None = None,
|
|
421
|
+
) -> dict[str, Any]:
|
|
422
|
+
"""Resolve references in a configuration dictionary.
|
|
423
|
+
|
|
424
|
+
Uses the global resolver.
|
|
425
|
+
|
|
426
|
+
Args:
|
|
427
|
+
config: Configuration dictionary.
|
|
428
|
+
context: Additional context variables.
|
|
429
|
+
|
|
430
|
+
Returns:
|
|
431
|
+
Resolved configuration.
|
|
432
|
+
"""
|
|
433
|
+
return get_resolver().resolve_config(config, context=context)
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
def resolve_file(
|
|
437
|
+
path: str | Path,
|
|
438
|
+
*,
|
|
439
|
+
context: dict[str, Any] | None = None,
|
|
440
|
+
) -> dict[str, Any]:
|
|
441
|
+
"""Resolve references in a configuration file.
|
|
442
|
+
|
|
443
|
+
Uses the global resolver.
|
|
444
|
+
|
|
445
|
+
Args:
|
|
446
|
+
path: Path to configuration file.
|
|
447
|
+
context: Additional context variables.
|
|
448
|
+
|
|
449
|
+
Returns:
|
|
450
|
+
Resolved configuration.
|
|
451
|
+
"""
|
|
452
|
+
return get_resolver().resolve_file(path, context=context)
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
# =============================================================================
|
|
456
|
+
# Decorator for Configuration Classes
|
|
457
|
+
# =============================================================================
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def with_secrets(cls: type[T]) -> type[T]:
|
|
461
|
+
"""Decorator to resolve secrets in dataclass fields.
|
|
462
|
+
|
|
463
|
+
Automatically resolves ${...} references in string fields
|
|
464
|
+
when the dataclass is initialized.
|
|
465
|
+
|
|
466
|
+
Example:
|
|
467
|
+
>>> @with_secrets
|
|
468
|
+
... @dataclass
|
|
469
|
+
... class DatabaseConfig:
|
|
470
|
+
... host: str
|
|
471
|
+
... password: str = "${secrets:DB_PASSWORD}"
|
|
472
|
+
...
|
|
473
|
+
>>> config = DatabaseConfig(host="localhost")
|
|
474
|
+
>>> # config.password is now the actual secret value
|
|
475
|
+
"""
|
|
476
|
+
original_init = cls.__init__
|
|
477
|
+
|
|
478
|
+
def new_init(self: Any, *args: Any, **kwargs: Any) -> None:
|
|
479
|
+
original_init(self, *args, **kwargs)
|
|
480
|
+
resolver = get_resolver()
|
|
481
|
+
|
|
482
|
+
for attr_name in dir(self):
|
|
483
|
+
if attr_name.startswith("_"):
|
|
484
|
+
continue
|
|
485
|
+
|
|
486
|
+
value = getattr(self, attr_name)
|
|
487
|
+
if isinstance(value, str) and "${" in value:
|
|
488
|
+
try:
|
|
489
|
+
resolved = resolver.resolve_template(value)
|
|
490
|
+
object.__setattr__(self, attr_name, resolved)
|
|
491
|
+
except SecretNotFoundError:
|
|
492
|
+
pass # Keep original value if resolution fails
|
|
493
|
+
|
|
494
|
+
cls.__init__ = new_init
|
|
495
|
+
return cls
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"""Stores module for persisting validation results and expectations.
|
|
2
|
+
|
|
3
|
+
This module provides a unified interface for storing and retrieving validation
|
|
4
|
+
results across different backends (filesystem, S3, GCS, databases).
|
|
5
|
+
|
|
6
|
+
Example:
|
|
7
|
+
>>> from truthound.stores import get_store, ValidationResult
|
|
8
|
+
>>>
|
|
9
|
+
>>> # Use filesystem store (default)
|
|
10
|
+
>>> store = get_store("filesystem", base_path=".truthound/results")
|
|
11
|
+
>>>
|
|
12
|
+
>>> # Save validation result
|
|
13
|
+
>>> result = ValidationResult.from_report(report, data_asset="customers.csv")
|
|
14
|
+
>>> run_id = store.save(result)
|
|
15
|
+
>>>
|
|
16
|
+
>>> # Retrieve result
|
|
17
|
+
>>> result = store.get(run_id)
|
|
18
|
+
>>>
|
|
19
|
+
>>> # List all results for a data asset
|
|
20
|
+
>>> run_ids = store.list_runs("customers.csv")
|
|
21
|
+
|
|
22
|
+
Concurrent Access:
|
|
23
|
+
For multi-threaded or multi-process access, use ConcurrentFileSystemStore:
|
|
24
|
+
|
|
25
|
+
>>> from truthound.stores.backends.concurrent_filesystem import (
|
|
26
|
+
... ConcurrentFileSystemStore,
|
|
27
|
+
... ConcurrencyConfig,
|
|
28
|
+
... )
|
|
29
|
+
>>>
|
|
30
|
+
>>> store = ConcurrentFileSystemStore(
|
|
31
|
+
... base_path=".truthound/results",
|
|
32
|
+
... concurrency=ConcurrencyConfig(lock_strategy="auto"),
|
|
33
|
+
... )
|
|
34
|
+
|
|
35
|
+
Enterprise Database Pooling:
|
|
36
|
+
For enterprise-grade database connection pooling with circuit breaker,
|
|
37
|
+
retry logic, and health monitoring:
|
|
38
|
+
|
|
39
|
+
>>> from truthound.stores.backends.database import DatabaseStore, PoolingConfig
|
|
40
|
+
>>>
|
|
41
|
+
>>> store = DatabaseStore(
|
|
42
|
+
... connection_url="postgresql://user:pass@localhost/db",
|
|
43
|
+
... pooling=PoolingConfig(
|
|
44
|
+
... pool_size=10,
|
|
45
|
+
... max_overflow=20,
|
|
46
|
+
... enable_circuit_breaker=True,
|
|
47
|
+
... enable_health_checks=True,
|
|
48
|
+
... ),
|
|
49
|
+
... )
|
|
50
|
+
>>>
|
|
51
|
+
>>> # Access pool metrics
|
|
52
|
+
>>> print(store.pool_metrics.to_dict())
|
|
53
|
+
>>> print(store.get_pool_status())
|
|
54
|
+
|
|
55
|
+
Streaming Storage:
|
|
56
|
+
For large-scale validation results that cannot fit in memory, use
|
|
57
|
+
streaming stores:
|
|
58
|
+
|
|
59
|
+
>>> from truthound.stores.streaming import StreamingFileSystemStore
|
|
60
|
+
>>>
|
|
61
|
+
>>> store = StreamingFileSystemStore(base_path=".truthound/streaming")
|
|
62
|
+
>>>
|
|
63
|
+
>>> # Create a streaming session
|
|
64
|
+
>>> session = store.create_session("run_001", "large_dataset.csv")
|
|
65
|
+
>>>
|
|
66
|
+
>>> # Write results incrementally
|
|
67
|
+
>>> with store.create_writer(session) as writer:
|
|
68
|
+
... for result in validation_results:
|
|
69
|
+
... writer.write_result(result)
|
|
70
|
+
>>>
|
|
71
|
+
>>> # Read results back efficiently
|
|
72
|
+
>>> for result in store.iter_results("run_001"):
|
|
73
|
+
... process(result)
|
|
74
|
+
|
|
75
|
+
Encryption:
|
|
76
|
+
For encrypting sensitive validation results:
|
|
77
|
+
|
|
78
|
+
>>> from truthound.stores.encryption import (
|
|
79
|
+
... get_encryptor,
|
|
80
|
+
... generate_key,
|
|
81
|
+
... EncryptionAlgorithm,
|
|
82
|
+
... create_secure_pipeline,
|
|
83
|
+
... )
|
|
84
|
+
>>>
|
|
85
|
+
>>> # Generate a key and encrypt data
|
|
86
|
+
>>> key = generate_key(EncryptionAlgorithm.AES_256_GCM)
|
|
87
|
+
>>> encryptor = get_encryptor("aes-256-gcm")
|
|
88
|
+
>>> encrypted = encryptor.encrypt(sensitive_data, key)
|
|
89
|
+
>>>
|
|
90
|
+
>>> # Or use a pipeline for compress-then-encrypt
|
|
91
|
+
>>> pipeline = create_secure_pipeline(key, compression="gzip")
|
|
92
|
+
>>> result = pipeline.process(data)
|
|
93
|
+
>>> original = pipeline.reverse(result.data, result.header)
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
from truthound.stores.base import (
|
|
97
|
+
BaseStore,
|
|
98
|
+
StoreConfig,
|
|
99
|
+
StoreQuery,
|
|
100
|
+
StoreError,
|
|
101
|
+
StoreNotFoundError,
|
|
102
|
+
StoreConnectionError,
|
|
103
|
+
)
|
|
104
|
+
from truthound.stores.results import (
|
|
105
|
+
ValidationResult,
|
|
106
|
+
ValidatorResult,
|
|
107
|
+
ResultStatistics,
|
|
108
|
+
ResultStatus,
|
|
109
|
+
)
|
|
110
|
+
from truthound.stores.expectations import (
|
|
111
|
+
Expectation,
|
|
112
|
+
ExpectationSuite,
|
|
113
|
+
)
|
|
114
|
+
from truthound.stores.factory import get_store, register_store
|
|
115
|
+
|
|
116
|
+
# Lazy import for submodules
|
|
117
|
+
_SUBMODULES = {
|
|
118
|
+
"streaming",
|
|
119
|
+
"encryption",
|
|
120
|
+
"compression",
|
|
121
|
+
"versioning",
|
|
122
|
+
"caching",
|
|
123
|
+
"tiering",
|
|
124
|
+
"backpressure",
|
|
125
|
+
"batching",
|
|
126
|
+
"retention",
|
|
127
|
+
"replication",
|
|
128
|
+
"migration",
|
|
129
|
+
"observability",
|
|
130
|
+
"concurrency",
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def __getattr__(name: str):
|
|
135
|
+
"""Lazy import submodules."""
|
|
136
|
+
if name in _SUBMODULES:
|
|
137
|
+
import importlib
|
|
138
|
+
module = importlib.import_module(f"truthound.stores.{name}")
|
|
139
|
+
globals()[name] = module
|
|
140
|
+
return module
|
|
141
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
__all__ = [
|
|
145
|
+
# Base classes
|
|
146
|
+
"BaseStore",
|
|
147
|
+
"StoreConfig",
|
|
148
|
+
"StoreQuery",
|
|
149
|
+
"StoreError",
|
|
150
|
+
"StoreNotFoundError",
|
|
151
|
+
"StoreConnectionError",
|
|
152
|
+
# Result types
|
|
153
|
+
"ValidationResult",
|
|
154
|
+
"ValidatorResult",
|
|
155
|
+
"ResultStatistics",
|
|
156
|
+
"ResultStatus",
|
|
157
|
+
# Expectation types
|
|
158
|
+
"Expectation",
|
|
159
|
+
"ExpectationSuite",
|
|
160
|
+
# Factory functions
|
|
161
|
+
"get_store",
|
|
162
|
+
"register_store",
|
|
163
|
+
# Submodules (lazy loaded)
|
|
164
|
+
"streaming",
|
|
165
|
+
"encryption",
|
|
166
|
+
"compression",
|
|
167
|
+
"versioning",
|
|
168
|
+
"caching",
|
|
169
|
+
"tiering",
|
|
170
|
+
"backpressure",
|
|
171
|
+
"batching",
|
|
172
|
+
"retention",
|
|
173
|
+
"replication",
|
|
174
|
+
"migration",
|
|
175
|
+
"observability",
|
|
176
|
+
"concurrency",
|
|
177
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Store backends for different storage systems.
|
|
2
|
+
|
|
3
|
+
This package contains implementations for various storage backends:
|
|
4
|
+
|
|
5
|
+
- filesystem: Local filesystem storage (default, no dependencies)
|
|
6
|
+
- memory: In-memory storage (for testing, no dependencies)
|
|
7
|
+
- s3: AWS S3 storage (requires boto3)
|
|
8
|
+
- gcs: Google Cloud Storage (requires google-cloud-storage)
|
|
9
|
+
- database: SQL database storage (requires sqlalchemy)
|
|
10
|
+
|
|
11
|
+
Use the get_store() factory function to create store instances:
|
|
12
|
+
|
|
13
|
+
>>> from truthound.stores import get_store
|
|
14
|
+
>>> store = get_store("filesystem", base_path=".truthound/results")
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
# Backends are imported lazily by the factory to avoid import errors
|
|
18
|
+
# when optional dependencies are not installed.
|