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,672 @@
|
|
|
1
|
+
"""Compression provider implementations.
|
|
2
|
+
|
|
3
|
+
This module provides concrete implementations of compression algorithms
|
|
4
|
+
with a unified interface and lazy loading of optional dependencies.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import gzip
|
|
10
|
+
import hashlib
|
|
11
|
+
import time
|
|
12
|
+
import zlib
|
|
13
|
+
from abc import ABC, abstractmethod
|
|
14
|
+
from io import BytesIO
|
|
15
|
+
from typing import Any, Callable, Type
|
|
16
|
+
|
|
17
|
+
from truthound.stores.compression.base import (
|
|
18
|
+
CompressionAlgorithm,
|
|
19
|
+
CompressionConfig,
|
|
20
|
+
CompressionError,
|
|
21
|
+
CompressionLevel,
|
|
22
|
+
CompressionMetrics,
|
|
23
|
+
CompressionResult,
|
|
24
|
+
Compressor,
|
|
25
|
+
DecompressionError,
|
|
26
|
+
Decompressor,
|
|
27
|
+
UnsupportedAlgorithmError,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# =============================================================================
|
|
32
|
+
# Base Compressor
|
|
33
|
+
# =============================================================================
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class BaseCompressor(ABC):
|
|
37
|
+
"""Abstract base class for compressor implementations.
|
|
38
|
+
|
|
39
|
+
Provides common functionality for all compressors including
|
|
40
|
+
metrics collection, checksum verification, and configuration handling.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self, config: CompressionConfig | None = None) -> None:
|
|
44
|
+
"""Initialize the compressor.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
config: Compression configuration.
|
|
48
|
+
"""
|
|
49
|
+
self._config = config or CompressionConfig(algorithm=self.algorithm)
|
|
50
|
+
self._config.validate()
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def algorithm(self) -> CompressionAlgorithm:
|
|
55
|
+
"""Get the compression algorithm."""
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def config(self) -> CompressionConfig:
|
|
60
|
+
"""Get the configuration."""
|
|
61
|
+
return self._config
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def level(self) -> int:
|
|
65
|
+
"""Get the effective compression level."""
|
|
66
|
+
return self._config.get_effective_level()
|
|
67
|
+
|
|
68
|
+
@abstractmethod
|
|
69
|
+
def _do_compress(self, data: bytes) -> bytes:
|
|
70
|
+
"""Perform actual compression. Override in subclasses."""
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
@abstractmethod
|
|
74
|
+
def _do_decompress(self, data: bytes) -> bytes:
|
|
75
|
+
"""Perform actual decompression. Override in subclasses."""
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
def compress(self, data: bytes) -> bytes:
|
|
79
|
+
"""Compress data.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
data: Uncompressed data.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Compressed data.
|
|
86
|
+
|
|
87
|
+
Raises:
|
|
88
|
+
CompressionError: If compression fails.
|
|
89
|
+
"""
|
|
90
|
+
try:
|
|
91
|
+
return self._do_compress(data)
|
|
92
|
+
except Exception as e:
|
|
93
|
+
raise CompressionError(
|
|
94
|
+
f"Compression failed: {e}", self.algorithm.value
|
|
95
|
+
) from e
|
|
96
|
+
|
|
97
|
+
def decompress(self, data: bytes) -> bytes:
|
|
98
|
+
"""Decompress data.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
data: Compressed data.
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
Decompressed data.
|
|
105
|
+
|
|
106
|
+
Raises:
|
|
107
|
+
DecompressionError: If decompression fails.
|
|
108
|
+
"""
|
|
109
|
+
try:
|
|
110
|
+
return self._do_decompress(data)
|
|
111
|
+
except Exception as e:
|
|
112
|
+
raise DecompressionError(
|
|
113
|
+
f"Decompression failed: {e}", self.algorithm.value
|
|
114
|
+
) from e
|
|
115
|
+
|
|
116
|
+
def compress_with_metrics(self, data: bytes) -> CompressionResult:
|
|
117
|
+
"""Compress data and return metrics.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
data: Uncompressed data.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Compression result with metrics.
|
|
124
|
+
"""
|
|
125
|
+
original_size = len(data)
|
|
126
|
+
|
|
127
|
+
# Measure compression time
|
|
128
|
+
start_time = time.perf_counter()
|
|
129
|
+
compressed = self.compress(data)
|
|
130
|
+
compression_time = (time.perf_counter() - start_time) * 1000
|
|
131
|
+
|
|
132
|
+
compressed_size = len(compressed)
|
|
133
|
+
|
|
134
|
+
# Calculate checksum if enabled
|
|
135
|
+
checksum = None
|
|
136
|
+
if self._config.verify_checksum:
|
|
137
|
+
checksum = hashlib.md5(data).hexdigest()
|
|
138
|
+
|
|
139
|
+
metrics = CompressionMetrics(
|
|
140
|
+
original_size=original_size,
|
|
141
|
+
compressed_size=compressed_size,
|
|
142
|
+
compression_time_ms=compression_time,
|
|
143
|
+
algorithm=self.algorithm,
|
|
144
|
+
level=self.level,
|
|
145
|
+
)
|
|
146
|
+
metrics.update_ratio()
|
|
147
|
+
|
|
148
|
+
return CompressionResult(
|
|
149
|
+
data=compressed,
|
|
150
|
+
metrics=metrics,
|
|
151
|
+
checksum=checksum,
|
|
152
|
+
header={
|
|
153
|
+
"algorithm": self.algorithm.value,
|
|
154
|
+
"level": self.level,
|
|
155
|
+
"original_size": original_size,
|
|
156
|
+
} if self._config.include_header else {},
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def decompress_with_metrics(
|
|
160
|
+
self,
|
|
161
|
+
data: bytes,
|
|
162
|
+
expected_checksum: str | None = None,
|
|
163
|
+
) -> tuple[bytes, CompressionMetrics]:
|
|
164
|
+
"""Decompress data and return metrics.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
data: Compressed data.
|
|
168
|
+
expected_checksum: Optional checksum to verify.
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
Tuple of (decompressed data, metrics).
|
|
172
|
+
"""
|
|
173
|
+
compressed_size = len(data)
|
|
174
|
+
|
|
175
|
+
# Measure decompression time
|
|
176
|
+
start_time = time.perf_counter()
|
|
177
|
+
decompressed = self.decompress(data)
|
|
178
|
+
decompression_time = (time.perf_counter() - start_time) * 1000
|
|
179
|
+
|
|
180
|
+
original_size = len(decompressed)
|
|
181
|
+
|
|
182
|
+
# Verify checksum if provided
|
|
183
|
+
if expected_checksum and self._config.verify_checksum:
|
|
184
|
+
actual_checksum = hashlib.md5(decompressed).hexdigest()
|
|
185
|
+
if actual_checksum != expected_checksum:
|
|
186
|
+
raise DecompressionError(
|
|
187
|
+
f"Checksum mismatch: expected {expected_checksum}, got {actual_checksum}",
|
|
188
|
+
self.algorithm.value,
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
metrics = CompressionMetrics(
|
|
192
|
+
original_size=original_size,
|
|
193
|
+
compressed_size=compressed_size,
|
|
194
|
+
decompression_time_ms=decompression_time,
|
|
195
|
+
algorithm=self.algorithm,
|
|
196
|
+
level=self.level,
|
|
197
|
+
)
|
|
198
|
+
metrics.update_ratio()
|
|
199
|
+
|
|
200
|
+
return decompressed, metrics
|
|
201
|
+
|
|
202
|
+
def get_extension(self) -> str:
|
|
203
|
+
"""Get file extension for compressed files."""
|
|
204
|
+
return self.algorithm.extension
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
# =============================================================================
|
|
208
|
+
# No-op Compressor
|
|
209
|
+
# =============================================================================
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class NoopCompressor(BaseCompressor):
|
|
213
|
+
"""No-operation compressor (passthrough)."""
|
|
214
|
+
|
|
215
|
+
@property
|
|
216
|
+
def algorithm(self) -> CompressionAlgorithm:
|
|
217
|
+
return CompressionAlgorithm.NONE
|
|
218
|
+
|
|
219
|
+
def _do_compress(self, data: bytes) -> bytes:
|
|
220
|
+
return data
|
|
221
|
+
|
|
222
|
+
def _do_decompress(self, data: bytes) -> bytes:
|
|
223
|
+
return data
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
# =============================================================================
|
|
227
|
+
# Gzip Compressor
|
|
228
|
+
# =============================================================================
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
class GzipCompressor(BaseCompressor):
|
|
232
|
+
"""Gzip compression using Python's built-in gzip module.
|
|
233
|
+
|
|
234
|
+
Gzip is widely supported and provides good compression for text data.
|
|
235
|
+
It's the default choice for web content and general-purpose compression.
|
|
236
|
+
"""
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def algorithm(self) -> CompressionAlgorithm:
|
|
240
|
+
return CompressionAlgorithm.GZIP
|
|
241
|
+
|
|
242
|
+
def _do_compress(self, data: bytes) -> bytes:
|
|
243
|
+
return gzip.compress(data, compresslevel=self.level)
|
|
244
|
+
|
|
245
|
+
def _do_decompress(self, data: bytes) -> bytes:
|
|
246
|
+
return gzip.decompress(data)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
# =============================================================================
|
|
250
|
+
# Zstandard Compressor
|
|
251
|
+
# =============================================================================
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class ZstdCompressor(BaseCompressor):
|
|
255
|
+
"""Zstandard compression using the zstandard library.
|
|
256
|
+
|
|
257
|
+
Zstd provides excellent compression ratio and speed balance.
|
|
258
|
+
It's particularly good for structured data like JSON.
|
|
259
|
+
"""
|
|
260
|
+
|
|
261
|
+
_zstd = None
|
|
262
|
+
|
|
263
|
+
@classmethod
|
|
264
|
+
def _get_zstd(cls):
|
|
265
|
+
"""Lazy import zstandard."""
|
|
266
|
+
if cls._zstd is None:
|
|
267
|
+
try:
|
|
268
|
+
import zstandard
|
|
269
|
+
cls._zstd = zstandard
|
|
270
|
+
except ImportError:
|
|
271
|
+
raise UnsupportedAlgorithmError(
|
|
272
|
+
"zstd",
|
|
273
|
+
["gzip", "lz4"] + (["snappy"] if _is_snappy_available() else []),
|
|
274
|
+
)
|
|
275
|
+
return cls._zstd
|
|
276
|
+
|
|
277
|
+
@property
|
|
278
|
+
def algorithm(self) -> CompressionAlgorithm:
|
|
279
|
+
return CompressionAlgorithm.ZSTD
|
|
280
|
+
|
|
281
|
+
def _get_compressor(self):
|
|
282
|
+
"""Get zstd compressor instance."""
|
|
283
|
+
zstd = self._get_zstd()
|
|
284
|
+
return zstd.ZstdCompressor(
|
|
285
|
+
level=self.level,
|
|
286
|
+
threads=self._config.threads if self._config.threads > 0 else -1,
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
def _get_decompressor(self):
|
|
290
|
+
"""Get zstd decompressor instance."""
|
|
291
|
+
zstd = self._get_zstd()
|
|
292
|
+
return zstd.ZstdDecompressor()
|
|
293
|
+
|
|
294
|
+
def _do_compress(self, data: bytes) -> bytes:
|
|
295
|
+
compressor = self._get_compressor()
|
|
296
|
+
return compressor.compress(data)
|
|
297
|
+
|
|
298
|
+
def _do_decompress(self, data: bytes) -> bytes:
|
|
299
|
+
decompressor = self._get_decompressor()
|
|
300
|
+
return decompressor.decompress(data)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
# =============================================================================
|
|
304
|
+
# LZ4 Compressor
|
|
305
|
+
# =============================================================================
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
class LZ4Compressor(BaseCompressor):
|
|
309
|
+
"""LZ4 compression using the lz4 library.
|
|
310
|
+
|
|
311
|
+
LZ4 is optimized for speed and is one of the fastest compression
|
|
312
|
+
algorithms available. Good for real-time compression needs.
|
|
313
|
+
"""
|
|
314
|
+
|
|
315
|
+
_lz4 = None
|
|
316
|
+
|
|
317
|
+
@classmethod
|
|
318
|
+
def _get_lz4(cls):
|
|
319
|
+
"""Lazy import lz4."""
|
|
320
|
+
if cls._lz4 is None:
|
|
321
|
+
try:
|
|
322
|
+
import lz4.frame
|
|
323
|
+
cls._lz4 = lz4.frame
|
|
324
|
+
except ImportError:
|
|
325
|
+
raise UnsupportedAlgorithmError(
|
|
326
|
+
"lz4",
|
|
327
|
+
["gzip", "zstd"] + (["snappy"] if _is_snappy_available() else []),
|
|
328
|
+
)
|
|
329
|
+
return cls._lz4
|
|
330
|
+
|
|
331
|
+
@property
|
|
332
|
+
def algorithm(self) -> CompressionAlgorithm:
|
|
333
|
+
return CompressionAlgorithm.LZ4
|
|
334
|
+
|
|
335
|
+
def _do_compress(self, data: bytes) -> bytes:
|
|
336
|
+
lz4 = self._get_lz4()
|
|
337
|
+
return lz4.compress(
|
|
338
|
+
data,
|
|
339
|
+
compression_level=self.level,
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
def _do_decompress(self, data: bytes) -> bytes:
|
|
343
|
+
lz4 = self._get_lz4()
|
|
344
|
+
return lz4.decompress(data)
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
# =============================================================================
|
|
348
|
+
# Snappy Compressor
|
|
349
|
+
# =============================================================================
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def _is_snappy_available() -> bool:
|
|
353
|
+
"""Check if snappy is available."""
|
|
354
|
+
try:
|
|
355
|
+
import snappy
|
|
356
|
+
return True
|
|
357
|
+
except ImportError:
|
|
358
|
+
return False
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
class SnappyCompressor(BaseCompressor):
|
|
362
|
+
"""Snappy compression using the python-snappy library.
|
|
363
|
+
|
|
364
|
+
Snappy is designed for speed rather than maximum compression.
|
|
365
|
+
Commonly used in distributed systems like Hadoop and Kafka.
|
|
366
|
+
"""
|
|
367
|
+
|
|
368
|
+
_snappy = None
|
|
369
|
+
|
|
370
|
+
@classmethod
|
|
371
|
+
def _get_snappy(cls):
|
|
372
|
+
"""Lazy import snappy."""
|
|
373
|
+
if cls._snappy is None:
|
|
374
|
+
try:
|
|
375
|
+
import snappy
|
|
376
|
+
cls._snappy = snappy
|
|
377
|
+
except ImportError:
|
|
378
|
+
raise UnsupportedAlgorithmError(
|
|
379
|
+
"snappy",
|
|
380
|
+
["gzip", "lz4", "zstd"],
|
|
381
|
+
)
|
|
382
|
+
return cls._snappy
|
|
383
|
+
|
|
384
|
+
@property
|
|
385
|
+
def algorithm(self) -> CompressionAlgorithm:
|
|
386
|
+
return CompressionAlgorithm.SNAPPY
|
|
387
|
+
|
|
388
|
+
def _do_compress(self, data: bytes) -> bytes:
|
|
389
|
+
snappy = self._get_snappy()
|
|
390
|
+
return snappy.compress(data)
|
|
391
|
+
|
|
392
|
+
def _do_decompress(self, data: bytes) -> bytes:
|
|
393
|
+
snappy = self._get_snappy()
|
|
394
|
+
return snappy.decompress(data)
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
# =============================================================================
|
|
398
|
+
# Brotli Compressor
|
|
399
|
+
# =============================================================================
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
class BrotliCompressor(BaseCompressor):
|
|
403
|
+
"""Brotli compression using the brotli library.
|
|
404
|
+
|
|
405
|
+
Brotli provides excellent compression for web content,
|
|
406
|
+
particularly for text-based formats. It's slower but achieves
|
|
407
|
+
better compression ratios than gzip.
|
|
408
|
+
"""
|
|
409
|
+
|
|
410
|
+
_brotli = None
|
|
411
|
+
|
|
412
|
+
@classmethod
|
|
413
|
+
def _get_brotli(cls):
|
|
414
|
+
"""Lazy import brotli."""
|
|
415
|
+
if cls._brotli is None:
|
|
416
|
+
try:
|
|
417
|
+
import brotli
|
|
418
|
+
cls._brotli = brotli
|
|
419
|
+
except ImportError:
|
|
420
|
+
raise UnsupportedAlgorithmError(
|
|
421
|
+
"brotli",
|
|
422
|
+
["gzip", "zstd", "lz4"],
|
|
423
|
+
)
|
|
424
|
+
return cls._brotli
|
|
425
|
+
|
|
426
|
+
@property
|
|
427
|
+
def algorithm(self) -> CompressionAlgorithm:
|
|
428
|
+
return CompressionAlgorithm.BROTLI
|
|
429
|
+
|
|
430
|
+
def _do_compress(self, data: bytes) -> bytes:
|
|
431
|
+
brotli = self._get_brotli()
|
|
432
|
+
return brotli.compress(data, quality=self.level)
|
|
433
|
+
|
|
434
|
+
def _do_decompress(self, data: bytes) -> bytes:
|
|
435
|
+
brotli = self._get_brotli()
|
|
436
|
+
return brotli.decompress(data)
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
# =============================================================================
|
|
440
|
+
# LZMA Compressor
|
|
441
|
+
# =============================================================================
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
class LzmaCompressor(BaseCompressor):
|
|
445
|
+
"""LZMA compression using Python's built-in lzma module.
|
|
446
|
+
|
|
447
|
+
LZMA provides very high compression ratios but is slower.
|
|
448
|
+
Good for archival purposes where compression ratio matters more than speed.
|
|
449
|
+
"""
|
|
450
|
+
|
|
451
|
+
@property
|
|
452
|
+
def algorithm(self) -> CompressionAlgorithm:
|
|
453
|
+
return CompressionAlgorithm.LZMA
|
|
454
|
+
|
|
455
|
+
def _do_compress(self, data: bytes) -> bytes:
|
|
456
|
+
import lzma
|
|
457
|
+
return lzma.compress(data, preset=self.level)
|
|
458
|
+
|
|
459
|
+
def _do_decompress(self, data: bytes) -> bytes:
|
|
460
|
+
import lzma
|
|
461
|
+
return lzma.decompress(data)
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
# =============================================================================
|
|
465
|
+
# BZ2 Compressor
|
|
466
|
+
# =============================================================================
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
class Bz2Compressor(BaseCompressor):
|
|
470
|
+
"""BZ2 compression using Python's built-in bz2 module.
|
|
471
|
+
|
|
472
|
+
BZ2 provides good compression ratios, better than gzip but slower.
|
|
473
|
+
It's a good middle ground between gzip and LZMA.
|
|
474
|
+
"""
|
|
475
|
+
|
|
476
|
+
@property
|
|
477
|
+
def algorithm(self) -> CompressionAlgorithm:
|
|
478
|
+
return CompressionAlgorithm.BZ2
|
|
479
|
+
|
|
480
|
+
def _do_compress(self, data: bytes) -> bytes:
|
|
481
|
+
import bz2
|
|
482
|
+
return bz2.compress(data, compresslevel=self.level)
|
|
483
|
+
|
|
484
|
+
def _do_decompress(self, data: bytes) -> bytes:
|
|
485
|
+
import bz2
|
|
486
|
+
return bz2.decompress(data)
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
# =============================================================================
|
|
490
|
+
# Deflate Compressor
|
|
491
|
+
# =============================================================================
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
class DeflateCompressor(BaseCompressor):
|
|
495
|
+
"""Raw Deflate compression using Python's built-in zlib module.
|
|
496
|
+
|
|
497
|
+
Deflate is the underlying algorithm for gzip and zip.
|
|
498
|
+
This provides raw deflate without gzip headers.
|
|
499
|
+
"""
|
|
500
|
+
|
|
501
|
+
@property
|
|
502
|
+
def algorithm(self) -> CompressionAlgorithm:
|
|
503
|
+
return CompressionAlgorithm.DEFLATE
|
|
504
|
+
|
|
505
|
+
def _do_compress(self, data: bytes) -> bytes:
|
|
506
|
+
return zlib.compress(data, level=self.level)
|
|
507
|
+
|
|
508
|
+
def _do_decompress(self, data: bytes) -> bytes:
|
|
509
|
+
return zlib.decompress(data)
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
# =============================================================================
|
|
513
|
+
# Registry and Factory
|
|
514
|
+
# =============================================================================
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
_COMPRESSOR_REGISTRY: dict[CompressionAlgorithm, Type[BaseCompressor]] = {
|
|
518
|
+
CompressionAlgorithm.NONE: NoopCompressor,
|
|
519
|
+
CompressionAlgorithm.GZIP: GzipCompressor,
|
|
520
|
+
CompressionAlgorithm.ZSTD: ZstdCompressor,
|
|
521
|
+
CompressionAlgorithm.LZ4: LZ4Compressor,
|
|
522
|
+
CompressionAlgorithm.SNAPPY: SnappyCompressor,
|
|
523
|
+
CompressionAlgorithm.BROTLI: BrotliCompressor,
|
|
524
|
+
CompressionAlgorithm.LZMA: LzmaCompressor,
|
|
525
|
+
CompressionAlgorithm.BZ2: Bz2Compressor,
|
|
526
|
+
CompressionAlgorithm.DEFLATE: DeflateCompressor,
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
def register_compressor(
|
|
531
|
+
algorithm: CompressionAlgorithm,
|
|
532
|
+
compressor_class: Type[BaseCompressor],
|
|
533
|
+
) -> None:
|
|
534
|
+
"""Register a custom compressor implementation.
|
|
535
|
+
|
|
536
|
+
Args:
|
|
537
|
+
algorithm: Algorithm identifier.
|
|
538
|
+
compressor_class: Compressor class to register.
|
|
539
|
+
"""
|
|
540
|
+
_COMPRESSOR_REGISTRY[algorithm] = compressor_class
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
def get_compressor(
|
|
544
|
+
algorithm: str | CompressionAlgorithm,
|
|
545
|
+
level: CompressionLevel | int = CompressionLevel.BALANCED,
|
|
546
|
+
**kwargs: Any,
|
|
547
|
+
) -> BaseCompressor:
|
|
548
|
+
"""Create a compressor for the specified algorithm.
|
|
549
|
+
|
|
550
|
+
Args:
|
|
551
|
+
algorithm: Compression algorithm name or enum.
|
|
552
|
+
level: Compression level.
|
|
553
|
+
**kwargs: Additional configuration options.
|
|
554
|
+
|
|
555
|
+
Returns:
|
|
556
|
+
Configured compressor instance.
|
|
557
|
+
|
|
558
|
+
Raises:
|
|
559
|
+
UnsupportedAlgorithmError: If algorithm is not available.
|
|
560
|
+
"""
|
|
561
|
+
# Convert string to enum
|
|
562
|
+
if isinstance(algorithm, str):
|
|
563
|
+
try:
|
|
564
|
+
algorithm = CompressionAlgorithm(algorithm.lower())
|
|
565
|
+
except ValueError:
|
|
566
|
+
raise UnsupportedAlgorithmError(
|
|
567
|
+
algorithm,
|
|
568
|
+
[a.value for a in _COMPRESSOR_REGISTRY.keys()],
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
# Get compressor class
|
|
572
|
+
compressor_class = _COMPRESSOR_REGISTRY.get(algorithm)
|
|
573
|
+
if compressor_class is None:
|
|
574
|
+
raise UnsupportedAlgorithmError(
|
|
575
|
+
algorithm.value,
|
|
576
|
+
[a.value for a in _COMPRESSOR_REGISTRY.keys()],
|
|
577
|
+
)
|
|
578
|
+
|
|
579
|
+
# Create config
|
|
580
|
+
custom_level = level if isinstance(level, int) else None
|
|
581
|
+
level_preset = level if isinstance(level, CompressionLevel) else CompressionLevel.BALANCED
|
|
582
|
+
|
|
583
|
+
config = CompressionConfig(
|
|
584
|
+
algorithm=algorithm,
|
|
585
|
+
level=level_preset,
|
|
586
|
+
custom_level=custom_level,
|
|
587
|
+
**{k: v for k, v in kwargs.items() if hasattr(CompressionConfig, k)},
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
return compressor_class(config)
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
def get_decompressor(
|
|
594
|
+
algorithm: str | CompressionAlgorithm,
|
|
595
|
+
**kwargs: Any,
|
|
596
|
+
) -> BaseCompressor:
|
|
597
|
+
"""Create a decompressor for the specified algorithm.
|
|
598
|
+
|
|
599
|
+
Args:
|
|
600
|
+
algorithm: Compression algorithm name or enum.
|
|
601
|
+
**kwargs: Additional configuration options.
|
|
602
|
+
|
|
603
|
+
Returns:
|
|
604
|
+
Configured decompressor instance.
|
|
605
|
+
"""
|
|
606
|
+
return get_compressor(algorithm, **kwargs)
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
def list_available_algorithms() -> list[CompressionAlgorithm]:
|
|
610
|
+
"""List all available compression algorithms.
|
|
611
|
+
|
|
612
|
+
Returns:
|
|
613
|
+
List of available algorithms.
|
|
614
|
+
"""
|
|
615
|
+
available = []
|
|
616
|
+
for algorithm in _COMPRESSOR_REGISTRY.keys():
|
|
617
|
+
if is_algorithm_available(algorithm):
|
|
618
|
+
available.append(algorithm)
|
|
619
|
+
return available
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
def is_algorithm_available(algorithm: str | CompressionAlgorithm) -> bool:
|
|
623
|
+
"""Check if a compression algorithm is available.
|
|
624
|
+
|
|
625
|
+
Args:
|
|
626
|
+
algorithm: Algorithm to check.
|
|
627
|
+
|
|
628
|
+
Returns:
|
|
629
|
+
True if algorithm is available.
|
|
630
|
+
"""
|
|
631
|
+
if isinstance(algorithm, str):
|
|
632
|
+
try:
|
|
633
|
+
algorithm = CompressionAlgorithm(algorithm.lower())
|
|
634
|
+
except ValueError:
|
|
635
|
+
return False
|
|
636
|
+
|
|
637
|
+
# Built-in algorithms are always available
|
|
638
|
+
if algorithm in (
|
|
639
|
+
CompressionAlgorithm.NONE,
|
|
640
|
+
CompressionAlgorithm.GZIP,
|
|
641
|
+
CompressionAlgorithm.DEFLATE,
|
|
642
|
+
CompressionAlgorithm.LZMA,
|
|
643
|
+
CompressionAlgorithm.BZ2,
|
|
644
|
+
):
|
|
645
|
+
return True
|
|
646
|
+
|
|
647
|
+
# Check optional dependencies
|
|
648
|
+
if algorithm == CompressionAlgorithm.ZSTD:
|
|
649
|
+
try:
|
|
650
|
+
import zstandard
|
|
651
|
+
return True
|
|
652
|
+
except ImportError:
|
|
653
|
+
return False
|
|
654
|
+
|
|
655
|
+
if algorithm == CompressionAlgorithm.LZ4:
|
|
656
|
+
try:
|
|
657
|
+
import lz4.frame
|
|
658
|
+
return True
|
|
659
|
+
except ImportError:
|
|
660
|
+
return False
|
|
661
|
+
|
|
662
|
+
if algorithm == CompressionAlgorithm.SNAPPY:
|
|
663
|
+
return _is_snappy_available()
|
|
664
|
+
|
|
665
|
+
if algorithm == CompressionAlgorithm.BROTLI:
|
|
666
|
+
try:
|
|
667
|
+
import brotli
|
|
668
|
+
return True
|
|
669
|
+
except ImportError:
|
|
670
|
+
return False
|
|
671
|
+
|
|
672
|
+
return False
|