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,599 @@
|
|
|
1
|
+
"""Async base classes for data sources.
|
|
2
|
+
|
|
3
|
+
This module provides the abstract base classes for async data source
|
|
4
|
+
implementations, including connection pooling and async context management.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
from abc import ABC, abstractmethod
|
|
11
|
+
from contextlib import asynccontextmanager
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar
|
|
14
|
+
|
|
15
|
+
from truthound.datasources._protocols import (
|
|
16
|
+
ColumnType,
|
|
17
|
+
DataSourceCapability,
|
|
18
|
+
)
|
|
19
|
+
from truthound.datasources.base import (
|
|
20
|
+
DataSourceConfig,
|
|
21
|
+
DataSourceConnectionError,
|
|
22
|
+
DataSourceError,
|
|
23
|
+
polars_to_column_type,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
import polars as pl
|
|
28
|
+
|
|
29
|
+
from truthound.execution.base import BaseExecutionEngine
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# =============================================================================
|
|
33
|
+
# Exceptions
|
|
34
|
+
# =============================================================================
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class AsyncDataSourceError(DataSourceError):
|
|
38
|
+
"""Base exception for async data source errors."""
|
|
39
|
+
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class AsyncConnectionPoolError(AsyncDataSourceError):
|
|
44
|
+
"""Error related to connection pool operations."""
|
|
45
|
+
|
|
46
|
+
def __init__(self, message: str, pool_size: int | None = None) -> None:
|
|
47
|
+
self.pool_size = pool_size
|
|
48
|
+
super().__init__(message)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class AsyncTimeoutError(AsyncDataSourceError):
|
|
52
|
+
"""Timeout during async operation."""
|
|
53
|
+
|
|
54
|
+
def __init__(self, operation: str, timeout: float) -> None:
|
|
55
|
+
self.operation = operation
|
|
56
|
+
self.timeout = timeout
|
|
57
|
+
super().__init__(f"Timeout after {timeout}s during {operation}")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# =============================================================================
|
|
61
|
+
# Configuration
|
|
62
|
+
# =============================================================================
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass
|
|
66
|
+
class AsyncDataSourceConfig(DataSourceConfig):
|
|
67
|
+
"""Configuration for async data sources.
|
|
68
|
+
|
|
69
|
+
Extends base DataSourceConfig with async-specific settings.
|
|
70
|
+
|
|
71
|
+
Attributes:
|
|
72
|
+
max_concurrent_requests: Maximum number of concurrent requests.
|
|
73
|
+
connection_timeout: Timeout for establishing connections (seconds).
|
|
74
|
+
query_timeout: Timeout for query operations (seconds).
|
|
75
|
+
pool_size: Number of connections in the pool.
|
|
76
|
+
retry_attempts: Number of retry attempts for failed operations.
|
|
77
|
+
retry_delay: Initial delay between retries (seconds).
|
|
78
|
+
retry_backoff: Backoff multiplier for retry delays.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
max_concurrent_requests: int = 10
|
|
82
|
+
connection_timeout: float = 30.0
|
|
83
|
+
query_timeout: float = 300.0
|
|
84
|
+
pool_size: int = 5
|
|
85
|
+
retry_attempts: int = 3
|
|
86
|
+
retry_delay: float = 1.0
|
|
87
|
+
retry_backoff: float = 2.0
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
AsyncConfigT = TypeVar("AsyncConfigT", bound=AsyncDataSourceConfig)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
# =============================================================================
|
|
94
|
+
# Connection Pool
|
|
95
|
+
# =============================================================================
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class AsyncConnectionPool(Generic[TypeVar("ConnT")]):
|
|
99
|
+
"""Async connection pool with semaphore-based concurrency control.
|
|
100
|
+
|
|
101
|
+
Manages a pool of connections for async data sources, providing
|
|
102
|
+
automatic connection lifecycle management and concurrency limiting.
|
|
103
|
+
|
|
104
|
+
Example:
|
|
105
|
+
>>> async def create_connection():
|
|
106
|
+
... return await SomeClient.connect(uri)
|
|
107
|
+
>>>
|
|
108
|
+
>>> pool = AsyncConnectionPool(
|
|
109
|
+
... factory=create_connection,
|
|
110
|
+
... size=5,
|
|
111
|
+
... timeout=30.0,
|
|
112
|
+
... )
|
|
113
|
+
>>> await pool.initialize()
|
|
114
|
+
>>>
|
|
115
|
+
>>> async with pool.acquire() as conn:
|
|
116
|
+
... result = await conn.query("...")
|
|
117
|
+
>>>
|
|
118
|
+
>>> await pool.close()
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
def __init__(
|
|
122
|
+
self,
|
|
123
|
+
factory: Callable[[], Any],
|
|
124
|
+
size: int = 5,
|
|
125
|
+
timeout: float = 30.0,
|
|
126
|
+
validator: Callable[[Any], bool] | None = None,
|
|
127
|
+
) -> None:
|
|
128
|
+
"""Initialize the connection pool.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
factory: Async callable that creates a new connection.
|
|
132
|
+
size: Maximum number of connections in the pool.
|
|
133
|
+
timeout: Timeout for acquiring a connection (seconds).
|
|
134
|
+
validator: Optional callable to validate connection health.
|
|
135
|
+
"""
|
|
136
|
+
self._factory = factory
|
|
137
|
+
self._size = size
|
|
138
|
+
self._timeout = timeout
|
|
139
|
+
self._validator = validator
|
|
140
|
+
|
|
141
|
+
self._semaphore = asyncio.Semaphore(size)
|
|
142
|
+
self._connections: asyncio.Queue[Any] = asyncio.Queue(maxsize=size)
|
|
143
|
+
self._lock = asyncio.Lock()
|
|
144
|
+
self._initialized = False
|
|
145
|
+
self._closed = False
|
|
146
|
+
self._active_count = 0
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def size(self) -> int:
|
|
150
|
+
"""Get pool size."""
|
|
151
|
+
return self._size
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def available(self) -> int:
|
|
155
|
+
"""Get number of available connections."""
|
|
156
|
+
return self._connections.qsize()
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def active(self) -> int:
|
|
160
|
+
"""Get number of active (in-use) connections."""
|
|
161
|
+
return self._active_count
|
|
162
|
+
|
|
163
|
+
@property
|
|
164
|
+
def is_initialized(self) -> bool:
|
|
165
|
+
"""Check if pool is initialized."""
|
|
166
|
+
return self._initialized
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def is_closed(self) -> bool:
|
|
170
|
+
"""Check if pool is closed."""
|
|
171
|
+
return self._closed
|
|
172
|
+
|
|
173
|
+
async def initialize(self) -> None:
|
|
174
|
+
"""Initialize the connection pool by creating initial connections."""
|
|
175
|
+
if self._initialized:
|
|
176
|
+
return
|
|
177
|
+
|
|
178
|
+
async with self._lock:
|
|
179
|
+
if self._initialized:
|
|
180
|
+
return
|
|
181
|
+
|
|
182
|
+
# Pre-create connections
|
|
183
|
+
for _ in range(self._size):
|
|
184
|
+
try:
|
|
185
|
+
if asyncio.iscoroutinefunction(self._factory):
|
|
186
|
+
conn = await asyncio.wait_for(
|
|
187
|
+
self._factory(), timeout=self._timeout
|
|
188
|
+
)
|
|
189
|
+
else:
|
|
190
|
+
conn = self._factory()
|
|
191
|
+
await self._connections.put(conn)
|
|
192
|
+
except asyncio.TimeoutError:
|
|
193
|
+
raise AsyncConnectionPoolError(
|
|
194
|
+
f"Timeout creating connection after {self._timeout}s",
|
|
195
|
+
pool_size=self._size,
|
|
196
|
+
)
|
|
197
|
+
except Exception as e:
|
|
198
|
+
raise AsyncConnectionPoolError(
|
|
199
|
+
f"Failed to create connection: {e}",
|
|
200
|
+
pool_size=self._size,
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
self._initialized = True
|
|
204
|
+
|
|
205
|
+
@asynccontextmanager
|
|
206
|
+
async def acquire(self):
|
|
207
|
+
"""Acquire a connection from the pool.
|
|
208
|
+
|
|
209
|
+
Yields:
|
|
210
|
+
A connection from the pool.
|
|
211
|
+
|
|
212
|
+
Raises:
|
|
213
|
+
AsyncConnectionPoolError: If pool is closed or timeout occurs.
|
|
214
|
+
"""
|
|
215
|
+
if self._closed:
|
|
216
|
+
raise AsyncConnectionPoolError("Connection pool is closed")
|
|
217
|
+
|
|
218
|
+
if not self._initialized:
|
|
219
|
+
await self.initialize()
|
|
220
|
+
|
|
221
|
+
# Acquire semaphore to limit concurrency
|
|
222
|
+
try:
|
|
223
|
+
await asyncio.wait_for(
|
|
224
|
+
self._semaphore.acquire(), timeout=self._timeout
|
|
225
|
+
)
|
|
226
|
+
except asyncio.TimeoutError:
|
|
227
|
+
raise AsyncTimeoutError("acquire_connection", self._timeout)
|
|
228
|
+
|
|
229
|
+
conn = None
|
|
230
|
+
try:
|
|
231
|
+
# Get connection from queue
|
|
232
|
+
try:
|
|
233
|
+
conn = self._connections.get_nowait()
|
|
234
|
+
except asyncio.QueueEmpty:
|
|
235
|
+
# Create new connection if pool exhausted
|
|
236
|
+
if asyncio.iscoroutinefunction(self._factory):
|
|
237
|
+
conn = await self._factory()
|
|
238
|
+
else:
|
|
239
|
+
conn = self._factory()
|
|
240
|
+
|
|
241
|
+
# Validate connection if validator provided
|
|
242
|
+
if self._validator and not self._validator(conn):
|
|
243
|
+
# Connection is stale, create new one
|
|
244
|
+
if asyncio.iscoroutinefunction(self._factory):
|
|
245
|
+
conn = await self._factory()
|
|
246
|
+
else:
|
|
247
|
+
conn = self._factory()
|
|
248
|
+
|
|
249
|
+
self._active_count += 1
|
|
250
|
+
yield conn
|
|
251
|
+
|
|
252
|
+
finally:
|
|
253
|
+
self._active_count -= 1
|
|
254
|
+
|
|
255
|
+
# Return connection to pool
|
|
256
|
+
if conn is not None and not self._closed:
|
|
257
|
+
try:
|
|
258
|
+
self._connections.put_nowait(conn)
|
|
259
|
+
except asyncio.QueueFull:
|
|
260
|
+
# Pool is full, close this connection
|
|
261
|
+
if hasattr(conn, "close"):
|
|
262
|
+
if asyncio.iscoroutinefunction(conn.close):
|
|
263
|
+
await conn.close()
|
|
264
|
+
else:
|
|
265
|
+
conn.close()
|
|
266
|
+
|
|
267
|
+
self._semaphore.release()
|
|
268
|
+
|
|
269
|
+
async def close(self) -> None:
|
|
270
|
+
"""Close all connections in the pool."""
|
|
271
|
+
if self._closed:
|
|
272
|
+
return
|
|
273
|
+
|
|
274
|
+
async with self._lock:
|
|
275
|
+
if self._closed:
|
|
276
|
+
return
|
|
277
|
+
|
|
278
|
+
self._closed = True
|
|
279
|
+
|
|
280
|
+
# Close all pooled connections
|
|
281
|
+
while not self._connections.empty():
|
|
282
|
+
try:
|
|
283
|
+
conn = self._connections.get_nowait()
|
|
284
|
+
if hasattr(conn, "close"):
|
|
285
|
+
if asyncio.iscoroutinefunction(conn.close):
|
|
286
|
+
await conn.close()
|
|
287
|
+
else:
|
|
288
|
+
conn.close()
|
|
289
|
+
except asyncio.QueueEmpty:
|
|
290
|
+
break
|
|
291
|
+
except Exception:
|
|
292
|
+
pass # Best effort cleanup
|
|
293
|
+
|
|
294
|
+
async def __aenter__(self) -> "AsyncConnectionPool":
|
|
295
|
+
"""Async context manager entry."""
|
|
296
|
+
await self.initialize()
|
|
297
|
+
return self
|
|
298
|
+
|
|
299
|
+
async def __aexit__(
|
|
300
|
+
self,
|
|
301
|
+
exc_type: type[BaseException] | None,
|
|
302
|
+
exc_val: BaseException | None,
|
|
303
|
+
exc_tb: Any,
|
|
304
|
+
) -> None:
|
|
305
|
+
"""Async context manager exit."""
|
|
306
|
+
await self.close()
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
# =============================================================================
|
|
310
|
+
# Abstract Async Base Data Source
|
|
311
|
+
# =============================================================================
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
class AsyncBaseDataSource(ABC, Generic[AsyncConfigT]):
|
|
315
|
+
"""Abstract base class for async data sources.
|
|
316
|
+
|
|
317
|
+
This class provides common functionality for async data source
|
|
318
|
+
implementations, including connection pooling, caching, and
|
|
319
|
+
async context management.
|
|
320
|
+
|
|
321
|
+
Type Parameters:
|
|
322
|
+
AsyncConfigT: The configuration type for this data source.
|
|
323
|
+
|
|
324
|
+
Example:
|
|
325
|
+
>>> class MyAsyncDataSource(AsyncBaseDataSource[MyConfig]):
|
|
326
|
+
... source_type = "my_async_source"
|
|
327
|
+
...
|
|
328
|
+
... async def get_schema_async(self) -> dict[str, ColumnType]:
|
|
329
|
+
... async with self._pool.acquire() as conn:
|
|
330
|
+
... return await conn.get_schema()
|
|
331
|
+
"""
|
|
332
|
+
|
|
333
|
+
source_type: str = "async_base"
|
|
334
|
+
|
|
335
|
+
def __init__(self, config: AsyncConfigT | None = None) -> None:
|
|
336
|
+
"""Initialize the async data source.
|
|
337
|
+
|
|
338
|
+
Args:
|
|
339
|
+
config: Optional configuration. Uses defaults if not provided.
|
|
340
|
+
"""
|
|
341
|
+
self._config = config or self._default_config()
|
|
342
|
+
self._cached_schema: dict[str, ColumnType] | None = None
|
|
343
|
+
self._cached_row_count: int | None = None
|
|
344
|
+
self._pool: AsyncConnectionPool | None = None
|
|
345
|
+
self._is_connected: bool = False
|
|
346
|
+
self._lock = asyncio.Lock()
|
|
347
|
+
|
|
348
|
+
@classmethod
|
|
349
|
+
def _default_config(cls) -> AsyncConfigT:
|
|
350
|
+
"""Create default configuration.
|
|
351
|
+
|
|
352
|
+
Override in subclasses for custom default configurations.
|
|
353
|
+
"""
|
|
354
|
+
return AsyncDataSourceConfig() # type: ignore
|
|
355
|
+
|
|
356
|
+
@property
|
|
357
|
+
def config(self) -> AsyncConfigT:
|
|
358
|
+
"""Get the data source configuration."""
|
|
359
|
+
return self._config
|
|
360
|
+
|
|
361
|
+
@property
|
|
362
|
+
def name(self) -> str:
|
|
363
|
+
"""Get the data source name."""
|
|
364
|
+
if self._config.name:
|
|
365
|
+
return self._config.name
|
|
366
|
+
return f"{self.source_type}_source"
|
|
367
|
+
|
|
368
|
+
# -------------------------------------------------------------------------
|
|
369
|
+
# Sync Properties (cached values)
|
|
370
|
+
# -------------------------------------------------------------------------
|
|
371
|
+
|
|
372
|
+
@property
|
|
373
|
+
def schema(self) -> dict[str, ColumnType]:
|
|
374
|
+
"""Get the schema as column name to type mapping (cached).
|
|
375
|
+
|
|
376
|
+
Note: This returns cached schema. Call get_schema_async() first
|
|
377
|
+
to populate the cache, or use the async context manager.
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
Column name to type mapping.
|
|
381
|
+
|
|
382
|
+
Raises:
|
|
383
|
+
RuntimeError: If schema not yet cached.
|
|
384
|
+
"""
|
|
385
|
+
if self._cached_schema is None:
|
|
386
|
+
raise RuntimeError(
|
|
387
|
+
"Schema not yet loaded. Call get_schema_async() or use "
|
|
388
|
+
"async context manager to initialize the data source."
|
|
389
|
+
)
|
|
390
|
+
return self._cached_schema
|
|
391
|
+
|
|
392
|
+
@property
|
|
393
|
+
def columns(self) -> list[str]:
|
|
394
|
+
"""Get list of column names."""
|
|
395
|
+
return list(self.schema.keys())
|
|
396
|
+
|
|
397
|
+
@property
|
|
398
|
+
def row_count(self) -> int | None:
|
|
399
|
+
"""Get row count if efficiently available (cached).
|
|
400
|
+
|
|
401
|
+
Returns:
|
|
402
|
+
Row count or None if not efficiently computable.
|
|
403
|
+
"""
|
|
404
|
+
return self._cached_row_count
|
|
405
|
+
|
|
406
|
+
@property
|
|
407
|
+
def capabilities(self) -> set[DataSourceCapability]:
|
|
408
|
+
"""Get the capabilities this data source supports.
|
|
409
|
+
|
|
410
|
+
Override in subclasses to declare specific capabilities.
|
|
411
|
+
"""
|
|
412
|
+
return {DataSourceCapability.SCHEMA_INFERENCE}
|
|
413
|
+
|
|
414
|
+
# -------------------------------------------------------------------------
|
|
415
|
+
# Abstract Async Methods
|
|
416
|
+
# -------------------------------------------------------------------------
|
|
417
|
+
|
|
418
|
+
@abstractmethod
|
|
419
|
+
async def get_schema_async(self) -> dict[str, ColumnType]:
|
|
420
|
+
"""Asynchronously fetch and return the schema.
|
|
421
|
+
|
|
422
|
+
This method performs the actual I/O operation to retrieve schema
|
|
423
|
+
information. Implementations should cache the result.
|
|
424
|
+
|
|
425
|
+
Returns:
|
|
426
|
+
Column name to type mapping.
|
|
427
|
+
"""
|
|
428
|
+
pass
|
|
429
|
+
|
|
430
|
+
@abstractmethod
|
|
431
|
+
async def to_polars_lazyframe_async(self) -> "pl.LazyFrame":
|
|
432
|
+
"""Asynchronously convert the data source to a Polars LazyFrame.
|
|
433
|
+
|
|
434
|
+
Returns:
|
|
435
|
+
Polars LazyFrame.
|
|
436
|
+
"""
|
|
437
|
+
pass
|
|
438
|
+
|
|
439
|
+
@abstractmethod
|
|
440
|
+
async def sample_async(
|
|
441
|
+
self, n: int = 1000, seed: int | None = None
|
|
442
|
+
) -> "AsyncBaseDataSource":
|
|
443
|
+
"""Asynchronously create a new data source with sampled data.
|
|
444
|
+
|
|
445
|
+
Args:
|
|
446
|
+
n: Number of rows to sample.
|
|
447
|
+
seed: Random seed for reproducibility.
|
|
448
|
+
|
|
449
|
+
Returns:
|
|
450
|
+
A new async data source containing the sampled data.
|
|
451
|
+
"""
|
|
452
|
+
pass
|
|
453
|
+
|
|
454
|
+
# -------------------------------------------------------------------------
|
|
455
|
+
# Connection Management
|
|
456
|
+
# -------------------------------------------------------------------------
|
|
457
|
+
|
|
458
|
+
@abstractmethod
|
|
459
|
+
async def _create_connection_factory(self) -> Callable:
|
|
460
|
+
"""Create a connection factory for the pool.
|
|
461
|
+
|
|
462
|
+
Returns:
|
|
463
|
+
Async callable that creates a new connection.
|
|
464
|
+
"""
|
|
465
|
+
pass
|
|
466
|
+
|
|
467
|
+
async def connect_async(self) -> None:
|
|
468
|
+
"""Establish connection to the data source."""
|
|
469
|
+
if self._is_connected:
|
|
470
|
+
return
|
|
471
|
+
|
|
472
|
+
async with self._lock:
|
|
473
|
+
if self._is_connected:
|
|
474
|
+
return
|
|
475
|
+
|
|
476
|
+
# Create connection pool
|
|
477
|
+
factory = await self._create_connection_factory()
|
|
478
|
+
self._pool = AsyncConnectionPool(
|
|
479
|
+
factory=factory,
|
|
480
|
+
size=self._config.pool_size,
|
|
481
|
+
timeout=self._config.connection_timeout,
|
|
482
|
+
)
|
|
483
|
+
await self._pool.initialize()
|
|
484
|
+
|
|
485
|
+
# Pre-fetch schema
|
|
486
|
+
self._cached_schema = await self.get_schema_async()
|
|
487
|
+
|
|
488
|
+
self._is_connected = True
|
|
489
|
+
|
|
490
|
+
async def disconnect_async(self) -> None:
|
|
491
|
+
"""Close connection to the data source."""
|
|
492
|
+
if not self._is_connected:
|
|
493
|
+
return
|
|
494
|
+
|
|
495
|
+
async with self._lock:
|
|
496
|
+
if not self._is_connected:
|
|
497
|
+
return
|
|
498
|
+
|
|
499
|
+
if self._pool:
|
|
500
|
+
await self._pool.close()
|
|
501
|
+
self._pool = None
|
|
502
|
+
|
|
503
|
+
self._is_connected = False
|
|
504
|
+
|
|
505
|
+
async def validate_connection_async(self) -> bool:
|
|
506
|
+
"""Validate that the data source connection is working.
|
|
507
|
+
|
|
508
|
+
Returns:
|
|
509
|
+
True if connection is valid.
|
|
510
|
+
"""
|
|
511
|
+
try:
|
|
512
|
+
if not self._is_connected:
|
|
513
|
+
await self.connect_async()
|
|
514
|
+
# Try to get schema as basic validation
|
|
515
|
+
await self.get_schema_async()
|
|
516
|
+
return True
|
|
517
|
+
except Exception:
|
|
518
|
+
return False
|
|
519
|
+
|
|
520
|
+
async def get_row_count_async(self) -> int | None:
|
|
521
|
+
"""Asynchronously get the row count.
|
|
522
|
+
|
|
523
|
+
Override in subclasses to provide efficient implementation.
|
|
524
|
+
|
|
525
|
+
Returns:
|
|
526
|
+
Row count or None if not efficiently computable.
|
|
527
|
+
"""
|
|
528
|
+
return self._cached_row_count
|
|
529
|
+
|
|
530
|
+
# -------------------------------------------------------------------------
|
|
531
|
+
# Sync Fallback (for compatibility)
|
|
532
|
+
# -------------------------------------------------------------------------
|
|
533
|
+
|
|
534
|
+
def get_execution_engine(self) -> "BaseExecutionEngine":
|
|
535
|
+
"""Get an execution engine for this data source.
|
|
536
|
+
|
|
537
|
+
Note: This is a sync method for compatibility. It creates
|
|
538
|
+
a wrapped sync execution engine from the async source.
|
|
539
|
+
|
|
540
|
+
Returns:
|
|
541
|
+
An execution engine appropriate for this data source.
|
|
542
|
+
"""
|
|
543
|
+
from truthound.datasources.adapters import AsyncToSyncAdapter
|
|
544
|
+
|
|
545
|
+
# Wrap self in sync adapter and get its engine
|
|
546
|
+
sync_adapter = AsyncToSyncAdapter(self)
|
|
547
|
+
return sync_adapter.get_execution_engine()
|
|
548
|
+
|
|
549
|
+
# -------------------------------------------------------------------------
|
|
550
|
+
# Async Context Manager
|
|
551
|
+
# -------------------------------------------------------------------------
|
|
552
|
+
|
|
553
|
+
async def __aenter__(self) -> "AsyncBaseDataSource":
|
|
554
|
+
"""Async context manager entry."""
|
|
555
|
+
await self.connect_async()
|
|
556
|
+
return self
|
|
557
|
+
|
|
558
|
+
async def __aexit__(
|
|
559
|
+
self,
|
|
560
|
+
exc_type: type[BaseException] | None,
|
|
561
|
+
exc_val: BaseException | None,
|
|
562
|
+
exc_tb: Any,
|
|
563
|
+
) -> None:
|
|
564
|
+
"""Async context manager exit."""
|
|
565
|
+
await self.disconnect_async()
|
|
566
|
+
|
|
567
|
+
# -------------------------------------------------------------------------
|
|
568
|
+
# Utility Methods
|
|
569
|
+
# -------------------------------------------------------------------------
|
|
570
|
+
|
|
571
|
+
def get_column_type(self, column: str) -> ColumnType | None:
|
|
572
|
+
"""Get the type of a specific column.
|
|
573
|
+
|
|
574
|
+
Args:
|
|
575
|
+
column: Column name.
|
|
576
|
+
|
|
577
|
+
Returns:
|
|
578
|
+
Column type or None if column doesn't exist.
|
|
579
|
+
"""
|
|
580
|
+
return self.schema.get(column)
|
|
581
|
+
|
|
582
|
+
def get_numeric_columns(self) -> list[str]:
|
|
583
|
+
"""Get list of numeric columns."""
|
|
584
|
+
numeric_types = {ColumnType.INTEGER, ColumnType.FLOAT, ColumnType.DECIMAL}
|
|
585
|
+
return [col for col, dtype in self.schema.items() if dtype in numeric_types]
|
|
586
|
+
|
|
587
|
+
def get_string_columns(self) -> list[str]:
|
|
588
|
+
"""Get list of string columns."""
|
|
589
|
+
string_types = {ColumnType.STRING, ColumnType.TEXT}
|
|
590
|
+
return [col for col, dtype in self.schema.items() if dtype in string_types]
|
|
591
|
+
|
|
592
|
+
def __repr__(self) -> str:
|
|
593
|
+
"""Get string representation."""
|
|
594
|
+
connected = "connected" if self._is_connected else "disconnected"
|
|
595
|
+
row_info = f", rows={self.row_count}" if self.row_count else ""
|
|
596
|
+
return (
|
|
597
|
+
f"{self.__class__.__name__}(name='{self.name}', "
|
|
598
|
+
f"status={connected}{row_info})"
|
|
599
|
+
)
|