dblift 2.1.0__tar.gz → 2.2.0__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.1.0 → dblift-2.2.0}/PKG-INFO +1 -1
- {dblift-2.1.0 → dblift-2.2.0}/cli/_command_handlers.py +3 -1
- {dblift-2.1.0 → dblift-2.2.0}/cli/_config_helpers.py +33 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/_parser_setup.py +66 -0
- dblift-2.2.0/cli/commands/__init__.py +1 -0
- dblift-2.2.0/cli/commands/config_command.py +48 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/main.py +19 -2
- {dblift-2.1.0 → dblift-2.2.0}/config/dblift_config.py +35 -50
- dblift-2.2.0/config/property_registry.py +135 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/commands/undo_command.py +28 -258
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/ui/data_collector.py +9 -15
- {dblift-2.1.0 → dblift-2.2.0}/dblift.egg-info/PKG-INFO +1 -1
- {dblift-2.1.0 → dblift-2.2.0}/dblift.egg-info/SOURCES.txt +3 -0
- {dblift-2.1.0 → dblift-2.2.0}/pyproject.toml +1 -1
- {dblift-2.1.0 → dblift-2.2.0}/LICENSE +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/README.md +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/api/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/api/_cli_support.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/api/_client_factory.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/api/_client_operations.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/api/_engine_config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/api/async_client.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/api/client.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/api/events.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/api/migrations.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/api/py.typed +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/_constants.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/_output.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/db_utils.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/extensions.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/handlers/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/handlers/_shared.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/handlers/baseline.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/handlers/clean.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/handlers/import_flyway.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/handlers/info.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/handlers/migrate.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/handlers/repair.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/handlers/undo.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/cli/handlers/validate.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/config/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/config/_credential_masking.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/config/_subclasses/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/config/_subclasses/dummy_config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/config/_url_builder_mixin.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/config/config_builder.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/config/database_config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/config/errors.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/config/secrets/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/config/secrets/_cache.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/config/secrets/_provider_base.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/config/secrets/_registry.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/config/secrets/_resolver.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/config/secrets/_secrets_config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/constants.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/dialect_boundary.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/exceptions.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/features.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/_column_enricher.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/_partition_enricher.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/_schema_orchestrator.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/_utils.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/_vendor_property_applier.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/base_introspector.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/extractors/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/extractors/base_extractor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/extractors/column_extractor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/extractors/constraint_extractor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/extractors/index_extractor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/extractors/misc_extractor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/extractors/procedure_extractor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/extractors/sequence_extractor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/extractors/table_extractor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/extractors/trigger_extractor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/extractors/view_extractor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/introspector_factory.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/result.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/schema_introspector.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/vendor_queries_base.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/vendor_queries_factory.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/vendor_queries_protocols.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/introspection/version_detector.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/_base.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/_factory.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/_formatters.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/_levels.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/_multi.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/_null.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/console.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/formatters/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/formatters/_formatter_impl.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/formatters/diff_utils.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/formatters/factory.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/formatters/formatter.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/formatters/htmlformatter.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/formatters/jsonformatter.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/log.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/logger/results.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/_type_match.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/clean_summary.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/commands/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/commands/_script_events.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/commands/base_command.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/commands/baseline_command.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/commands/clean_command.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/commands/import_flyway_command.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/commands/info_command.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/commands/migrate_command.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/commands/repair_command.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/commands/validate_command.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/encoding.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/executor/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/executor/execution_engine.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/executor/migration_executor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/executor/migration_helpers.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/executor/placeholder_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/executor/transaction_policy.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/executors/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/executors/base_executor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/executors/executor_factory.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/executors/python_executor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/executors/sql_executor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/formats/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/formats/format_detector.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/formats/migration_format.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/history/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/history/migration_history_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/journals/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/journals/migration_journal.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/migration.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/placeholders/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/placeholders/placeholder_service.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/rules/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/rules/migration_rules.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/scripting/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/scripting/migration_script_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/scripting/undo_script_generator/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/scripting/undo_script_generator/_ddl_reversers.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/scripting/undo_script_generator/_dml_reversers.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/scripting/undo_script_generator/_extractors.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/scripting/undo_script_generator/_generator.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/scripting/undo_script_generator/_helpers.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/scripting/undo_script_generator/_models.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/scripting/undo_script_generator/_reversers.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/sql/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/sql/execution_statement.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/sql/sql_analyzer.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/sql/sql_execution_service.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/sql/statement_splitter.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/state/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/state/migration_data_service.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/state/migration_display_state.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/state/migration_formatter.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/state/migration_state.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/state/migration_state_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/state/migration_state_service.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/ui/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/ui/display_formatters.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/ui/migration_analyzer.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/ui/migration_ui.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/ui/table_renderer.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/migration/version_utils.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/normalization/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/normalization/data_type_normalizer.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/normalization/dependency_resolver.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/normalization/identifier_normalizer.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/normalization/object_orderer.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/normalization/type_constants.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/normalization/type_mapper.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/normalization/type_mappings.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/normalization/type_normalizer.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/seams/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/seams/event_listeners.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/seams/introspection.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/_base_parse_result.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/_base_sql_column.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/_base_sql_constraint.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/_base_sql_object.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/_base_sql_statement.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/base.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/constraint_validator.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/database_link.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/dialect.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/event.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/extension.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/foreign_data_wrapper.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/foreign_server.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/index.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/linked_server.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/module.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/package.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/partition.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/procedure.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/sequence.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/synonym.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/table.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/table_canonicalizer.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/table_options.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/trigger.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/user_defined_type.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/view.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_model/view_options.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/_partition_handler.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/_sqlglot_builders.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/base_statement_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/base_tokenizer.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/common/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/common/base_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/dialects/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/dialects/base_config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/enhanced_regex_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/hybrid_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/parser_context.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/parser_factory.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/parser_interface.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/sqlglot_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/tokens.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_parser/unified_regex_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_validator/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_validator/_checksum_validator.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_validator/_flyway_compatibility.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_validator/_migration_filter.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_validator/_sql_syntax_validator.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_validator/_strict_mode_validator.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/sql_validator/migration_validator.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/state/sql_script_formatter.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/state/sql_statement.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/utils/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/utils/database_url_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/utils/metadata_helpers.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/utils/row_access.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/utils/string_utils.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/core/utils/url_masking.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/base_provider.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/base_quirks.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/constants.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/dml_analysis.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/error.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/error_handler.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/exceptions.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/native_connection_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/object_naming.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/base_history_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/base_locking_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/base_query_executor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/base_schema_operations.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/base_snapshot_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/base_undo_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/cosmosdb/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/cosmosdb/_sdk.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/cosmosdb/connection_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/cosmosdb/history_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/cosmosdb/locking_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/cosmosdb/query_executor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/cosmosdb/schema_operations.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/introspection/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/parser/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/parser/cosmosdb_regex_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/plugin.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/provider.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/quirks.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/sdk_translator/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/sdk_translator/_executor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/sdk_translator/_executors.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/sdk_translator/_parsing.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/sdk_translator/_script_generation.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/sdk_translator/_translator.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/cosmosdb/sdk_translator/_translators.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/db2/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/db2/config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/db2/db2/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/db2/db2/history_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/db2/db2/locking_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/db2/db2/schema_operations.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/db2/introspection/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/db2/parser/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/db2/parser/db2_regex_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/db2/parser/parser_config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/db2/plugin.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/db2/provider.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/db2/quirks.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/db2/sqlalchemy_url.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mariadb/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mariadb/plugin.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mariadb/provider.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mariadb/quirks.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/introspection/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/mysql/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/mysql/history_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/mysql/locking_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/mysql/schema_operations.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/parser/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/parser/mysql_regex_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/parser/mysql_statement_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/parser/mysql_tokenizer.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/parser/parser_config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/plugin.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/provider.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/quirks.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/mysql/sqlalchemy_url.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/introspection/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/introspection/oracle_utils.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/oracle/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/oracle/dbms_output.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/oracle/history_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/oracle/locking_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/oracle/schema_operations.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/parser/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/parser/_comments.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/parser/_object_extractor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/parser/_plsql_block.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/parser/_sqlplus.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/parser/_statement_splitter.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/parser/oracle_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/parser/oracle_statement_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/parser/oracle_tokenizer.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/parser/parser_config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/parser/sqlplus_context.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/plugin.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/provider.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/quirks.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/oracle/sqlalchemy_url.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/_provider_query_executor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/introspection/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/parser/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/parser/parser_config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/parser/postgresql_regex_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/parser/postgresql_statement_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/parser/postgresql_tokenizer.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/plugin.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/postgresql/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/postgresql/history_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/postgresql/locking_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/postgresql/schema_operations.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/provider.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/quirks.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/postgresql/sqlalchemy_url.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/introspection/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/parser/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/parser/parser_config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/parser/sqlite_regex_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/plugin.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/provider.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/quirks.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/sqlalchemy_url.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/sqlite/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/sqlite/connection_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/sqlite/history_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/sqlite/locking_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/sqlite/query_executor.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlite/sqlite/schema_operations.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/introspection/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/parser/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/parser/parser_config.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/parser/sqlserver_regex_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/parser/sqlserver_statement_parser.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/parser/sqlserver_tokenizer.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/parser/tsql_batch_separator.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/plugin.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/provider.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/quirks.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/sqlalchemy_url.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/sqlserver/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/sqlserver/history_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/sqlserver/locking_manager.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/plugins/sqlserver/sqlserver/schema_operations.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/provider_capabilities.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/provider_interfaces.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/provider_registry.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/sqlalchemy_provider.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/db/value_utils.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/dblift.egg-info/dependency_links.txt +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/dblift.egg-info/entry_points.txt +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/dblift.egg-info/requires.txt +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/dblift.egg-info/top_level.txt +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/integrations/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/integrations/django/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/integrations/django/_client.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/integrations/django/_engine.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/integrations/django/apps.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/integrations/django/checks.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/integrations/django/management/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/integrations/django/management/commands/__init__.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/integrations/django/management/commands/dblift_info.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/integrations/django/management/commands/dblift_migrate.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/integrations/django/management/commands/dblift_validate.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/integrations/fastapi.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/integrations/flask.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/integrations/opentelemetry.py +0 -0
- {dblift-2.1.0 → dblift-2.2.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dblift
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
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
|
|
@@ -43,7 +43,9 @@ if _builtin_conflicts:
|
|
|
43
43
|
_COMMAND_HANDLERS.update(_extension_handlers)
|
|
44
44
|
del _extension_handlers, _builtin_conflicts
|
|
45
45
|
|
|
46
|
-
_AVAILABLE_COMMANDS =
|
|
46
|
+
_AVAILABLE_COMMANDS = (
|
|
47
|
+
list(_COMMAND_HANDLERS.keys()) + ["db", "config"] + list(load_terminal_commands())
|
|
48
|
+
)
|
|
47
49
|
|
|
48
50
|
|
|
49
51
|
def execute_single_command(
|
|
@@ -189,12 +189,45 @@ def _build_args_namespace(
|
|
|
189
189
|
return args, unknown_args
|
|
190
190
|
|
|
191
191
|
|
|
192
|
+
# Default config filenames searched in the current working directory when no
|
|
193
|
+
# --config is given, in precedence order. Lets `dblift <command>` run without an
|
|
194
|
+
# explicit --config when a config file sits in the project root, matching the
|
|
195
|
+
# convention of peer tools (Alembic's alembic.ini, Flyway's flyway.conf).
|
|
196
|
+
_DEFAULT_CONFIG_NAMES: Tuple[str, ...] = ("dblift.yaml", "dblift.yml")
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _discover_default_config(log: Any = None) -> Optional[str]:
|
|
200
|
+
"""Return the path to a default config file in the cwd, or None.
|
|
201
|
+
|
|
202
|
+
Searches the current working directory for the filenames in
|
|
203
|
+
:data:`_DEFAULT_CONFIG_NAMES` and returns the first match. Returns ``None``
|
|
204
|
+
when no default config is present, preserving the existing behaviour for
|
|
205
|
+
pure ``--db-url`` workflows.
|
|
206
|
+
"""
|
|
207
|
+
cwd = Path.cwd()
|
|
208
|
+
for name in _DEFAULT_CONFIG_NAMES:
|
|
209
|
+
candidate = cwd / name
|
|
210
|
+
if candidate.is_file():
|
|
211
|
+
if log:
|
|
212
|
+
log.debug(f"Using discovered config file: {candidate}")
|
|
213
|
+
return str(candidate)
|
|
214
|
+
return None
|
|
215
|
+
|
|
216
|
+
|
|
192
217
|
def _load_and_merge_config(args: argparse.Namespace, log: Any) -> Any:
|
|
193
218
|
"""Load configuration and merge database overrides from CLI arguments.
|
|
194
219
|
|
|
195
220
|
Returns:
|
|
196
221
|
Loaded and merged config object
|
|
197
222
|
"""
|
|
223
|
+
# Auto-discover a config file in the cwd when the user passed neither
|
|
224
|
+
# --config nor --db-url, so `dblift <command>` works from a project that has
|
|
225
|
+
# a dblift.yaml without forcing an explicit --config on every invocation.
|
|
226
|
+
if not getattr(args, "config", None) and not getattr(args, "database_url", None):
|
|
227
|
+
discovered = _discover_default_config(log)
|
|
228
|
+
if discovered:
|
|
229
|
+
args.config = discovered
|
|
230
|
+
|
|
198
231
|
try:
|
|
199
232
|
config = load_config(args.config, args)
|
|
200
233
|
except (
|
|
@@ -106,6 +106,53 @@ def _make_history_table_parent() -> argparse.ArgumentParser:
|
|
|
106
106
|
return p
|
|
107
107
|
|
|
108
108
|
|
|
109
|
+
def _add_registry_flags(parser: argparse.ArgumentParser) -> None:
|
|
110
|
+
"""Emit a --flag for every registry property that lacks one.
|
|
111
|
+
|
|
112
|
+
Skips properties that are cli_only, cli_exempt, nested (database.*), or
|
|
113
|
+
already covered by a legacy flag recorded in cli_aliases. Ensures any NEW
|
|
114
|
+
persistent property added to the registry automatically gets a CLI flag,
|
|
115
|
+
so the CLI surface can never silently drift from config/env again.
|
|
116
|
+
"""
|
|
117
|
+
from config.property_registry import PROPERTY_REGISTRY
|
|
118
|
+
|
|
119
|
+
# Collect option strings across the WHOLE tree (root + every subparser), not
|
|
120
|
+
# just the root parser. Many registry properties (e.g. --tags,
|
|
121
|
+
# --target-version, --snapshot-table) intentionally live only on specific
|
|
122
|
+
# subcommands; a root-only ``existing`` set would treat them as missing and
|
|
123
|
+
# emit a duplicate root flag, colliding with the subparser dest. This helper
|
|
124
|
+
# therefore runs AFTER subparsers are registered so the tree walk sees them.
|
|
125
|
+
existing: set[str] = set()
|
|
126
|
+
|
|
127
|
+
def _collect(p: argparse.ArgumentParser) -> None:
|
|
128
|
+
for action in p._actions:
|
|
129
|
+
existing.update(action.option_strings)
|
|
130
|
+
choices = getattr(action, "choices", None)
|
|
131
|
+
if isinstance(choices, dict):
|
|
132
|
+
for sub in choices.values():
|
|
133
|
+
if isinstance(sub, argparse.ArgumentParser):
|
|
134
|
+
_collect(sub)
|
|
135
|
+
|
|
136
|
+
_collect(parser)
|
|
137
|
+
for spec in PROPERTY_REGISTRY:
|
|
138
|
+
if spec.cli_only or spec.cli_exempt or "." in spec.name:
|
|
139
|
+
continue
|
|
140
|
+
if spec.cli_aliases:
|
|
141
|
+
continue # legacy flag (e.g. --table, --strict) already provides the surface
|
|
142
|
+
if spec.cli in existing:
|
|
143
|
+
continue
|
|
144
|
+
if spec.type == "bool":
|
|
145
|
+
parser.add_argument(
|
|
146
|
+
spec.cli, dest=spec.name, action="store_true", default=None, help=spec.help
|
|
147
|
+
)
|
|
148
|
+
elif spec.type == "int":
|
|
149
|
+
parser.add_argument(spec.cli, dest=spec.name, type=int, default=None, help=spec.help)
|
|
150
|
+
elif spec.type == "float":
|
|
151
|
+
parser.add_argument(spec.cli, dest=spec.name, type=float, default=None, help=spec.help)
|
|
152
|
+
else:
|
|
153
|
+
parser.add_argument(spec.cli, dest=spec.name, default=None, help=spec.help)
|
|
154
|
+
|
|
155
|
+
|
|
109
156
|
def _make_snapshot_table_parent() -> argparse.ArgumentParser:
|
|
110
157
|
"""Parent parser for explicit snapshot storage commands."""
|
|
111
158
|
p = argparse.ArgumentParser(add_help=False)
|
|
@@ -307,6 +354,11 @@ def create_parser(
|
|
|
307
354
|
),
|
|
308
355
|
)
|
|
309
356
|
parser.add_argument("--dry-run", action="store_true", help="Dry run mode")
|
|
357
|
+
parser.add_argument(
|
|
358
|
+
"--installed-by",
|
|
359
|
+
dest="installed_by",
|
|
360
|
+
help="Value recorded in the installed_by column (default: database username)",
|
|
361
|
+
)
|
|
310
362
|
parser.add_argument("--log-dir", default="logs", help="Log directory")
|
|
311
363
|
parser.add_argument("--log-format", default="text", help="Log format (text, json, html)")
|
|
312
364
|
parser.add_argument(
|
|
@@ -404,7 +456,21 @@ def create_parser(
|
|
|
404
456
|
db_parser = subparsers.add_parser("db", help="Database utility commands")
|
|
405
457
|
db_subparsers = db_parser.add_subparsers(dest="db_command", required=True)
|
|
406
458
|
setup_db_utils_parser(db_subparsers)
|
|
459
|
+
# Configuration introspection: `dblift config --list` prints every persistent
|
|
460
|
+
# property and its three surfaces (config key / env var / CLI flag). Distinct
|
|
461
|
+
# from the global `--config <path>` option — a subcommand named ``config`` and
|
|
462
|
+
# an optional ``--config`` flag do not collide in argparse.
|
|
463
|
+
config_parser = subparsers.add_parser("config", help="Inspect dblift configuration")
|
|
464
|
+
config_parser.add_argument(
|
|
465
|
+
"--list",
|
|
466
|
+
action="store_true",
|
|
467
|
+
help="List all properties and how to set them (config key / env var / CLI flag)",
|
|
468
|
+
)
|
|
407
469
|
import_module("cli.extensions").load_command_extensions(parser)
|
|
470
|
+
# Emit registry-derived flags LAST, after every subparser (built-in and
|
|
471
|
+
# extension) is registered, so the tree walk in _add_registry_flags can see
|
|
472
|
+
# subcommand-only flags and skip them instead of shadowing them on the root.
|
|
473
|
+
_add_registry_flags(parser)
|
|
408
474
|
if suppress_errors:
|
|
409
475
|
all_subparsers = [
|
|
410
476
|
migrate_parser,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""First-party CLI command handlers that own their own dispatch."""
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""``dblift config --list`` — print every persistent property and its surfaces."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Dict, List
|
|
6
|
+
|
|
7
|
+
from config.property_registry import PROPERTY_REGISTRY, PropertySpec
|
|
8
|
+
from core.logger.console import render_records_table
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _cli_display(spec: PropertySpec) -> str:
|
|
12
|
+
"""The real CLI flag for a property: '(none)' if cli-exempt, the legacy
|
|
13
|
+
alias if one is registered, else the derived flag."""
|
|
14
|
+
if spec.cli_exempt:
|
|
15
|
+
return "(none)"
|
|
16
|
+
if spec.cli_aliases:
|
|
17
|
+
return str(spec.cli_aliases[0])
|
|
18
|
+
return spec.cli
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def build_property_table() -> List[Dict[str, str]]:
|
|
22
|
+
"""Return one row per registry property with its config key, env var, CLI flag, and default."""
|
|
23
|
+
rows: List[Dict[str, str]] = []
|
|
24
|
+
for spec in PROPERTY_REGISTRY:
|
|
25
|
+
rows.append(
|
|
26
|
+
{
|
|
27
|
+
"name": spec.name,
|
|
28
|
+
"config": spec.name,
|
|
29
|
+
"env": spec.env,
|
|
30
|
+
"cli": _cli_display(spec),
|
|
31
|
+
"default": "" if spec.default is None else str(spec.default),
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
return rows
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def run_config_command(args: Any) -> int:
|
|
38
|
+
"""Print the property/env/CLI surface table for ``dblift config --list``; return 0."""
|
|
39
|
+
rows = build_property_table()
|
|
40
|
+
table = render_records_table(
|
|
41
|
+
[("PROPERTY", "left"), ("ENV VAR", "left"), ("CLI FLAG", "left")],
|
|
42
|
+
[[r["name"], r["env"], r["cli"]] for r in rows],
|
|
43
|
+
title="dblift configuration properties",
|
|
44
|
+
)
|
|
45
|
+
print(
|
|
46
|
+
table
|
|
47
|
+
) # lint: allow-print config --list self-documentation (pre-CommandOutput short-circuit)
|
|
48
|
+
return 0
|
|
@@ -102,6 +102,16 @@ _GLOBAL_ONLY_ARGS: List[str] = [
|
|
|
102
102
|
"--quiet",
|
|
103
103
|
"-q",
|
|
104
104
|
"--no-progress",
|
|
105
|
+
# Root-only value flags surfaced from the PropertySpec registry
|
|
106
|
+
# (installed_by is added directly; max_snapshots is generated by
|
|
107
|
+
# _add_registry_flags). They live only on the root parser, so — like the
|
|
108
|
+
# other root-only value flags above — they must be classified global or the
|
|
109
|
+
# argv preprocessor relocates them past the subcommand token and the
|
|
110
|
+
# subparser rejects them as "unrecognized arguments". Covered by
|
|
111
|
+
# tests/unit/cli/test_global_only_args_completeness.py.
|
|
112
|
+
"--installed-by",
|
|
113
|
+
"--max-snapshots",
|
|
114
|
+
"--snapshot-table",
|
|
105
115
|
]
|
|
106
116
|
|
|
107
117
|
# Tool-level flag aliases for subcommands that take their own version-like
|
|
@@ -227,6 +237,15 @@ def _parse_argv_and_load_config(argv: List[str]) -> _CliContext:
|
|
|
227
237
|
if not commands and hasattr(args, "command"):
|
|
228
238
|
commands = [args.command]
|
|
229
239
|
|
|
240
|
+
# `dblift config --list` is offline self-documentation: it reads only the
|
|
241
|
+
# property registry, so it short-circuits here — before any config/db load —
|
|
242
|
+
# exactly like the `db` subcommand path below. Listing is the command's only
|
|
243
|
+
# behaviour today, so it runs whether or not --list was passed.
|
|
244
|
+
if commands and commands[0] == "config":
|
|
245
|
+
from cli.commands.config_command import run_config_command
|
|
246
|
+
|
|
247
|
+
sys.exit(run_config_command(args))
|
|
248
|
+
|
|
230
249
|
log = LogFactory.get_log("Dblift")
|
|
231
250
|
parser = create_parser()
|
|
232
251
|
# Validate log format before any config load so bogus --log-format fails with argparse
|
|
@@ -316,7 +335,6 @@ def _dispatch_command(ctx: _CliContext, command_output: CommandOutput) -> int:
|
|
|
316
335
|
ctx.log.debug(f"Using placeholders: {placeholders}")
|
|
317
336
|
|
|
318
337
|
ctx.config.journal_enabled = True
|
|
319
|
-
ctx.config.journal_dir = None
|
|
320
338
|
if getattr(ctx.args, "strict", False):
|
|
321
339
|
ctx.config.strict_mode = True
|
|
322
340
|
ctx.log.info(
|
|
@@ -382,7 +400,6 @@ def _dispatch_command(ctx: _CliContext, command_output: CommandOutput) -> int:
|
|
|
382
400
|
recursive=recursive,
|
|
383
401
|
placeholders=placeholders,
|
|
384
402
|
dir_recursive_map=dir_recursive_map,
|
|
385
|
-
license_tier=_resolve_license_tier(ctx.args),
|
|
386
403
|
)
|
|
387
404
|
if not success:
|
|
388
405
|
any_command_failed = True
|
|
@@ -285,7 +285,6 @@ class DbliftConfig:
|
|
|
285
285
|
1 # Maximum number of snapshots to keep (oldest are deleted when limit exceeded)
|
|
286
286
|
)
|
|
287
287
|
journal_enabled: bool = True
|
|
288
|
-
journal_dir: Optional[str] = None
|
|
289
288
|
|
|
290
289
|
# Error handling and retry configuration
|
|
291
290
|
error_handling_enabled: bool = True
|
|
@@ -572,8 +571,8 @@ class DbliftConfig:
|
|
|
572
571
|
migrations_directories = migrations.get("directories", [])
|
|
573
572
|
migrations_recursive = migrations.get("recursive", True)
|
|
574
573
|
|
|
575
|
-
# Journal settings are always in-memory only
|
|
576
|
-
# journal_enabled defaults to True
|
|
574
|
+
# Journal settings are always in-memory only
|
|
575
|
+
# journal_enabled defaults to True
|
|
577
576
|
config = cls(
|
|
578
577
|
database=database_config,
|
|
579
578
|
migrations=MigrationsConfig(
|
|
@@ -614,8 +613,6 @@ class DbliftConfig:
|
|
|
614
613
|
log_level=data.get("log_level"),
|
|
615
614
|
secrets=secrets_config,
|
|
616
615
|
)
|
|
617
|
-
# Explicitly ensure journal_dir is None (journal is always in-memory only)
|
|
618
|
-
config.journal_dir = None
|
|
619
616
|
config.log_dir = root_log_dir
|
|
620
617
|
return config
|
|
621
618
|
|
|
@@ -699,7 +696,11 @@ class DbliftConfig:
|
|
|
699
696
|
# cannot pollute or shadow legitimate config fields.
|
|
700
697
|
#
|
|
701
698
|
# Names whose env-var suffix differs from the config field name
|
|
702
|
-
_DB_ALIASES: Dict[str, str] = {
|
|
699
|
+
_DB_ALIASES: Dict[str, str] = {
|
|
700
|
+
"USER": "username",
|
|
701
|
+
"USERNAME": "username",
|
|
702
|
+
"SESSION_VARS": "session_variables",
|
|
703
|
+
}
|
|
703
704
|
# Suffixes that require structured (JSON / k=v CSV) parsing into a dict
|
|
704
705
|
_STRUCTURED = {"OPTIONS", "SESSION_VARS", "EXTRA_PARAMS", "PROPERTIES"}
|
|
705
706
|
# Suffixes whose value must be coerced to int
|
|
@@ -719,6 +720,7 @@ class DbliftConfig:
|
|
|
719
720
|
| {
|
|
720
721
|
"URL",
|
|
721
722
|
"USER",
|
|
723
|
+
"USERNAME",
|
|
722
724
|
"PASSWORD",
|
|
723
725
|
"SCHEMA",
|
|
724
726
|
"HOST",
|
|
@@ -776,19 +778,23 @@ class DbliftConfig:
|
|
|
776
778
|
config: Dict[str, Any] = {}
|
|
777
779
|
if db:
|
|
778
780
|
config["database"] = db
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
781
|
+
|
|
782
|
+
from config.property_registry import PROPERTY_REGISTRY
|
|
783
|
+
|
|
784
|
+
for spec in PROPERTY_REGISTRY:
|
|
785
|
+
if spec.cli_only or "." in spec.name:
|
|
786
|
+
continue # nested database.* fields are handled by the DBLIFT_DB_* loop above
|
|
787
|
+
raw = env.get(spec.env)
|
|
788
|
+
if not raw:
|
|
789
|
+
continue
|
|
790
|
+
if spec.coerce is not None:
|
|
791
|
+
try:
|
|
792
|
+
config[spec.name] = spec.coerce(raw)
|
|
793
|
+
except (ValueError, TypeError):
|
|
794
|
+
if diagnostics is not None:
|
|
795
|
+
diagnostics.invalid_int_vars.append(spec.env)
|
|
796
|
+
else:
|
|
797
|
+
config[spec.name] = raw
|
|
792
798
|
return config
|
|
793
799
|
|
|
794
800
|
@classmethod
|
|
@@ -849,34 +855,16 @@ class DbliftConfig:
|
|
|
849
855
|
if db_cfg:
|
|
850
856
|
config["database"] = db_cfg
|
|
851
857
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
"
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
"strict_mode",
|
|
863
|
-
"clean_disabled",
|
|
864
|
-
"journal_enabled",
|
|
865
|
-
"error_handling_enabled",
|
|
866
|
-
"max_retries",
|
|
867
|
-
"retry_delay",
|
|
868
|
-
"retry_backoff",
|
|
869
|
-
"retry_jitter",
|
|
870
|
-
"retryable_error_categories",
|
|
871
|
-
"tags",
|
|
872
|
-
"exclude_tags",
|
|
873
|
-
"versions",
|
|
874
|
-
"exclude_versions",
|
|
875
|
-
"log_file",
|
|
876
|
-
"log_dir",
|
|
877
|
-
"log_format",
|
|
878
|
-
"log_level",
|
|
879
|
-
):
|
|
858
|
+
from config.property_registry import PROPERTY_REGISTRY
|
|
859
|
+
|
|
860
|
+
# Registry covers the persistent scalar properties; these three are
|
|
861
|
+
# arg-only keys not modeled in the registry (undo is subcommand-driven,
|
|
862
|
+
# journal_enabled/retryable_error_categories are non-scalar/internal).
|
|
863
|
+
_arg_only_keys = ("undo", "journal_enabled", "retryable_error_categories")
|
|
864
|
+
registry_keys = [
|
|
865
|
+
spec.name for spec in PROPERTY_REGISTRY if not spec.cli_only and "." not in spec.name
|
|
866
|
+
]
|
|
867
|
+
for key in (*registry_keys, *_arg_only_keys):
|
|
880
868
|
if key in args and args[key] not in (None, ""):
|
|
881
869
|
config[key] = args[key]
|
|
882
870
|
|
|
@@ -1019,9 +1007,6 @@ class DbliftConfig:
|
|
|
1019
1007
|
if self.placeholders:
|
|
1020
1008
|
result["placeholders"] = self.placeholders
|
|
1021
1009
|
|
|
1022
|
-
if self.journal_dir:
|
|
1023
|
-
result["journal_dir"] = self.journal_dir
|
|
1024
|
-
|
|
1025
1010
|
if self.log_dir:
|
|
1026
1011
|
result["log_dir"] = self.log_dir
|
|
1027
1012
|
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""Single source of truth for every persistent dblift property.
|
|
2
|
+
|
|
3
|
+
Each :class:`PropertySpec` mechanically derives its environment variable and
|
|
4
|
+
CLI flag from its dotted config name, so a property can never be added to one
|
|
5
|
+
surface and silently missing from another. See
|
|
6
|
+
``tests/unit/config/test_property_parity.py`` (added in a later task) for the
|
|
7
|
+
invariant that enforces this across ``from_env_dict`` / ``from_args_dict`` /
|
|
8
|
+
``to_dict`` / the CLI parser.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from dataclasses import dataclass
|
|
14
|
+
from typing import Callable, List, Optional
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def env_name(name: str) -> str:
|
|
18
|
+
"""Derive the env var: ``database.username`` -> ``DBLIFT_DB_USERNAME``."""
|
|
19
|
+
if name.startswith("database."):
|
|
20
|
+
name = "db_" + name[len("database.") :]
|
|
21
|
+
return "DBLIFT_" + name.replace(".", "_").upper()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def cli_flag(name: str) -> str:
|
|
25
|
+
"""Derive the CLI flag: ``database.username`` -> ``--db-username``."""
|
|
26
|
+
if name.startswith("database."):
|
|
27
|
+
name = "db_" + name[len("database.") :]
|
|
28
|
+
return "--" + name.replace(".", "_").replace("_", "-")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True)
|
|
32
|
+
class PropertySpec:
|
|
33
|
+
name: str # dotted config key; "database.<field>" for nested db config
|
|
34
|
+
type: str # "str" | "int" | "float" | "bool" | "dict" | "list"
|
|
35
|
+
default: object = None
|
|
36
|
+
cli_only: bool = False # runtime meta-flags (version/quiet/...) — no env/config
|
|
37
|
+
cli_exempt: bool = False # has env+config but intentionally no CLI flag
|
|
38
|
+
cli_aliases: tuple = () # legacy flag names that already provide this CLI surface
|
|
39
|
+
coerce: Optional[Callable[[str], object]] = None
|
|
40
|
+
help: str = ""
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def env(self) -> str:
|
|
44
|
+
return env_name(self.name)
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def cli(self) -> str:
|
|
48
|
+
return cli_flag(self.name)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _bool(v: str) -> bool:
|
|
52
|
+
return v.lower() in ("1", "true", "yes")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# NOTE: keep this list the ONLY place persistent properties are declared.
|
|
56
|
+
# Structured db fields (extra_params, properties, options, session_variables)
|
|
57
|
+
# and CosmosDB-specific fields keep their existing bespoke env/arg parsing and
|
|
58
|
+
# are intentionally EXCLUDED here.
|
|
59
|
+
PROPERTY_REGISTRY: List[PropertySpec] = [
|
|
60
|
+
# --- dblift-managed tables ---
|
|
61
|
+
PropertySpec(
|
|
62
|
+
"history_table",
|
|
63
|
+
"str",
|
|
64
|
+
"dblift_schema_history",
|
|
65
|
+
cli_aliases=("--table",),
|
|
66
|
+
help="dblift schema-history table name",
|
|
67
|
+
),
|
|
68
|
+
PropertySpec(
|
|
69
|
+
"snapshot_table",
|
|
70
|
+
"str",
|
|
71
|
+
"dblift_schema_snapshots",
|
|
72
|
+
help="dblift schema-snapshots table name",
|
|
73
|
+
),
|
|
74
|
+
PropertySpec("max_snapshots", "int", 1, coerce=int, help="Max snapshots to retain"),
|
|
75
|
+
# --- audit / execution ---
|
|
76
|
+
PropertySpec(
|
|
77
|
+
"installed_by",
|
|
78
|
+
"str",
|
|
79
|
+
None,
|
|
80
|
+
help="Value recorded in the installed_by column (default: db username)",
|
|
81
|
+
),
|
|
82
|
+
PropertySpec("baseline_version", "str", None),
|
|
83
|
+
PropertySpec("target_version", "str", None),
|
|
84
|
+
PropertySpec("mark_as_executed", "bool", False, coerce=_bool),
|
|
85
|
+
PropertySpec("strict_mode", "bool", False, coerce=_bool, cli_aliases=("--strict",)),
|
|
86
|
+
PropertySpec("clean_disabled", "bool", True, coerce=_bool),
|
|
87
|
+
PropertySpec("dry_run", "bool", False, coerce=_bool),
|
|
88
|
+
# --- migration selection ---
|
|
89
|
+
PropertySpec("tags", "str", None),
|
|
90
|
+
PropertySpec("exclude_tags", "str", None),
|
|
91
|
+
PropertySpec("versions", "str", None),
|
|
92
|
+
PropertySpec("exclude_versions", "str", None),
|
|
93
|
+
# --- retry / error handling (config+env, no CLI flag) ---
|
|
94
|
+
PropertySpec("error_handling_enabled", "bool", True, coerce=_bool, cli_exempt=True),
|
|
95
|
+
PropertySpec("max_retries", "int", 3, coerce=int, cli_exempt=True),
|
|
96
|
+
PropertySpec("retry_delay", "float", 1.0, coerce=float, cli_exempt=True),
|
|
97
|
+
PropertySpec("retry_backoff", "float", 2.0, coerce=float, cli_exempt=True),
|
|
98
|
+
PropertySpec("retry_jitter", "float", 0.2, coerce=float, cli_exempt=True),
|
|
99
|
+
# --- logging ---
|
|
100
|
+
PropertySpec("log_level", "str", None),
|
|
101
|
+
PropertySpec("log_format", "str", None),
|
|
102
|
+
PropertySpec("log_file", "str", None),
|
|
103
|
+
PropertySpec("log_dir", "str", None),
|
|
104
|
+
# --- database connection (nested under database.*) ---
|
|
105
|
+
# NOTE: the env/args generators skip dotted (database.*) names. These fields
|
|
106
|
+
# are read by the pre-existing DBLIFT_DB_* machinery in DbliftConfig
|
|
107
|
+
# (_DB_ALIASES / _ALLOWED), which also handles the structured/aliased/CosmosDB
|
|
108
|
+
# cases the registry does not model. Listing them here is NOT redundant: the
|
|
109
|
+
# parity tests validate each one's surfaces, so adding a new database.* field
|
|
110
|
+
# without a corresponding DBLIFT_DB_* allowlist entry fails CI loudly rather
|
|
111
|
+
# than silently dropping the surface. Drift is detected, not eliminated, for
|
|
112
|
+
# these fields.
|
|
113
|
+
PropertySpec("database.url", "str", ""),
|
|
114
|
+
PropertySpec("database.type", "str", None, cli_exempt=True),
|
|
115
|
+
PropertySpec("database.username", "str", ""),
|
|
116
|
+
PropertySpec("database.password", "str", ""),
|
|
117
|
+
PropertySpec("database.schema", "str", ""),
|
|
118
|
+
PropertySpec("database.host", "str", None, cli_exempt=True),
|
|
119
|
+
PropertySpec("database.port", "int", None, coerce=int, cli_exempt=True),
|
|
120
|
+
PropertySpec("database.database", "str", None, cli_exempt=True),
|
|
121
|
+
PropertySpec("database.connection_timeout", "int", 30, coerce=int, cli_exempt=True),
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def spec_for(name: str) -> Optional[PropertySpec]:
|
|
126
|
+
"""Return the :class:`PropertySpec` for ``name``, or ``None`` if unknown.
|
|
127
|
+
|
|
128
|
+
Runtime-only meta flags (``--version``, ``--quiet``, ``--config`` …) are not
|
|
129
|
+
persistent properties and are intentionally absent from the registry, so
|
|
130
|
+
``spec_for("version")`` returns ``None`` by design.
|
|
131
|
+
"""
|
|
132
|
+
for spec in PROPERTY_REGISTRY:
|
|
133
|
+
if spec.name == name:
|
|
134
|
+
return spec
|
|
135
|
+
return None
|