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.
Files changed (413) hide show
  1. {dblift-2.0.3 → dblift-2.0.4}/PKG-INFO +26 -23
  2. {dblift-2.0.3 → dblift-2.0.4}/README.md +24 -22
  3. {dblift-2.0.3 → dblift-2.0.4}/api/client.py +1 -2
  4. {dblift-2.0.3 → dblift-2.0.4}/cli/_command_handlers.py +0 -1
  5. {dblift-2.0.3 → dblift-2.0.4}/cli/_config_helpers.py +9 -18
  6. {dblift-2.0.3 → dblift-2.0.4}/cli/_constants.py +0 -9
  7. {dblift-2.0.3 → dblift-2.0.4}/cli/_output.py +1 -2
  8. {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/_shared.py +4 -15
  9. {dblift-2.0.3 → dblift-2.0.4}/cli/main.py +3 -30
  10. {dblift-2.0.3 → dblift-2.0.4}/config/dblift_config.py +4 -80
  11. {dblift-2.0.3 → dblift-2.0.4}/core/logger/__init__.py +0 -4
  12. {dblift-2.0.3 → dblift-2.0.4}/core/logger/console.py +1 -1
  13. {dblift-2.0.3 → dblift-2.0.4}/core/logger/formatters/_formatter_impl.py +1 -83
  14. {dblift-2.0.3 → dblift-2.0.4}/core/logger/formatters/htmlformatter.py +1 -270
  15. {dblift-2.0.3 → dblift-2.0.4}/core/logger/formatters/jsonformatter.py +0 -298
  16. {dblift-2.0.3 → dblift-2.0.4}/core/logger/results.py +0 -395
  17. {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/base_command.py +2 -2
  18. {dblift-2.0.3 → dblift-2.0.4}/core/sql_validator/migration_validator.py +2 -2
  19. {dblift-2.0.3 → dblift-2.0.4}/db/base_quirks.py +0 -6
  20. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/quirks.py +0 -1
  21. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/quirks.py +0 -1
  22. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/quirks.py +0 -1
  23. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/quirks.py +0 -1
  24. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/quirks.py +0 -1
  25. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/quirks.py +0 -1
  26. {dblift-2.0.3 → dblift-2.0.4}/dblift.egg-info/PKG-INFO +26 -23
  27. {dblift-2.0.3 → dblift-2.0.4}/dblift.egg-info/SOURCES.txt +0 -5
  28. {dblift-2.0.3 → dblift-2.0.4}/dblift.egg-info/requires.txt +1 -0
  29. {dblift-2.0.3 → dblift-2.0.4}/pyproject.toml +2 -1
  30. dblift-2.0.3/config/validation_config.py +0 -124
  31. dblift-2.0.3/core/logger/formatters/_format_diff_meta.py +0 -117
  32. dblift-2.0.3/core/logger/formatters/_format_diff_object.py +0 -195
  33. dblift-2.0.3/core/logger/formatters/_format_diff_routine.py +0 -208
  34. dblift-2.0.3/core/logger/formatters/_format_diff_table.py +0 -250
  35. {dblift-2.0.3 → dblift-2.0.4}/LICENSE +0 -0
  36. {dblift-2.0.3 → dblift-2.0.4}/api/__init__.py +0 -0
  37. {dblift-2.0.3 → dblift-2.0.4}/api/_cli_support.py +0 -0
  38. {dblift-2.0.3 → dblift-2.0.4}/api/_client_factory.py +0 -0
  39. {dblift-2.0.3 → dblift-2.0.4}/api/_client_operations.py +0 -0
  40. {dblift-2.0.3 → dblift-2.0.4}/api/_engine_config.py +0 -0
  41. {dblift-2.0.3 → dblift-2.0.4}/api/async_client.py +0 -0
  42. {dblift-2.0.3 → dblift-2.0.4}/api/events.py +0 -0
  43. {dblift-2.0.3 → dblift-2.0.4}/api/migrations.py +0 -0
  44. {dblift-2.0.3 → dblift-2.0.4}/api/py.typed +0 -0
  45. {dblift-2.0.3 → dblift-2.0.4}/cli/__init__.py +0 -0
  46. {dblift-2.0.3 → dblift-2.0.4}/cli/_parser_setup.py +0 -0
  47. {dblift-2.0.3 → dblift-2.0.4}/cli/db_utils.py +0 -0
  48. {dblift-2.0.3 → dblift-2.0.4}/cli/extensions.py +0 -0
  49. {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/__init__.py +0 -0
  50. {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/baseline.py +0 -0
  51. {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/clean.py +0 -0
  52. {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/import_flyway.py +0 -0
  53. {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/info.py +0 -0
  54. {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/migrate.py +0 -0
  55. {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/repair.py +0 -0
  56. {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/undo.py +0 -0
  57. {dblift-2.0.3 → dblift-2.0.4}/cli/handlers/validate.py +0 -0
  58. {dblift-2.0.3 → dblift-2.0.4}/config/__init__.py +0 -0
  59. {dblift-2.0.3 → dblift-2.0.4}/config/_credential_masking.py +0 -0
  60. {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/__init__.py +0 -0
  61. {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/cosmosdb_config.py +0 -0
  62. {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/db2_config.py +0 -0
  63. {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/dummy_config.py +0 -0
  64. {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/mysql_config.py +0 -0
  65. {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/oracle_config.py +0 -0
  66. {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/postgresql_config.py +0 -0
  67. {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/sqlite_config.py +0 -0
  68. {dblift-2.0.3 → dblift-2.0.4}/config/_subclasses/sqlserver_config.py +0 -0
  69. {dblift-2.0.3 → dblift-2.0.4}/config/_url_builder_mixin.py +0 -0
  70. {dblift-2.0.3 → dblift-2.0.4}/config/config_builder.py +0 -0
  71. {dblift-2.0.3 → dblift-2.0.4}/config/database_config.py +0 -0
  72. {dblift-2.0.3 → dblift-2.0.4}/config/errors.py +0 -0
  73. {dblift-2.0.3 → dblift-2.0.4}/config/secrets/__init__.py +0 -0
  74. {dblift-2.0.3 → dblift-2.0.4}/config/secrets/_cache.py +0 -0
  75. {dblift-2.0.3 → dblift-2.0.4}/config/secrets/_provider_base.py +0 -0
  76. {dblift-2.0.3 → dblift-2.0.4}/config/secrets/_registry.py +0 -0
  77. {dblift-2.0.3 → dblift-2.0.4}/config/secrets/_resolver.py +0 -0
  78. {dblift-2.0.3 → dblift-2.0.4}/config/secrets/_secrets_config.py +0 -0
  79. {dblift-2.0.3 → dblift-2.0.4}/core/__init__.py +0 -0
  80. {dblift-2.0.3 → dblift-2.0.4}/core/constants.py +0 -0
  81. {dblift-2.0.3 → dblift-2.0.4}/core/dialect_boundary.py +0 -0
  82. {dblift-2.0.3 → dblift-2.0.4}/core/exceptions.py +0 -0
  83. {dblift-2.0.3 → dblift-2.0.4}/core/features.py +0 -0
  84. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/__init__.py +0 -0
  85. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/_column_enricher.py +0 -0
  86. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/_partition_enricher.py +0 -0
  87. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/_schema_orchestrator.py +0 -0
  88. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/_utils.py +0 -0
  89. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/_vendor_property_applier.py +0 -0
  90. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/base_introspector.py +0 -0
  91. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/capability_matrix.py +0 -0
  92. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/__init__.py +0 -0
  93. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/base_extractor.py +0 -0
  94. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/column_extractor.py +0 -0
  95. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/constraint_extractor.py +0 -0
  96. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/index_extractor.py +0 -0
  97. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/misc_extractor.py +0 -0
  98. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/procedure_extractor.py +0 -0
  99. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/sequence_extractor.py +0 -0
  100. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/table_extractor.py +0 -0
  101. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/trigger_extractor.py +0 -0
  102. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/extractors/view_extractor.py +0 -0
  103. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/introspector_factory.py +0 -0
  104. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/result.py +0 -0
  105. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/schema_introspector.py +0 -0
  106. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/vendor_queries_base.py +0 -0
  107. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/vendor_queries_factory.py +0 -0
  108. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/vendor_queries_protocols.py +0 -0
  109. {dblift-2.0.3 → dblift-2.0.4}/core/introspection/version_detector.py +0 -0
  110. {dblift-2.0.3 → dblift-2.0.4}/core/logger/_base.py +0 -0
  111. {dblift-2.0.3 → dblift-2.0.4}/core/logger/_factory.py +0 -0
  112. {dblift-2.0.3 → dblift-2.0.4}/core/logger/_formatters.py +0 -0
  113. {dblift-2.0.3 → dblift-2.0.4}/core/logger/_levels.py +0 -0
  114. {dblift-2.0.3 → dblift-2.0.4}/core/logger/_multi.py +0 -0
  115. {dblift-2.0.3 → dblift-2.0.4}/core/logger/_null.py +0 -0
  116. {dblift-2.0.3 → dblift-2.0.4}/core/logger/formatters/__init__.py +0 -0
  117. {dblift-2.0.3 → dblift-2.0.4}/core/logger/formatters/diff_utils.py +0 -0
  118. {dblift-2.0.3 → dblift-2.0.4}/core/logger/formatters/factory.py +0 -0
  119. {dblift-2.0.3 → dblift-2.0.4}/core/logger/formatters/formatter.py +0 -0
  120. {dblift-2.0.3 → dblift-2.0.4}/core/logger/log.py +0 -0
  121. {dblift-2.0.3 → dblift-2.0.4}/core/migration/__init__.py +0 -0
  122. {dblift-2.0.3 → dblift-2.0.4}/core/migration/_type_match.py +0 -0
  123. {dblift-2.0.3 → dblift-2.0.4}/core/migration/clean_summary.py +0 -0
  124. {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/__init__.py +0 -0
  125. {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/_script_events.py +0 -0
  126. {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/baseline_command.py +0 -0
  127. {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/clean_command.py +0 -0
  128. {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/import_flyway_command.py +0 -0
  129. {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/info_command.py +0 -0
  130. {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/migrate_command.py +0 -0
  131. {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/repair_command.py +0 -0
  132. {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/undo_command.py +0 -0
  133. {dblift-2.0.3 → dblift-2.0.4}/core/migration/commands/validate_command.py +0 -0
  134. {dblift-2.0.3 → dblift-2.0.4}/core/migration/encoding.py +0 -0
  135. {dblift-2.0.3 → dblift-2.0.4}/core/migration/executor/__init__.py +0 -0
  136. {dblift-2.0.3 → dblift-2.0.4}/core/migration/executor/execution_engine.py +0 -0
  137. {dblift-2.0.3 → dblift-2.0.4}/core/migration/executor/migration_executor.py +0 -0
  138. {dblift-2.0.3 → dblift-2.0.4}/core/migration/executor/migration_helpers.py +0 -0
  139. {dblift-2.0.3 → dblift-2.0.4}/core/migration/executor/placeholder_manager.py +0 -0
  140. {dblift-2.0.3 → dblift-2.0.4}/core/migration/executor/transaction_policy.py +0 -0
  141. {dblift-2.0.3 → dblift-2.0.4}/core/migration/executors/__init__.py +0 -0
  142. {dblift-2.0.3 → dblift-2.0.4}/core/migration/executors/base_executor.py +0 -0
  143. {dblift-2.0.3 → dblift-2.0.4}/core/migration/executors/executor_factory.py +0 -0
  144. {dblift-2.0.3 → dblift-2.0.4}/core/migration/executors/python_executor.py +0 -0
  145. {dblift-2.0.3 → dblift-2.0.4}/core/migration/executors/sql_executor.py +0 -0
  146. {dblift-2.0.3 → dblift-2.0.4}/core/migration/formats/__init__.py +0 -0
  147. {dblift-2.0.3 → dblift-2.0.4}/core/migration/formats/format_detector.py +0 -0
  148. {dblift-2.0.3 → dblift-2.0.4}/core/migration/formats/migration_format.py +0 -0
  149. {dblift-2.0.3 → dblift-2.0.4}/core/migration/history/__init__.py +0 -0
  150. {dblift-2.0.3 → dblift-2.0.4}/core/migration/history/migration_history_manager.py +0 -0
  151. {dblift-2.0.3 → dblift-2.0.4}/core/migration/journals/__init__.py +0 -0
  152. {dblift-2.0.3 → dblift-2.0.4}/core/migration/journals/migration_journal.py +0 -0
  153. {dblift-2.0.3 → dblift-2.0.4}/core/migration/migration.py +0 -0
  154. {dblift-2.0.3 → dblift-2.0.4}/core/migration/placeholders/__init__.py +0 -0
  155. {dblift-2.0.3 → dblift-2.0.4}/core/migration/placeholders/placeholder_service.py +0 -0
  156. {dblift-2.0.3 → dblift-2.0.4}/core/migration/rules/__init__.py +0 -0
  157. {dblift-2.0.3 → dblift-2.0.4}/core/migration/rules/migration_rules.py +0 -0
  158. {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/__init__.py +0 -0
  159. {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/migration_script_manager.py +0 -0
  160. {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/__init__.py +0 -0
  161. {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/_ddl_reversers.py +0 -0
  162. {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/_dml_reversers.py +0 -0
  163. {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/_extractors.py +0 -0
  164. {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/_generator.py +0 -0
  165. {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/_helpers.py +0 -0
  166. {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/_models.py +0 -0
  167. {dblift-2.0.3 → dblift-2.0.4}/core/migration/scripting/undo_script_generator/_reversers.py +0 -0
  168. {dblift-2.0.3 → dblift-2.0.4}/core/migration/sql/__init__.py +0 -0
  169. {dblift-2.0.3 → dblift-2.0.4}/core/migration/sql/execution_statement.py +0 -0
  170. {dblift-2.0.3 → dblift-2.0.4}/core/migration/sql/sql_analyzer.py +0 -0
  171. {dblift-2.0.3 → dblift-2.0.4}/core/migration/sql/sql_execution_service.py +0 -0
  172. {dblift-2.0.3 → dblift-2.0.4}/core/migration/sql/statement_splitter.py +0 -0
  173. {dblift-2.0.3 → dblift-2.0.4}/core/migration/state/__init__.py +0 -0
  174. {dblift-2.0.3 → dblift-2.0.4}/core/migration/state/migration_data_service.py +0 -0
  175. {dblift-2.0.3 → dblift-2.0.4}/core/migration/state/migration_display_state.py +0 -0
  176. {dblift-2.0.3 → dblift-2.0.4}/core/migration/state/migration_formatter.py +0 -0
  177. {dblift-2.0.3 → dblift-2.0.4}/core/migration/state/migration_state.py +0 -0
  178. {dblift-2.0.3 → dblift-2.0.4}/core/migration/state/migration_state_manager.py +0 -0
  179. {dblift-2.0.3 → dblift-2.0.4}/core/migration/state/migration_state_service.py +0 -0
  180. {dblift-2.0.3 → dblift-2.0.4}/core/migration/ui/__init__.py +0 -0
  181. {dblift-2.0.3 → dblift-2.0.4}/core/migration/ui/data_collector.py +0 -0
  182. {dblift-2.0.3 → dblift-2.0.4}/core/migration/ui/display_formatters.py +0 -0
  183. {dblift-2.0.3 → dblift-2.0.4}/core/migration/ui/migration_analyzer.py +0 -0
  184. {dblift-2.0.3 → dblift-2.0.4}/core/migration/ui/migration_ui.py +0 -0
  185. {dblift-2.0.3 → dblift-2.0.4}/core/migration/ui/table_renderer.py +0 -0
  186. {dblift-2.0.3 → dblift-2.0.4}/core/migration/version_utils.py +0 -0
  187. {dblift-2.0.3 → dblift-2.0.4}/core/normalization/__init__.py +0 -0
  188. {dblift-2.0.3 → dblift-2.0.4}/core/normalization/data_type_normalizer.py +0 -0
  189. {dblift-2.0.3 → dblift-2.0.4}/core/normalization/dependency_resolver.py +0 -0
  190. {dblift-2.0.3 → dblift-2.0.4}/core/normalization/identifier_normalizer.py +0 -0
  191. {dblift-2.0.3 → dblift-2.0.4}/core/normalization/object_orderer.py +0 -0
  192. {dblift-2.0.3 → dblift-2.0.4}/core/normalization/type_constants.py +0 -0
  193. {dblift-2.0.3 → dblift-2.0.4}/core/normalization/type_mapper.py +0 -0
  194. {dblift-2.0.3 → dblift-2.0.4}/core/normalization/type_mappings.py +0 -0
  195. {dblift-2.0.3 → dblift-2.0.4}/core/normalization/type_normalizer.py +0 -0
  196. {dblift-2.0.3 → dblift-2.0.4}/core/seams/__init__.py +0 -0
  197. {dblift-2.0.3 → dblift-2.0.4}/core/seams/event_listeners.py +0 -0
  198. {dblift-2.0.3 → dblift-2.0.4}/core/seams/introspection.py +0 -0
  199. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/__init__.py +0 -0
  200. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/_base_parse_result.py +0 -0
  201. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/_base_sql_column.py +0 -0
  202. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/_base_sql_constraint.py +0 -0
  203. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/_base_sql_object.py +0 -0
  204. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/_base_sql_statement.py +0 -0
  205. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/base.py +0 -0
  206. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/constraint_validator.py +0 -0
  207. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/database_link.py +0 -0
  208. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/dialect.py +0 -0
  209. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/event.py +0 -0
  210. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/extension.py +0 -0
  211. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/foreign_data_wrapper.py +0 -0
  212. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/foreign_server.py +0 -0
  213. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/index.py +0 -0
  214. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/linked_server.py +0 -0
  215. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/module.py +0 -0
  216. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/package.py +0 -0
  217. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/partition.py +0 -0
  218. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/procedure.py +0 -0
  219. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/sequence.py +0 -0
  220. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/synonym.py +0 -0
  221. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/table.py +0 -0
  222. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/table_canonicalizer.py +0 -0
  223. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/table_options.py +0 -0
  224. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/trigger.py +0 -0
  225. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/user_defined_type.py +0 -0
  226. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/view.py +0 -0
  227. {dblift-2.0.3 → dblift-2.0.4}/core/sql_model/view_options.py +0 -0
  228. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/__init__.py +0 -0
  229. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/_partition_handler.py +0 -0
  230. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/_sqlglot_builders.py +0 -0
  231. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/base_statement_parser.py +0 -0
  232. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/base_tokenizer.py +0 -0
  233. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/common/__init__.py +0 -0
  234. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/common/base_parser.py +0 -0
  235. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/dialects/__init__.py +0 -0
  236. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/dialects/base_config.py +0 -0
  237. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/enhanced_regex_parser.py +0 -0
  238. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/hybrid_parser.py +0 -0
  239. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/parser_context.py +0 -0
  240. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/parser_factory.py +0 -0
  241. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/parser_interface.py +0 -0
  242. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/sqlglot_parser.py +0 -0
  243. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/tokens.py +0 -0
  244. {dblift-2.0.3 → dblift-2.0.4}/core/sql_parser/unified_regex_parser.py +0 -0
  245. {dblift-2.0.3 → dblift-2.0.4}/core/sql_validator/__init__.py +0 -0
  246. {dblift-2.0.3 → dblift-2.0.4}/core/sql_validator/_checksum_validator.py +0 -0
  247. {dblift-2.0.3 → dblift-2.0.4}/core/sql_validator/_flyway_compatibility.py +0 -0
  248. {dblift-2.0.3 → dblift-2.0.4}/core/sql_validator/_migration_filter.py +0 -0
  249. {dblift-2.0.3 → dblift-2.0.4}/core/sql_validator/_sql_syntax_validator.py +0 -0
  250. {dblift-2.0.3 → dblift-2.0.4}/core/sql_validator/_strict_mode_validator.py +0 -0
  251. {dblift-2.0.3 → dblift-2.0.4}/core/state/sql_script_formatter.py +0 -0
  252. {dblift-2.0.3 → dblift-2.0.4}/core/state/sql_statement.py +0 -0
  253. {dblift-2.0.3 → dblift-2.0.4}/core/utils/__init__.py +0 -0
  254. {dblift-2.0.3 → dblift-2.0.4}/core/utils/database_url_parser.py +0 -0
  255. {dblift-2.0.3 → dblift-2.0.4}/core/utils/metadata_helpers.py +0 -0
  256. {dblift-2.0.3 → dblift-2.0.4}/core/utils/row_access.py +0 -0
  257. {dblift-2.0.3 → dblift-2.0.4}/core/utils/string_utils.py +0 -0
  258. {dblift-2.0.3 → dblift-2.0.4}/core/utils/url_masking.py +0 -0
  259. {dblift-2.0.3 → dblift-2.0.4}/db/__init__.py +0 -0
  260. {dblift-2.0.3 → dblift-2.0.4}/db/base_provider.py +0 -0
  261. {dblift-2.0.3 → dblift-2.0.4}/db/constants.py +0 -0
  262. {dblift-2.0.3 → dblift-2.0.4}/db/error.py +0 -0
  263. {dblift-2.0.3 → dblift-2.0.4}/db/error_handler.py +0 -0
  264. {dblift-2.0.3 → dblift-2.0.4}/db/exceptions.py +0 -0
  265. {dblift-2.0.3 → dblift-2.0.4}/db/native_connection_manager.py +0 -0
  266. {dblift-2.0.3 → dblift-2.0.4}/db/object_naming.py +0 -0
  267. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/__init__.py +0 -0
  268. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/base_history_manager.py +0 -0
  269. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/base_locking_manager.py +0 -0
  270. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/base_query_executor.py +0 -0
  271. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/base_schema_operations.py +0 -0
  272. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/base_snapshot_manager.py +0 -0
  273. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/base_undo_manager.py +0 -0
  274. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/__init__.py +0 -0
  275. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/cosmosdb/__init__.py +0 -0
  276. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/cosmosdb/_sdk.py +0 -0
  277. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/cosmosdb/connection_manager.py +0 -0
  278. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/cosmosdb/history_manager.py +0 -0
  279. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/cosmosdb/locking_manager.py +0 -0
  280. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/cosmosdb/query_executor.py +0 -0
  281. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/cosmosdb/schema_operations.py +0 -0
  282. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/introspection/__init__.py +0 -0
  283. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/parser/__init__.py +0 -0
  284. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/parser/cosmosdb_regex_parser.py +0 -0
  285. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/plugin.py +0 -0
  286. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/provider.py +0 -0
  287. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/quirks.py +0 -0
  288. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/sdk_translator/__init__.py +0 -0
  289. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/sdk_translator/_executor.py +0 -0
  290. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/sdk_translator/_executors.py +0 -0
  291. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/sdk_translator/_parsing.py +0 -0
  292. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/sdk_translator/_script_generation.py +0 -0
  293. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/sdk_translator/_translator.py +0 -0
  294. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/cosmosdb/sdk_translator/_translators.py +0 -0
  295. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/__init__.py +0 -0
  296. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/db2/__init__.py +0 -0
  297. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/db2/history_manager.py +0 -0
  298. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/db2/locking_manager.py +0 -0
  299. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/db2/schema_operations.py +0 -0
  300. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/introspection/__init__.py +0 -0
  301. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/parser/__init__.py +0 -0
  302. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/parser/db2_regex_parser.py +0 -0
  303. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/parser/parser_config.py +0 -0
  304. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/plugin.py +0 -0
  305. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/provider.py +0 -0
  306. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/db2/sqlalchemy_url.py +0 -0
  307. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mariadb/__init__.py +0 -0
  308. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mariadb/plugin.py +0 -0
  309. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mariadb/provider.py +0 -0
  310. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mariadb/quirks.py +0 -0
  311. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/__init__.py +0 -0
  312. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/introspection/__init__.py +0 -0
  313. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/mysql/__init__.py +0 -0
  314. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/mysql/history_manager.py +0 -0
  315. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/mysql/locking_manager.py +0 -0
  316. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/mysql/schema_operations.py +0 -0
  317. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/parser/__init__.py +0 -0
  318. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/parser/mysql_regex_parser.py +0 -0
  319. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/parser/mysql_statement_parser.py +0 -0
  320. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/parser/mysql_tokenizer.py +0 -0
  321. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/parser/parser_config.py +0 -0
  322. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/plugin.py +0 -0
  323. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/provider.py +0 -0
  324. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/mysql/sqlalchemy_url.py +0 -0
  325. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/__init__.py +0 -0
  326. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/introspection/__init__.py +0 -0
  327. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/introspection/oracle_utils.py +0 -0
  328. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/oracle/__init__.py +0 -0
  329. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/oracle/dbms_output.py +0 -0
  330. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/oracle/history_manager.py +0 -0
  331. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/oracle/locking_manager.py +0 -0
  332. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/oracle/schema_operations.py +0 -0
  333. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/__init__.py +0 -0
  334. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/_comments.py +0 -0
  335. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/_object_extractor.py +0 -0
  336. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/_plsql_block.py +0 -0
  337. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/_sqlplus.py +0 -0
  338. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/_statement_splitter.py +0 -0
  339. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/oracle_parser.py +0 -0
  340. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/oracle_statement_parser.py +0 -0
  341. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/oracle_tokenizer.py +0 -0
  342. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/parser_config.py +0 -0
  343. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/parser/sqlplus_context.py +0 -0
  344. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/plugin.py +0 -0
  345. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/provider.py +0 -0
  346. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/oracle/sqlalchemy_url.py +0 -0
  347. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/__init__.py +0 -0
  348. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/_provider_query_executor.py +0 -0
  349. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/introspection/__init__.py +0 -0
  350. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/parser/__init__.py +0 -0
  351. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/parser/parser_config.py +0 -0
  352. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/parser/postgresql_regex_parser.py +0 -0
  353. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/parser/postgresql_statement_parser.py +0 -0
  354. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/parser/postgresql_tokenizer.py +0 -0
  355. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/plugin.py +0 -0
  356. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/postgresql/__init__.py +0 -0
  357. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/postgresql/history_manager.py +0 -0
  358. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/postgresql/locking_manager.py +0 -0
  359. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/postgresql/schema_operations.py +0 -0
  360. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/provider.py +0 -0
  361. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/postgresql/sqlalchemy_url.py +0 -0
  362. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/__init__.py +0 -0
  363. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/introspection/__init__.py +0 -0
  364. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/parser/__init__.py +0 -0
  365. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/parser/parser_config.py +0 -0
  366. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/parser/sqlite_regex_parser.py +0 -0
  367. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/plugin.py +0 -0
  368. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/provider.py +0 -0
  369. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/sqlalchemy_url.py +0 -0
  370. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/sqlite/__init__.py +0 -0
  371. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/sqlite/connection_manager.py +0 -0
  372. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/sqlite/history_manager.py +0 -0
  373. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/sqlite/locking_manager.py +0 -0
  374. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/sqlite/query_executor.py +0 -0
  375. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlite/sqlite/schema_operations.py +0 -0
  376. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/__init__.py +0 -0
  377. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/introspection/__init__.py +0 -0
  378. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/parser/__init__.py +0 -0
  379. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/parser/parser_config.py +0 -0
  380. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/parser/sqlserver_regex_parser.py +0 -0
  381. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/parser/sqlserver_statement_parser.py +0 -0
  382. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/parser/sqlserver_tokenizer.py +0 -0
  383. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/parser/tsql_batch_separator.py +0 -0
  384. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/plugin.py +0 -0
  385. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/provider.py +0 -0
  386. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/sqlalchemy_url.py +0 -0
  387. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/sqlserver/__init__.py +0 -0
  388. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/sqlserver/history_manager.py +0 -0
  389. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/sqlserver/locking_manager.py +0 -0
  390. {dblift-2.0.3 → dblift-2.0.4}/db/plugins/sqlserver/sqlserver/schema_operations.py +0 -0
  391. {dblift-2.0.3 → dblift-2.0.4}/db/provider_capabilities.py +0 -0
  392. {dblift-2.0.3 → dblift-2.0.4}/db/provider_interfaces.py +0 -0
  393. {dblift-2.0.3 → dblift-2.0.4}/db/provider_registry.py +0 -0
  394. {dblift-2.0.3 → dblift-2.0.4}/db/sqlalchemy_provider.py +0 -0
  395. {dblift-2.0.3 → dblift-2.0.4}/db/value_utils.py +0 -0
  396. {dblift-2.0.3 → dblift-2.0.4}/dblift.egg-info/dependency_links.txt +0 -0
  397. {dblift-2.0.3 → dblift-2.0.4}/dblift.egg-info/entry_points.txt +0 -0
  398. {dblift-2.0.3 → dblift-2.0.4}/dblift.egg-info/top_level.txt +0 -0
  399. {dblift-2.0.3 → dblift-2.0.4}/integrations/__init__.py +0 -0
  400. {dblift-2.0.3 → dblift-2.0.4}/integrations/django/__init__.py +0 -0
  401. {dblift-2.0.3 → dblift-2.0.4}/integrations/django/_client.py +0 -0
  402. {dblift-2.0.3 → dblift-2.0.4}/integrations/django/_engine.py +0 -0
  403. {dblift-2.0.3 → dblift-2.0.4}/integrations/django/apps.py +0 -0
  404. {dblift-2.0.3 → dblift-2.0.4}/integrations/django/checks.py +0 -0
  405. {dblift-2.0.3 → dblift-2.0.4}/integrations/django/management/__init__.py +0 -0
  406. {dblift-2.0.3 → dblift-2.0.4}/integrations/django/management/commands/__init__.py +0 -0
  407. {dblift-2.0.3 → dblift-2.0.4}/integrations/django/management/commands/dblift_info.py +0 -0
  408. {dblift-2.0.3 → dblift-2.0.4}/integrations/django/management/commands/dblift_migrate.py +0 -0
  409. {dblift-2.0.3 → dblift-2.0.4}/integrations/django/management/commands/dblift_validate.py +0 -0
  410. {dblift-2.0.3 → dblift-2.0.4}/integrations/fastapi.py +0 -0
  411. {dblift-2.0.3 → dblift-2.0.4}/integrations/flask.py +0 -0
  412. {dblift-2.0.3 → dblift-2.0.4}/integrations/opentelemetry.py +0 -0
  413. {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
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
- ``diff`` / ``repair`` / ``baseline`` / ``import_flyway`` /
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, but only for online commands.
228
- # Offline commands (plan, validate-sql) skip secret resolution in load_config;
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
- try:
237
- db_overrides = resolve_secret_refs({"database": db_overrides}, config.secrets).get(
238
- "database", db_overrides
239
- )
240
- except SecretsResolutionError as e:
241
- print(f"Error: {e}", file=sys.stderr)
242
- sys.exit(1)
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 two regressions (PR 158 banner fix
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 used by validate-sql to
16
- # skip non-migration SQL files when scanning a directory (e.g. leftover
17
- # temp files, schema dumps) so only intentional migration scripts are
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
- Shared by plan and preflight handlers both follow the same machine/human/file
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, Union
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 distinguish standalone
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
- # Standalone offline commands only need DbliftConfig (dialect, validation rules).
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
- command = getattr(args, "command", None) if args else None
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 such as validate-sql that never open a DB connection
511
- and must not require secret-manager credentials to be available).
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 like plan/validate-sql),
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 (snapshot, export-schema) wrap their
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)