dblift 2.0.3__tar.gz → 2.0.4__tar.gz
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.
- {dblift-2.0.3 → dblift-2.0.4}/PKG-INFO +26 -23
- {dblift-2.0.3 → dblift-2.0.4}/README.md +24 -22
- {dblift-2.0.3 → dblift-2.0.4}/api/client.py +1 -2
- {dblift-2.0.3 → dblift-2.0.4}/cli/_command_handlers.py +0 -1
- {dblift-2.0.3 → dblift-2.0.4}/cli/_config_helpers.py +9 -18
- {dblift-2.0.3 → dblift-2.0.4}/cli/_constants.py +0 -9
- {dblift-2.0.3 → dblift-2.0.4}/cli/_output.py +1 -2
- {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/_shared.py +4 -15
- {dblift-2.0.3 → dblift-2.0.4}/cli/main.py +3 -30
- {dblift-2.0.3 → dblift-2.0.4}/config/dblift_config.py +4 -80
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/__init__.py +0 -4
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/console.py +1 -1
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/formatters/_formatter_impl.py +1 -83
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/formatters/htmlformatter.py +1 -270
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/formatters/jsonformatter.py +0 -298
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/results.py +0 -395
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/base_command.py +2 -2
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_validator/migration_validator.py +2 -2
- {dblift-2.0.3 → dblift-2.0.4}/db/base_quirks.py +0 -6
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/quirks.py +0 -1
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/quirks.py +0 -1
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/quirks.py +0 -1
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/quirks.py +0 -1
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/quirks.py +0 -1
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/quirks.py +0 -1
- {dblift-2.0.3 → dblift-2.0.4}/dblift.egg-info/PKG-INFO +26 -23
- {dblift-2.0.3 → dblift-2.0.4}/dblift.egg-info/SOURCES.txt +0 -5
- {dblift-2.0.3 → dblift-2.0.4}/dblift.egg-info/requires.txt +1 -0
- {dblift-2.0.3 → dblift-2.0.4}/pyproject.toml +2 -1
- dblift-2.0.3/config/validation_config.py +0 -124
- dblift-2.0.3/core/logger/formatters/_format_diff_meta.py +0 -117
- dblift-2.0.3/core/logger/formatters/_format_diff_object.py +0 -195
- dblift-2.0.3/core/logger/formatters/_format_diff_routine.py +0 -208
- dblift-2.0.3/core/logger/formatters/_format_diff_table.py +0 -250
- {dblift-2.0.3 → dblift-2.0.4}/LICENSE +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/api/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/api/_cli_support.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/api/_client_factory.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/api/_client_operations.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/api/_engine_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/api/async_client.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/api/events.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/api/migrations.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/api/py.typed +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/cli/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/cli/_parser_setup.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/cli/db_utils.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/cli/extensions.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/baseline.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/clean.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/import_flyway.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/info.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/migrate.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/repair.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/undo.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/validate.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/_credential_masking.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/cosmosdb_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/db2_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/dummy_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/mysql_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/oracle_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/postgresql_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/sqlite_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/sqlserver_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/_url_builder_mixin.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/config_builder.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/database_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/errors.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/secrets/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/secrets/_cache.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/secrets/_provider_base.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/secrets/_registry.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/secrets/_resolver.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/config/secrets/_secrets_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/constants.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/dialect_boundary.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/exceptions.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/features.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/_column_enricher.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/_partition_enricher.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/_schema_orchestrator.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/_utils.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/_vendor_property_applier.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/base_introspector.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/capability_matrix.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/base_extractor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/column_extractor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/constraint_extractor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/index_extractor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/misc_extractor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/procedure_extractor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/sequence_extractor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/table_extractor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/trigger_extractor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/view_extractor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/introspector_factory.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/result.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/schema_introspector.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/vendor_queries_base.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/vendor_queries_factory.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/vendor_queries_protocols.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/introspection/version_detector.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/_base.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/_factory.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/_formatters.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/_levels.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/_multi.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/_null.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/formatters/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/formatters/diff_utils.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/formatters/factory.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/formatters/formatter.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/logger/log.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/_type_match.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/clean_summary.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/_script_events.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/baseline_command.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/clean_command.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/import_flyway_command.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/info_command.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/migrate_command.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/repair_command.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/undo_command.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/validate_command.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/encoding.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/executor/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/executor/execution_engine.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/executor/migration_executor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/executor/migration_helpers.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/executor/placeholder_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/executor/transaction_policy.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/executors/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/executors/base_executor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/executors/executor_factory.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/executors/python_executor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/executors/sql_executor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/formats/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/formats/format_detector.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/formats/migration_format.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/history/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/history/migration_history_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/journals/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/journals/migration_journal.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/migration.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/placeholders/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/placeholders/placeholder_service.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/rules/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/rules/migration_rules.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/migration_script_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/_ddl_reversers.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/_dml_reversers.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/_extractors.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/_generator.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/_helpers.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/_models.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/_reversers.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/sql/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/sql/execution_statement.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/sql/sql_analyzer.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/sql/sql_execution_service.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/sql/statement_splitter.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/state/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/state/migration_data_service.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/state/migration_display_state.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/state/migration_formatter.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/state/migration_state.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/state/migration_state_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/state/migration_state_service.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/ui/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/ui/data_collector.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/ui/display_formatters.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/ui/migration_analyzer.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/ui/migration_ui.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/ui/table_renderer.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/migration/version_utils.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/normalization/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/normalization/data_type_normalizer.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/normalization/dependency_resolver.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/normalization/identifier_normalizer.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/normalization/object_orderer.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/normalization/type_constants.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/normalization/type_mapper.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/normalization/type_mappings.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/normalization/type_normalizer.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/seams/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/seams/event_listeners.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/seams/introspection.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/_base_parse_result.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/_base_sql_column.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/_base_sql_constraint.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/_base_sql_object.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/_base_sql_statement.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/base.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/constraint_validator.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/database_link.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/dialect.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/event.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/extension.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/foreign_data_wrapper.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/foreign_server.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/index.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/linked_server.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/module.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/package.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/partition.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/procedure.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/sequence.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/synonym.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/table.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/table_canonicalizer.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/table_options.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/trigger.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/user_defined_type.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/view.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/view_options.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/_partition_handler.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/_sqlglot_builders.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/base_statement_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/base_tokenizer.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/common/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/common/base_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/dialects/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/dialects/base_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/enhanced_regex_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/hybrid_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/parser_context.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/parser_factory.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/parser_interface.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/sqlglot_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/tokens.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/unified_regex_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_validator/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_validator/_checksum_validator.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_validator/_flyway_compatibility.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_validator/_migration_filter.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_validator/_sql_syntax_validator.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/sql_validator/_strict_mode_validator.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/state/sql_script_formatter.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/state/sql_statement.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/utils/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/utils/database_url_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/utils/metadata_helpers.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/utils/row_access.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/utils/string_utils.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/core/utils/url_masking.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/base_provider.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/constants.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/error.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/error_handler.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/exceptions.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/native_connection_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/object_naming.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/base_history_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/base_locking_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/base_query_executor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/base_schema_operations.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/base_snapshot_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/base_undo_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/cosmosdb/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/cosmosdb/_sdk.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/cosmosdb/connection_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/cosmosdb/history_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/cosmosdb/locking_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/cosmosdb/query_executor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/cosmosdb/schema_operations.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/introspection/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/parser/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/parser/cosmosdb_regex_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/plugin.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/provider.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/quirks.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/sdk_translator/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/sdk_translator/_executor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/sdk_translator/_executors.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/sdk_translator/_parsing.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/sdk_translator/_script_generation.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/sdk_translator/_translator.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/sdk_translator/_translators.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/db2/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/db2/history_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/db2/locking_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/db2/schema_operations.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/introspection/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/parser/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/parser/db2_regex_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/parser/parser_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/plugin.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/provider.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/sqlalchemy_url.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mariadb/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mariadb/plugin.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mariadb/provider.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mariadb/quirks.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/introspection/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/mysql/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/mysql/history_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/mysql/locking_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/mysql/schema_operations.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/parser/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/parser/mysql_regex_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/parser/mysql_statement_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/parser/mysql_tokenizer.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/parser/parser_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/plugin.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/provider.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/sqlalchemy_url.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/introspection/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/introspection/oracle_utils.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/oracle/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/oracle/dbms_output.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/oracle/history_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/oracle/locking_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/oracle/schema_operations.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/_comments.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/_object_extractor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/_plsql_block.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/_sqlplus.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/_statement_splitter.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/oracle_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/oracle_statement_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/oracle_tokenizer.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/parser_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/sqlplus_context.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/plugin.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/provider.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/sqlalchemy_url.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/_provider_query_executor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/introspection/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/parser/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/parser/parser_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/parser/postgresql_regex_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/parser/postgresql_statement_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/parser/postgresql_tokenizer.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/plugin.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/postgresql/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/postgresql/history_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/postgresql/locking_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/postgresql/schema_operations.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/provider.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/sqlalchemy_url.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/introspection/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/parser/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/parser/parser_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/parser/sqlite_regex_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/plugin.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/provider.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/sqlalchemy_url.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/sqlite/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/sqlite/connection_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/sqlite/history_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/sqlite/locking_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/sqlite/query_executor.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/sqlite/schema_operations.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/introspection/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/parser/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/parser/parser_config.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/parser/sqlserver_regex_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/parser/sqlserver_statement_parser.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/parser/sqlserver_tokenizer.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/parser/tsql_batch_separator.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/plugin.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/provider.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/sqlalchemy_url.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/sqlserver/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/sqlserver/history_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/sqlserver/locking_manager.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/sqlserver/schema_operations.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/provider_capabilities.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/provider_interfaces.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/provider_registry.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/sqlalchemy_provider.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/db/value_utils.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/dblift.egg-info/dependency_links.txt +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/dblift.egg-info/entry_points.txt +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/dblift.egg-info/top_level.txt +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/integrations/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/integrations/django/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/integrations/django/_client.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/integrations/django/_engine.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/integrations/django/apps.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/integrations/django/checks.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/integrations/django/management/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/integrations/django/management/commands/__init__.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/integrations/django/management/commands/dblift_info.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/integrations/django/management/commands/dblift_migrate.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/integrations/django/management/commands/dblift_validate.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/integrations/fastapi.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/integrations/flask.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/integrations/opentelemetry.py +0 -0
- {dblift-2.0.3 → dblift-2.0.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dblift
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.4
|
|
4
4
|
Summary: A database migration tool that supports multiple databases with native Python drivers
|
|
5
5
|
Classifier: Development Status :: 5 - Production/Stable
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -22,6 +22,7 @@ Requires-Dist: Jinja2>=3.1.0
|
|
|
22
22
|
Requires-Dist: sqlglot>=30.0.0
|
|
23
23
|
Requires-Dist: packaging>=23.0
|
|
24
24
|
Requires-Dist: azure-cosmos>=4.5.0
|
|
25
|
+
Requires-Dist: azure-identity>=1.15.0
|
|
25
26
|
Requires-Dist: SQLAlchemy>=2.0.0
|
|
26
27
|
Provides-Extra: dev
|
|
27
28
|
Requires-Dist: pytest>=7.3.1; extra == "dev"
|
|
@@ -132,6 +133,30 @@ DBLift helps you track and apply database changes systematically. Think of it as
|
|
|
132
133
|
<!-- BEGIN: OSS README sync: python-install -->
|
|
133
134
|
#### Python / pip install
|
|
134
135
|
|
|
136
|
+
| Install | Dialects |
|
|
137
|
+
| --- | --- |
|
|
138
|
+
| `pip install dblift[postgresql]` | PostgreSQL (OSS) |
|
|
139
|
+
| `pip install dblift[oracle]` | Oracle (OSS) |
|
|
140
|
+
|
|
141
|
+
`pytest-dblift` quickstart:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
pip install pytest-dblift
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
# tests/test_foo.py
|
|
149
|
+
import pytest
|
|
150
|
+
|
|
151
|
+
def test_something(dblift_migrated_db, dblift_client):
|
|
152
|
+
# dblift_migrated_db ensures migrations applied (function scope by default)
|
|
153
|
+
result = dblift_client.info()
|
|
154
|
+
assert result.pending_count == 0
|
|
155
|
+
```
|
|
156
|
+
<!-- END: OSS README sync: python-install -->
|
|
157
|
+
|
|
158
|
+
#### Using the Python SDK
|
|
159
|
+
|
|
135
160
|
**Synchronous client:**
|
|
136
161
|
|
|
137
162
|
```python
|
|
@@ -157,28 +182,6 @@ async with AsyncDBLiftClient.from_sqlalchemy(engine, migrations_dir="migrations"
|
|
|
157
182
|
|
|
158
183
|
See [Async usage](docs/user-guide/async.md) for the full guide.
|
|
159
184
|
|
|
160
|
-
| Install | Dialects |
|
|
161
|
-
| --- | --- |
|
|
162
|
-
| `pip install dblift[postgresql]` | PostgreSQL (OSS) |
|
|
163
|
-
| `pip install dblift[oracle]` | Oracle (OSS) |
|
|
164
|
-
|
|
165
|
-
`pytest-dblift` quickstart:
|
|
166
|
-
|
|
167
|
-
```bash
|
|
168
|
-
pip install pytest-dblift
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
```python
|
|
172
|
-
# tests/test_foo.py
|
|
173
|
-
import pytest
|
|
174
|
-
|
|
175
|
-
def test_something(dblift_migrated_db, dblift_client):
|
|
176
|
-
# dblift_migrated_db ensures migrations applied (function scope by default)
|
|
177
|
-
result = dblift_client.info()
|
|
178
|
-
assert result.pending_count == 0
|
|
179
|
-
```
|
|
180
|
-
<!-- END: OSS README sync: python-install -->
|
|
181
|
-
|
|
182
185
|
### Your First Migration
|
|
183
186
|
|
|
184
187
|
Let's create your first database change in 4 simple steps:
|
|
@@ -53,6 +53,30 @@ DBLift helps you track and apply database changes systematically. Think of it as
|
|
|
53
53
|
<!-- BEGIN: OSS README sync: python-install -->
|
|
54
54
|
#### Python / pip install
|
|
55
55
|
|
|
56
|
+
| Install | Dialects |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| `pip install dblift[postgresql]` | PostgreSQL (OSS) |
|
|
59
|
+
| `pip install dblift[oracle]` | Oracle (OSS) |
|
|
60
|
+
|
|
61
|
+
`pytest-dblift` quickstart:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install pytest-dblift
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
# tests/test_foo.py
|
|
69
|
+
import pytest
|
|
70
|
+
|
|
71
|
+
def test_something(dblift_migrated_db, dblift_client):
|
|
72
|
+
# dblift_migrated_db ensures migrations applied (function scope by default)
|
|
73
|
+
result = dblift_client.info()
|
|
74
|
+
assert result.pending_count == 0
|
|
75
|
+
```
|
|
76
|
+
<!-- END: OSS README sync: python-install -->
|
|
77
|
+
|
|
78
|
+
#### Using the Python SDK
|
|
79
|
+
|
|
56
80
|
**Synchronous client:**
|
|
57
81
|
|
|
58
82
|
```python
|
|
@@ -78,28 +102,6 @@ async with AsyncDBLiftClient.from_sqlalchemy(engine, migrations_dir="migrations"
|
|
|
78
102
|
|
|
79
103
|
See [Async usage](docs/user-guide/async.md) for the full guide.
|
|
80
104
|
|
|
81
|
-
| Install | Dialects |
|
|
82
|
-
| --- | --- |
|
|
83
|
-
| `pip install dblift[postgresql]` | PostgreSQL (OSS) |
|
|
84
|
-
| `pip install dblift[oracle]` | Oracle (OSS) |
|
|
85
|
-
|
|
86
|
-
`pytest-dblift` quickstart:
|
|
87
|
-
|
|
88
|
-
```bash
|
|
89
|
-
pip install pytest-dblift
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
```python
|
|
93
|
-
# tests/test_foo.py
|
|
94
|
-
import pytest
|
|
95
|
-
|
|
96
|
-
def test_something(dblift_migrated_db, dblift_client):
|
|
97
|
-
# dblift_migrated_db ensures migrations applied (function scope by default)
|
|
98
|
-
result = dblift_client.info()
|
|
99
|
-
assert result.pending_count == 0
|
|
100
|
-
```
|
|
101
|
-
<!-- END: OSS README sync: python-install -->
|
|
102
|
-
|
|
103
105
|
### Your First Migration
|
|
104
106
|
|
|
105
107
|
Let's create your first database change in 4 simple steps:
|
|
@@ -59,8 +59,7 @@ def _with_client_emitter(method: _F) -> _F:
|
|
|
59
59
|
"every public operation wraps its body in ``use_client_emitter``",
|
|
60
60
|
but only ``migrate`` and ``undo`` actually did. Any core-layer
|
|
61
61
|
``emit_event`` raised from ``clean`` / ``info`` / ``validate`` /
|
|
62
|
-
``
|
|
63
|
-
``export_schema`` / ``snapshot`` would land on the process-wide
|
|
62
|
+
``repair`` / ``baseline`` / ``import_flyway`` would land on the process-wide
|
|
64
63
|
default emitter, breaking the per-client isolation guarantee.
|
|
65
64
|
Decorating every public operation restores that invariant once and
|
|
66
65
|
keeps it enforced by location instead of by convention.
|
|
@@ -9,7 +9,6 @@ from cli.extensions import load_command_handlers, load_terminal_commands
|
|
|
9
9
|
from cli.handlers._shared import ( # noqa: F401
|
|
10
10
|
_MIGRATION_FILENAME_RE,
|
|
11
11
|
CliCommandContext,
|
|
12
|
-
ValidateSqlConfigClient,
|
|
13
12
|
_extract_version_filters,
|
|
14
13
|
_is_migration_sql_file,
|
|
15
14
|
_minimal_result,
|
|
@@ -224,22 +224,16 @@ def _load_and_merge_config(args: argparse.Namespace, log: Any) -> Any:
|
|
|
224
224
|
db_overrides["schema"] = args.database_schema
|
|
225
225
|
|
|
226
226
|
if db_overrides:
|
|
227
|
-
# Resolve secret URIs in CLI overrides
|
|
228
|
-
|
|
229
|
-
# the same bypass must apply here so they don't trigger provider calls.
|
|
230
|
-
command = getattr(args, "command", None)
|
|
231
|
-
commands_list = getattr(args, "commands_list", None) or ([command] if command else [])
|
|
232
|
-
is_offline = command in ("validate-sql", "plan") and len(commands_list) == 1
|
|
233
|
-
if not is_offline:
|
|
234
|
-
from config.secrets._resolver import resolve_secret_refs
|
|
227
|
+
# Resolve secret URIs in CLI overrides.
|
|
228
|
+
from config.secrets._resolver import resolve_secret_refs
|
|
235
229
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
230
|
+
try:
|
|
231
|
+
db_overrides = resolve_secret_refs({"database": db_overrides}, config.secrets).get(
|
|
232
|
+
"database", db_overrides
|
|
233
|
+
)
|
|
234
|
+
except SecretsResolutionError as e:
|
|
235
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
236
|
+
sys.exit(1)
|
|
243
237
|
config.database = ConfigBuilder.merge_database_overrides(config.database, db_overrides)
|
|
244
238
|
|
|
245
239
|
if log:
|
|
@@ -300,12 +294,9 @@ def _validate_db_config(
|
|
|
300
294
|
"clean",
|
|
301
295
|
"validate",
|
|
302
296
|
"info",
|
|
303
|
-
"diff",
|
|
304
297
|
"repair",
|
|
305
298
|
"import-flyway",
|
|
306
299
|
"baseline",
|
|
307
|
-
"export-schema",
|
|
308
|
-
"snapshot",
|
|
309
300
|
]
|
|
310
301
|
if args.command not in migration_commands:
|
|
311
302
|
return
|
|
@@ -22,12 +22,3 @@ from __future__ import annotations
|
|
|
22
22
|
MACHINE_READABLE_FORMATS: frozenset[str] = frozenset(
|
|
23
23
|
{"json", "sarif", "github-actions", "gitlab", "compact"}
|
|
24
24
|
)
|
|
25
|
-
FAIL_ON_CHOICES: tuple[str, ...] = ("never", "error", "warning", "info")
|
|
26
|
-
|
|
27
|
-
# ``console`` and ``html`` are human-facing; every other entry must also
|
|
28
|
-
# appear in ``MACHINE_READABLE_FORMATS`` above (tested in the matrix
|
|
29
|
-
# regression suite to prevent the two lists from drifting out of sync).
|
|
30
|
-
VALIDATE_SQL_FORMATS: tuple[str, ...] = (
|
|
31
|
-
"console",
|
|
32
|
-
"html",
|
|
33
|
-
) + tuple(sorted(MACHINE_READABLE_FORMATS))
|
|
@@ -13,8 +13,7 @@ dispatch in ``cli/main.py`` re-derive the same predicate:
|
|
|
13
13
|
else:
|
|
14
14
|
ctx.log.info(payload) # routed through ConsoleLog
|
|
15
15
|
|
|
16
|
-
That duplication has already caused
|
|
17
|
-
+ PR-01 `validate-sql --format json` scope). ADR-0005 added the
|
|
16
|
+
That duplication has already caused banner-routing regressions. ADR-0005 added the
|
|
18
17
|
`MACHINE_READABLE_FORMATS` set as a single source of truth; this
|
|
19
18
|
module does the same for the *routing* decision itself.
|
|
20
19
|
|
|
@@ -12,9 +12,9 @@ from dataclasses import dataclass, field
|
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from typing import Any, Dict, List, Optional
|
|
14
14
|
|
|
15
|
-
# Flyway-compatible migration filename patterns
|
|
16
|
-
#
|
|
17
|
-
#
|
|
15
|
+
# Flyway-compatible migration filename patterns used to skip non-migration
|
|
16
|
+
# SQL files when scanning a directory (e.g. leftover temp files, schema
|
|
17
|
+
# dumps) so only intentional migration scripts are
|
|
18
18
|
# checked. Explicitly-listed files are always validated regardless of name.
|
|
19
19
|
_MIGRATION_FILENAME_RE = re.compile(
|
|
20
20
|
r"^[VRUBvrub][\d_.]*__.*\.sql$",
|
|
@@ -61,17 +61,6 @@ class CliCommandContext:
|
|
|
61
61
|
dir_recursive_map: Dict[Path, bool] = field(default_factory=dict)
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
@dataclass
|
|
65
|
-
class ValidateSqlConfigClient:
|
|
66
|
-
"""Config-only stand-in for DBLiftClient when running offline commands."""
|
|
67
|
-
|
|
68
|
-
config: Any
|
|
69
|
-
|
|
70
|
-
def plan(self, *args: Any, **kwargs: Any) -> Any:
|
|
71
|
-
"""Offline plan construction is not available in DBLift OSS."""
|
|
72
|
-
raise RuntimeError("plan is not available in DBLift OSS")
|
|
73
|
-
|
|
74
|
-
|
|
75
64
|
def _set_command_completed(log: Any, result: Any, command_type: str) -> None:
|
|
76
65
|
"""Helper to report command completion to the logger (eliminates SMELL-04 duplication)."""
|
|
77
66
|
if result is None:
|
|
@@ -98,7 +87,7 @@ def emit_rendered_output(
|
|
|
98
87
|
) -> None:
|
|
99
88
|
"""Dispatch a rendered command output to machine channel, logger, and/or file.
|
|
100
89
|
|
|
101
|
-
|
|
90
|
+
Used by command handlers that follow the same machine/human/file
|
|
102
91
|
dispatch pattern once the command-specific rendering is done.
|
|
103
92
|
"""
|
|
104
93
|
if command_output.is_machine_format:
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import sys
|
|
4
4
|
from dataclasses import dataclass
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import Any, List, Optional
|
|
6
|
+
from typing import Any, List, Optional
|
|
7
7
|
|
|
8
8
|
# Add project root to Python path when running as a script
|
|
9
9
|
# This allows imports to work when running: python3 cli/main.py
|
|
@@ -23,7 +23,6 @@ from cli._command_handlers import ( # noqa: F401
|
|
|
23
23
|
_AVAILABLE_COMMANDS,
|
|
24
24
|
_COMMAND_HANDLERS,
|
|
25
25
|
CliCommandContext,
|
|
26
|
-
ValidateSqlConfigClient,
|
|
27
26
|
_extract_version_filters,
|
|
28
27
|
_handle_baseline,
|
|
29
28
|
_handle_clean,
|
|
@@ -233,8 +232,7 @@ def _parse_argv_and_load_config(argv: List[str]) -> _CliContext:
|
|
|
233
232
|
# Validate log format before any config load so bogus --log-format fails with argparse
|
|
234
233
|
# UX (and so db/* commands are covered — _validate_db_config skips early for "db").
|
|
235
234
|
_validate_log_format_for_cli(args, parser)
|
|
236
|
-
# Attach the full command list so load_config can
|
|
237
|
-
# offline commands (plan, validate-sql) from chained invocations.
|
|
235
|
+
# Attach the full command list so load_config can see chained invocations.
|
|
238
236
|
args.commands_list = commands
|
|
239
237
|
config = None if commands[0] == "db" else _load_and_merge_config(args, log)
|
|
240
238
|
_validate_db_config(args, config, parser, commands)
|
|
@@ -289,24 +287,12 @@ def _setup_logging_and_output(ctx: _CliContext) -> CommandOutput:
|
|
|
289
287
|
assert ctx.config is not None
|
|
290
288
|
ctx.log = _configure_logging(ctx.args, ctx.config, ctx.parser)
|
|
291
289
|
|
|
292
|
-
_apply_validate_sql_configured_output_format(ctx)
|
|
293
|
-
|
|
294
290
|
# Banner routing is centralised in :class:`cli._output.CommandOutput`
|
|
295
291
|
# (ADR-0008 supersedes ADR-0005's suppression approach). Machine
|
|
296
292
|
# mode routes the banner to stderr; human mode keeps it on stdout.
|
|
297
293
|
return from_args(ctx.args)
|
|
298
294
|
|
|
299
295
|
|
|
300
|
-
def _apply_validate_sql_configured_output_format(ctx: _CliContext) -> None:
|
|
301
|
-
"""Use configured validate-sql output format before top-level banner routing."""
|
|
302
|
-
if ctx.commands != ["validate-sql"] or getattr(ctx.args, "format", None):
|
|
303
|
-
return
|
|
304
|
-
validation_config = getattr(ctx.config, "validation", None)
|
|
305
|
-
output_format = getattr(validation_config, "output_format", None)
|
|
306
|
-
if output_format:
|
|
307
|
-
ctx.args.format = output_format
|
|
308
|
-
|
|
309
|
-
|
|
310
296
|
def _dispatch_command(ctx: _CliContext, command_output: CommandOutput) -> int:
|
|
311
297
|
"""Phase 4: build full workflow context and run the command loop.
|
|
312
298
|
|
|
@@ -319,13 +305,7 @@ def _dispatch_command(ctx: _CliContext, command_output: CommandOutput) -> int:
|
|
|
319
305
|
_resolve_scripts_directories(ctx.args, ctx.config, ctx.parser, ctx.commands)
|
|
320
306
|
)
|
|
321
307
|
|
|
322
|
-
|
|
323
|
-
offline_only = False
|
|
324
|
-
client: Union[DBLiftClient, ValidateSqlConfigClient]
|
|
325
|
-
if offline_only:
|
|
326
|
-
client = ValidateSqlConfigClient(config=ctx.config)
|
|
327
|
-
else:
|
|
328
|
-
client = DBLiftClient.from_config(ctx.config, logger=ctx.log)
|
|
308
|
+
client = DBLiftClient.from_config(ctx.config, logger=ctx.log)
|
|
329
309
|
ctx.log.debug(f"scripts_dir: {scripts_dir}")
|
|
330
310
|
ctx.log.debug(
|
|
331
311
|
f"config.migrations.directories: {getattr(ctx.config.migrations, 'directories', None)}"
|
|
@@ -364,13 +344,6 @@ def _dispatch_command(ctx: _CliContext, command_output: CommandOutput) -> int:
|
|
|
364
344
|
# in base_command does not re-emit it (it also has no format awareness).
|
|
365
345
|
if main_header:
|
|
366
346
|
base_command._console_main_header_printed = True # type: ignore[attr-defined]
|
|
367
|
-
for module_name in (
|
|
368
|
-
"cli.export_schema_command",
|
|
369
|
-
"cli.snapshot_command",
|
|
370
|
-
):
|
|
371
|
-
command_module = sys.modules.get(module_name)
|
|
372
|
-
if command_module is not None:
|
|
373
|
-
command_module._console_main_header_printed = True # type: ignore[attr-defined]
|
|
374
347
|
|
|
375
348
|
for cmd_index, command in enumerate(ctx.commands):
|
|
376
349
|
if len(ctx.commands) > 1 and cmd_index > 0:
|
|
@@ -10,7 +10,6 @@ import yaml
|
|
|
10
10
|
from config.database_config import BaseDatabaseConfig
|
|
11
11
|
from config.errors import ConfigurationError
|
|
12
12
|
from config.secrets import SecretsConfig, resolve_secret_refs
|
|
13
|
-
from config.validation_config import ValidationConfig
|
|
14
13
|
|
|
15
14
|
ENV_PLACEHOLDER_PATTERN = re.compile(r"\$\{([^}:]+)(?::-(.*?))?\}")
|
|
16
15
|
|
|
@@ -28,56 +27,6 @@ _CONFIG_LOAD_EXC: Tuple[Type[Exception], ...] = (
|
|
|
28
27
|
)
|
|
29
28
|
|
|
30
29
|
|
|
31
|
-
# ``validate-sql`` only needs a dialect-typed DbliftConfig; connection is never opened.
|
|
32
|
-
# Placeholder database URLs satisfy :meth:`DbliftConfig.validate_complete_data` and are never
|
|
33
|
-
# used to connect in the validate-sql code path.
|
|
34
|
-
def _validate_sql_lint_filler(dialect: str) -> Dict[str, Any]:
|
|
35
|
-
"""Minimal ``database:`` block for validate-sql (lint-only) when
|
|
36
|
-
no real DB is configured.
|
|
37
|
-
|
|
38
|
-
Story 26-11: dialect normalisation + placeholder URL come from the
|
|
39
|
-
plugin registry / quirks. The earlier hardcoded
|
|
40
|
-
``_VALIDATE_SQL_DIALECT_TO_DB``, ``_VALIDATE_SQL_PLACEHOLDER_URL``,
|
|
41
|
-
and ``_VALIDATE_SQL_DB_TO_DIALECT`` dicts are gone; adding a new
|
|
42
|
-
dialect with offline-lint support = override
|
|
43
|
-
``lint_placeholder_url`` in its plugin quirks.py.
|
|
44
|
-
"""
|
|
45
|
-
from db.provider_registry import ProviderRegistry
|
|
46
|
-
|
|
47
|
-
db_type = ProviderRegistry.canonical_dialect_name((dialect or "").strip().lower())
|
|
48
|
-
if not db_type:
|
|
49
|
-
return {}
|
|
50
|
-
quirks = ProviderRegistry.get_quirks(db_type)
|
|
51
|
-
placeholder = quirks.lint_placeholder_url
|
|
52
|
-
if not placeholder:
|
|
53
|
-
return {}
|
|
54
|
-
return {
|
|
55
|
-
"database": {
|
|
56
|
-
"type": db_type,
|
|
57
|
-
"url": placeholder,
|
|
58
|
-
"username": "dblift_validate_sql",
|
|
59
|
-
"password": "dblift_validate_sql",
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def _validate_sql_effective_dialect(args: Any, config_data: Dict[str, Any]) -> Optional[str]:
|
|
65
|
-
"""Resolve validate-sql dialect from CLI or config without defaulting."""
|
|
66
|
-
cli_dialect = getattr(args, "dialect", None)
|
|
67
|
-
if isinstance(cli_dialect, str) and cli_dialect.strip():
|
|
68
|
-
return cli_dialect.strip().lower()
|
|
69
|
-
|
|
70
|
-
database_config = config_data.get("database")
|
|
71
|
-
if isinstance(database_config, dict):
|
|
72
|
-
from db.provider_registry import ProviderRegistry
|
|
73
|
-
|
|
74
|
-
db_type = str(database_config.get("type") or "").strip().lower()
|
|
75
|
-
if db_type:
|
|
76
|
-
return ProviderRegistry.canonical_dialect_name(db_type) or db_type
|
|
77
|
-
|
|
78
|
-
return None
|
|
79
|
-
|
|
80
|
-
|
|
81
30
|
def _placeholder_tokens(raw_placeholders: Any) -> List[str]:
|
|
82
31
|
if not raw_placeholders:
|
|
83
32
|
return []
|
|
@@ -170,30 +119,12 @@ def load_config(config_file_path: Optional[str], args: Optional[Any] = None) ->
|
|
|
170
119
|
if args_dict:
|
|
171
120
|
config_data = DbliftConfig.merge_config_data(config_data, args_dict)
|
|
172
121
|
|
|
173
|
-
# ``validate-sql`` does not need a real database, but static linting does
|
|
174
|
-
# need an explicit SQL dialect or a database type from config.
|
|
175
|
-
if args and getattr(args, "command", None) == "validate-sql":
|
|
176
|
-
dialect = _validate_sql_effective_dialect(args, config_data)
|
|
177
|
-
if not dialect:
|
|
178
|
-
raise ConfigurationError(
|
|
179
|
-
"validate-sql requires --dialect for offline validation when no database type is configured."
|
|
180
|
-
)
|
|
181
|
-
filler = _validate_sql_lint_filler(dialect)
|
|
182
|
-
if filler:
|
|
183
|
-
config_data = DbliftConfig.merge_config_data(filler, config_data)
|
|
184
|
-
|
|
185
122
|
if not config_data:
|
|
186
123
|
raise ConfigurationError(
|
|
187
124
|
"No configuration source provided. Pass --config, --db-url, or set DBLIFT_DB_URL."
|
|
188
125
|
)
|
|
189
126
|
|
|
190
|
-
|
|
191
|
-
commands_list = getattr(args, "commands_list", None) if args else None
|
|
192
|
-
if commands_list is None and command:
|
|
193
|
-
commands_list = [command]
|
|
194
|
-
is_offline_cmd = bool(
|
|
195
|
-
command in ("validate-sql", "plan") and commands_list and len(commands_list) == 1
|
|
196
|
-
)
|
|
127
|
+
is_offline_cmd = False
|
|
197
128
|
config = DbliftConfig.from_dict(config_data, resolve_secrets=not is_offline_cmd)
|
|
198
129
|
if args:
|
|
199
130
|
installed_by = getattr(args, "installed_by", None)
|
|
@@ -322,7 +253,6 @@ class DbliftConfig:
|
|
|
322
253
|
database: BaseDatabaseConfig
|
|
323
254
|
migrations: MigrationsConfig = field(default_factory=MigrationsConfig)
|
|
324
255
|
logging: LoggingConfig = field(default_factory=LoggingConfig)
|
|
325
|
-
validation: ValidationConfig = field(default_factory=ValidationConfig)
|
|
326
256
|
baseline_version: Optional[str] = None
|
|
327
257
|
target_version: Optional[str] = None
|
|
328
258
|
dry_run: bool = False
|
|
@@ -455,11 +385,6 @@ class DbliftConfig:
|
|
|
455
385
|
if "log_dir" in other_config:
|
|
456
386
|
self.log_dir = other_config.get("log_dir", self.log_dir)
|
|
457
387
|
|
|
458
|
-
if "validation" in other_config:
|
|
459
|
-
raw_val = other_config["validation"]
|
|
460
|
-
if raw_val is not None and isinstance(raw_val, dict):
|
|
461
|
-
self.validation = ValidationConfig.from_dict(raw_val)
|
|
462
|
-
|
|
463
388
|
# Fields that must use ``key in other_config`` so falsy values (False, 0) are not dropped.
|
|
464
389
|
for scalar_key in (
|
|
465
390
|
"strict_mode",
|
|
@@ -507,8 +432,8 @@ class DbliftConfig:
|
|
|
507
432
|
Args:
|
|
508
433
|
data: Configuration dictionary
|
|
509
434
|
resolve_secrets: When False, skip secret-URI resolution (used for
|
|
510
|
-
offline commands
|
|
511
|
-
|
|
435
|
+
offline commands that never open a DB connection and must not
|
|
436
|
+
require secret-manager credentials to be available).
|
|
512
437
|
|
|
513
438
|
Returns:
|
|
514
439
|
A DbliftConfig instance
|
|
@@ -562,7 +487,7 @@ class DbliftConfig:
|
|
|
562
487
|
# Non-secret unparseable URLs are left as-is so _apply_url_overrides
|
|
563
488
|
# raises a focused URL error immediately rather than producing a
|
|
564
489
|
# silently broken config.
|
|
565
|
-
# When secrets are not resolved (offline commands
|
|
490
|
+
# When secrets are not resolved (offline commands),
|
|
566
491
|
# a secret URI in database.url must not be validated as a database URL — the
|
|
567
492
|
# type may already be known from database.type but the URL is still raw.
|
|
568
493
|
# This covers the case where database.type is set explicitly, which skips
|
|
@@ -663,7 +588,6 @@ class DbliftConfig:
|
|
|
663
588
|
detect_encoding=migrations_detect_encoding,
|
|
664
589
|
),
|
|
665
590
|
logging=LoggingConfig(level=log_level, file=log_file, directory=log_directory),
|
|
666
|
-
validation=ValidationConfig.from_dict(data.get("validation", {})),
|
|
667
591
|
baseline_version=data.get("baseline_version"),
|
|
668
592
|
target_version=data.get("target_version"),
|
|
669
593
|
dry_run=data.get("dry_run", False),
|
|
@@ -17,12 +17,10 @@ from core.logger.log import (
|
|
|
17
17
|
from core.logger.results import (
|
|
18
18
|
BaselineResult,
|
|
19
19
|
CleanResult,
|
|
20
|
-
DiffResult,
|
|
21
20
|
InfoResult,
|
|
22
21
|
MigrateResult,
|
|
23
22
|
MigrationInfo,
|
|
24
23
|
OperationResult,
|
|
25
|
-
PlanResult,
|
|
26
24
|
RepairResult,
|
|
27
25
|
ValidateResult,
|
|
28
26
|
)
|
|
@@ -428,7 +426,6 @@ __all__ = [
|
|
|
428
426
|
"ConsoleLog",
|
|
429
427
|
"MultiLog",
|
|
430
428
|
"OperationResult",
|
|
431
|
-
"PlanResult",
|
|
432
429
|
"MigrateResult",
|
|
433
430
|
"MigrationInfo",
|
|
434
431
|
"InfoResult",
|
|
@@ -438,7 +435,6 @@ __all__ = [
|
|
|
438
435
|
"RepairResult",
|
|
439
436
|
"NullLog",
|
|
440
437
|
"DbliftLogger",
|
|
441
|
-
"DiffResult",
|
|
442
438
|
# Formatters
|
|
443
439
|
"OutputFormatter",
|
|
444
440
|
"OutputFormatterFactory",
|
|
@@ -168,7 +168,7 @@ def console_status(message: str) -> "ContextManager[Any]":
|
|
|
168
168
|
"""Return a Rich ``Console.status`` context manager, or a no-op
|
|
169
169
|
when progress is disabled (``--no-progress`` / non-tty).
|
|
170
170
|
|
|
171
|
-
Long-running command paths
|
|
171
|
+
Long-running command paths wrap their
|
|
172
172
|
blocking service calls with this so the spinner respects the
|
|
173
173
|
same suppression rules as ``rich.progress.Progress``.
|
|
174
174
|
"""
|
|
@@ -13,18 +13,12 @@ This file was extracted from the monolithic
|
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
from typing import Any, Dict, Optional, Type
|
|
15
15
|
|
|
16
|
-
from core.logger.formatters._format_diff_meta import _DiffMetaFormatterMixin
|
|
17
|
-
from core.logger.formatters._format_diff_object import _DiffObjectFormatterMixin
|
|
18
|
-
from core.logger.formatters._format_diff_routine import _DiffRoutineFormatterMixin
|
|
19
|
-
from core.logger.formatters._format_diff_table import _DiffTableFormatterMixin
|
|
20
16
|
from core.logger.results import (
|
|
21
17
|
BaselineResult,
|
|
22
18
|
CleanResult,
|
|
23
|
-
DiffResult,
|
|
24
19
|
InfoResult,
|
|
25
20
|
MigrateResult,
|
|
26
21
|
OperationResult,
|
|
27
|
-
PlanResult,
|
|
28
22
|
RepairResult,
|
|
29
23
|
UndoResult,
|
|
30
24
|
ValidateResult,
|
|
@@ -42,12 +36,7 @@ except ImportError:
|
|
|
42
36
|
JsonFormatter = None # type: ignore
|
|
43
37
|
|
|
44
38
|
|
|
45
|
-
class OutputFormatter
|
|
46
|
-
_DiffMetaFormatterMixin,
|
|
47
|
-
_DiffTableFormatterMixin,
|
|
48
|
-
_DiffRoutineFormatterMixin,
|
|
49
|
-
_DiffObjectFormatterMixin,
|
|
50
|
-
):
|
|
39
|
+
class OutputFormatter:
|
|
51
40
|
"""Unified formatter for all operation results."""
|
|
52
41
|
|
|
53
42
|
# Maps result type → (format_method_name, command_type_string)
|
|
@@ -58,9 +47,7 @@ class OutputFormatter(
|
|
|
58
47
|
ValidateResult: ("format_validate", "validate"),
|
|
59
48
|
BaselineResult: ("format_baseline", "baseline"),
|
|
60
49
|
RepairResult: ("format_repair", "repair"),
|
|
61
|
-
DiffResult: ("format_diff", "diff"),
|
|
62
50
|
UndoResult: ("format_undo", "undo"),
|
|
63
|
-
PlanResult: ("format_plan", "plan"),
|
|
64
51
|
}
|
|
65
52
|
|
|
66
53
|
def __init__(self) -> None:
|
|
@@ -192,55 +179,6 @@ class OutputFormatter(
|
|
|
192
179
|
self._append_sql_visibility(output, result)
|
|
193
180
|
return "\n".join(output)
|
|
194
181
|
|
|
195
|
-
def format_plan(self, result: PlanResult) -> str:
|
|
196
|
-
"""Format an offline plan operation result."""
|
|
197
|
-
output = []
|
|
198
|
-
output.append("Migration Plan Report")
|
|
199
|
-
output.append("=====================")
|
|
200
|
-
output.append(f"Snapshot: {result.snapshot_model or ''}")
|
|
201
|
-
output.append("Status: SUCCESS" if result.success else "Status: FAILED")
|
|
202
|
-
if result.error_message:
|
|
203
|
-
output.append(f"Error: {result.error_message}")
|
|
204
|
-
output.append(f"Applied in snapshot: {result.already_applied_count}")
|
|
205
|
-
output.append(f"Pending versioned: {result.pending_count}")
|
|
206
|
-
output.append(f"Pending repeatable: {result.repeatables_pending_count}")
|
|
207
|
-
output.append(f"Checksum drift: {result.checksum_drift_count}")
|
|
208
|
-
if result.sql_validation:
|
|
209
|
-
output.append(
|
|
210
|
-
"SQL validation: "
|
|
211
|
-
f"{result.sql_validation.status} "
|
|
212
|
-
f"({result.sql_validation.files_checked} files)"
|
|
213
|
-
)
|
|
214
|
-
if result.pending_migrations:
|
|
215
|
-
output.append("")
|
|
216
|
-
output.append("Pending Migrations:")
|
|
217
|
-
for migration in result.pending_migrations:
|
|
218
|
-
output.append(f"- {migration.script}")
|
|
219
|
-
if result.repeatables_pending:
|
|
220
|
-
output.append("")
|
|
221
|
-
output.append("Repeatables Pending:")
|
|
222
|
-
for migration in result.repeatables_pending:
|
|
223
|
-
output.append(f"- {migration.script}")
|
|
224
|
-
if result.checksum_drift:
|
|
225
|
-
output.append("")
|
|
226
|
-
output.append("Checksum Drift:")
|
|
227
|
-
for drift in result.checksum_drift:
|
|
228
|
-
output.append(
|
|
229
|
-
f"- {drift.script}: snapshot={drift.expected_checksum}, "
|
|
230
|
-
f"local={drift.actual_checksum}"
|
|
231
|
-
)
|
|
232
|
-
if result.plan_errors:
|
|
233
|
-
output.append("")
|
|
234
|
-
output.append("Errors:")
|
|
235
|
-
for error in result.plan_errors:
|
|
236
|
-
output.append(f"- {error}")
|
|
237
|
-
if result.plan_warnings:
|
|
238
|
-
output.append("")
|
|
239
|
-
output.append("Warnings:")
|
|
240
|
-
for warning in result.plan_warnings:
|
|
241
|
-
output.append(f"- {warning}")
|
|
242
|
-
return "\n".join(output)
|
|
243
|
-
|
|
244
182
|
def _append_sql_visibility(self, output: list[str], result: OperationResult) -> None:
|
|
245
183
|
"""Append SQL statements only when the operation explicitly requested them."""
|
|
246
184
|
if not getattr(result, "show_sql", False) or not getattr(result, "sql", None):
|
|
@@ -545,23 +483,3 @@ class OutputFormatter(
|
|
|
545
483
|
output.append(f"- {warning}")
|
|
546
484
|
|
|
547
485
|
return "\n".join(output)
|
|
548
|
-
|
|
549
|
-
def format_diff(self, result: DiffResult) -> str:
|
|
550
|
-
"""Format a diff/comparison operation result."""
|
|
551
|
-
sections = [
|
|
552
|
-
self._format_diff_header(result),
|
|
553
|
-
self._format_diff_counts(result),
|
|
554
|
-
self._format_table_diff(result),
|
|
555
|
-
self._format_view_diff(result),
|
|
556
|
-
self._format_index_diff(result),
|
|
557
|
-
self._format_sequence_diff(result),
|
|
558
|
-
self._format_trigger_diff(result),
|
|
559
|
-
self._format_procedure_diff(result),
|
|
560
|
-
self._format_type_diff(result),
|
|
561
|
-
self._format_extension_diff(result),
|
|
562
|
-
self._format_fdw_diff(result),
|
|
563
|
-
self._format_server_diff(result),
|
|
564
|
-
self._format_event_diff(result),
|
|
565
|
-
self._format_diff_footer(result),
|
|
566
|
-
]
|
|
567
|
-
return "\n".join(s for s in sections if s)
|