sqlspec 0.18.0__tar.gz → 0.19.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.

Potentially problematic release.


This version of sqlspec might be problematic. Click here for more details.

Files changed (324) hide show
  1. {sqlspec-0.18.0 → sqlspec-0.19.0}/PKG-INFO +1 -1
  2. {sqlspec-0.18.0 → sqlspec-0.19.0}/pyproject.toml +1 -1
  3. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/base.py +18 -14
  4. sqlspec-0.19.0/sqlspec/cli.py +495 -0
  5. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/config.py +151 -1
  6. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/extensions/litestar/plugin.py +15 -8
  7. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_duckdb/test_connection.py +4 -1
  8. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_duckdb/test_execute_many.py +5 -2
  9. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_duckdb/test_parameter_styles.py +6 -4
  10. sqlspec-0.19.0/tests/unit/test_base/test_sql_integration.py +298 -0
  11. {sqlspec-0.18.0 → sqlspec-0.19.0}/uv.lock +7 -7
  12. sqlspec-0.18.0/sqlspec/cli.py +0 -247
  13. sqlspec-0.18.0/tests/unit/test_base_sql_integration.py +0 -282
  14. {sqlspec-0.18.0 → sqlspec-0.19.0}/.gitignore +0 -0
  15. {sqlspec-0.18.0 → sqlspec-0.19.0}/.pre-commit-config.yaml +0 -0
  16. {sqlspec-0.18.0 → sqlspec-0.19.0}/CONTRIBUTING.rst +0 -0
  17. {sqlspec-0.18.0 → sqlspec-0.19.0}/LICENSE +0 -0
  18. {sqlspec-0.18.0 → sqlspec-0.19.0}/Makefile +0 -0
  19. {sqlspec-0.18.0 → sqlspec-0.19.0}/NOTICE +0 -0
  20. {sqlspec-0.18.0 → sqlspec-0.19.0}/README.md +0 -0
  21. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/__init__.py +0 -0
  22. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/__main__.py +0 -0
  23. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/__metadata__.py +0 -0
  24. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/_serialization.py +0 -0
  25. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/_sql.py +0 -0
  26. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/_typing.py +0 -0
  27. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/__init__.py +0 -0
  28. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/adbc/__init__.py +0 -0
  29. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/adbc/_types.py +0 -0
  30. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/adbc/config.py +0 -0
  31. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/adbc/driver.py +0 -0
  32. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/aiosqlite/__init__.py +0 -0
  33. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/aiosqlite/_types.py +0 -0
  34. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/aiosqlite/config.py +0 -0
  35. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/aiosqlite/driver.py +0 -0
  36. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/aiosqlite/pool.py +0 -0
  37. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/asyncmy/__init__.py +0 -0
  38. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/asyncmy/_types.py +0 -0
  39. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/asyncmy/config.py +0 -0
  40. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/asyncmy/driver.py +0 -0
  41. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/asyncpg/__init__.py +0 -0
  42. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/asyncpg/_types.py +0 -0
  43. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/asyncpg/config.py +0 -0
  44. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/asyncpg/driver.py +0 -0
  45. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/bigquery/__init__.py +0 -0
  46. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/bigquery/_types.py +0 -0
  47. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/bigquery/config.py +0 -0
  48. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/bigquery/driver.py +0 -0
  49. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/duckdb/__init__.py +0 -0
  50. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/duckdb/_types.py +0 -0
  51. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/duckdb/config.py +0 -0
  52. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/duckdb/driver.py +0 -0
  53. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/duckdb/pool.py +0 -0
  54. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/oracledb/__init__.py +0 -0
  55. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/oracledb/_types.py +0 -0
  56. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/oracledb/config.py +0 -0
  57. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/oracledb/driver.py +0 -0
  58. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/oracledb/migrations.py +0 -0
  59. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/psqlpy/__init__.py +0 -0
  60. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/psqlpy/_types.py +0 -0
  61. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/psqlpy/config.py +0 -0
  62. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/psqlpy/driver.py +0 -0
  63. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/psycopg/__init__.py +0 -0
  64. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/psycopg/_types.py +0 -0
  65. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/psycopg/config.py +0 -0
  66. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/psycopg/driver.py +0 -0
  67. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/sqlite/__init__.py +0 -0
  68. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/sqlite/_types.py +0 -0
  69. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/sqlite/config.py +0 -0
  70. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/sqlite/driver.py +0 -0
  71. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/adapters/sqlite/pool.py +0 -0
  72. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/__init__.py +0 -0
  73. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/_base.py +0 -0
  74. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/_column.py +0 -0
  75. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/_ddl.py +0 -0
  76. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/_delete.py +0 -0
  77. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/_expression_wrappers.py +0 -0
  78. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/_insert.py +0 -0
  79. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/_merge.py +0 -0
  80. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/_parsing_utils.py +0 -0
  81. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/_select.py +0 -0
  82. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/_update.py +0 -0
  83. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/mixins/__init__.py +0 -0
  84. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/mixins/_cte_and_set_ops.py +0 -0
  85. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/mixins/_delete_operations.py +0 -0
  86. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/mixins/_insert_operations.py +0 -0
  87. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/mixins/_join_operations.py +0 -0
  88. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/mixins/_merge_operations.py +0 -0
  89. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/mixins/_order_limit_operations.py +0 -0
  90. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/mixins/_pivot_operations.py +0 -0
  91. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/mixins/_select_operations.py +0 -0
  92. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/mixins/_update_operations.py +0 -0
  93. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/builder/mixins/_where_clause.py +0 -0
  94. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/core/__init__.py +0 -0
  95. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/core/cache.py +0 -0
  96. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/core/compiler.py +0 -0
  97. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/core/filters.py +0 -0
  98. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/core/hashing.py +0 -0
  99. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/core/parameters.py +0 -0
  100. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/core/result.py +0 -0
  101. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/core/splitter.py +0 -0
  102. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/core/statement.py +0 -0
  103. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/driver/__init__.py +0 -0
  104. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/driver/_async.py +0 -0
  105. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/driver/_common.py +0 -0
  106. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/driver/_sync.py +0 -0
  107. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/driver/mixins/__init__.py +0 -0
  108. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/driver/mixins/_result_tools.py +0 -0
  109. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/driver/mixins/_sql_translator.py +0 -0
  110. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/exceptions.py +0 -0
  111. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/extensions/__init__.py +0 -0
  112. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/extensions/aiosql/__init__.py +0 -0
  113. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/extensions/aiosql/adapter.py +0 -0
  114. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/extensions/litestar/__init__.py +0 -0
  115. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/extensions/litestar/_utils.py +0 -0
  116. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/extensions/litestar/cli.py +0 -0
  117. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/extensions/litestar/config.py +0 -0
  118. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/extensions/litestar/handlers.py +0 -0
  119. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/extensions/litestar/providers.py +0 -0
  120. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/loader.py +0 -0
  121. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/migrations/__init__.py +0 -0
  122. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/migrations/base.py +0 -0
  123. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/migrations/commands.py +0 -0
  124. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/migrations/loaders.py +0 -0
  125. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/migrations/runner.py +0 -0
  126. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/migrations/tracker.py +0 -0
  127. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/migrations/utils.py +0 -0
  128. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/protocols.py +0 -0
  129. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/py.typed +0 -0
  130. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/storage/__init__.py +0 -0
  131. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/storage/backends/__init__.py +0 -0
  132. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/storage/backends/base.py +0 -0
  133. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/storage/backends/fsspec.py +0 -0
  134. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/storage/backends/obstore.py +0 -0
  135. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/storage/capabilities.py +0 -0
  136. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/storage/registry.py +0 -0
  137. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/typing.py +0 -0
  138. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/utils/__init__.py +0 -0
  139. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/utils/correlation.py +0 -0
  140. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/utils/deprecation.py +0 -0
  141. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/utils/fixtures.py +0 -0
  142. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/utils/logging.py +0 -0
  143. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/utils/module_loader.py +0 -0
  144. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/utils/serializers.py +0 -0
  145. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/utils/singleton.py +0 -0
  146. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/utils/sync_tools.py +0 -0
  147. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/utils/text.py +0 -0
  148. {sqlspec-0.18.0 → sqlspec-0.19.0}/sqlspec/utils/type_guards.py +0 -0
  149. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/__init__.py +0 -0
  150. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/conftest.py +0 -0
  151. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/__init__.py +0 -0
  152. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/asset_maintenance.sql +0 -0
  153. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/ddls-mysql-collection.sql +0 -0
  154. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/ddls-postgres-collection.sql +0 -0
  155. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/example_usage.py +0 -0
  156. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/init.sql +0 -0
  157. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/mysql/collection-config.sql +0 -0
  158. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/mysql/collection-data_types.sql +0 -0
  159. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/mysql/collection-database_details.sql +0 -0
  160. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/mysql/collection-engines.sql +0 -0
  161. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/mysql/collection-hostname.sql +0 -0
  162. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/mysql/collection-plugins.sql +0 -0
  163. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/mysql/collection-process_list.sql +0 -0
  164. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/mysql/collection-resource-groups.sql +0 -0
  165. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/mysql/collection-schema_objects.sql +0 -0
  166. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/mysql/collection-table_details.sql +0 -0
  167. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/mysql/collection-users.sql +0 -0
  168. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/mysql/init.sql +0 -0
  169. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/oracle.ddl.sql +0 -0
  170. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-applications.sql +0 -0
  171. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-aws_extension_dependency.sql +0 -0
  172. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-aws_oracle_exists.sql +0 -0
  173. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-bg_writer_stats.sql +0 -0
  174. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-calculated_metrics.sql +0 -0
  175. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-data_types.sql +0 -0
  176. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-database_details.sql +0 -0
  177. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-extensions.sql +0 -0
  178. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-index_details.sql +0 -0
  179. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-pglogical-details.sql +0 -0
  180. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-privileges.sql +0 -0
  181. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-replication_slots.sql +0 -0
  182. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-replication_stats.sql +0 -0
  183. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-schema_details.sql +0 -0
  184. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-schema_objects.sql +0 -0
  185. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-settings.sql +0 -0
  186. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-source_details.sql +0 -0
  187. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/collection-table_details.sql +0 -0
  188. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/extended-collection-all-databases.sql +0 -0
  189. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/postgres/init.sql +0 -0
  190. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/readiness-check.sql +0 -0
  191. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/fixtures/sql_utils.py +0 -0
  192. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/__init__.py +0 -0
  193. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/conftest.py +0 -0
  194. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/__init__.py +0 -0
  195. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_adbc/__init__.py +0 -0
  196. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_adbc/conftest.py +0 -0
  197. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_adbc/test_adbc_arrow_features.py +0 -0
  198. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_adbc/test_adbc_backends.py +0 -0
  199. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_adbc/test_adbc_connection.py +0 -0
  200. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_adbc/test_adbc_driver.py +0 -0
  201. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_adbc/test_adbc_edge_cases.py +0 -0
  202. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_adbc/test_adbc_results.py +0 -0
  203. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_adbc/test_migrations.py +0 -0
  204. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_aiosqlite/__init__.py +0 -0
  205. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_aiosqlite/conftest.py +0 -0
  206. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_aiosqlite/test_connection.py +0 -0
  207. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_aiosqlite/test_driver.py +0 -0
  208. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_aiosqlite/test_migrations.py +0 -0
  209. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_aiosqlite/test_pooling.py +0 -0
  210. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_asyncmy/__init__.py +0 -0
  211. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_asyncmy/conftest.py +0 -0
  212. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_asyncmy/test_asyncmy_features.py +0 -0
  213. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_asyncmy/test_config.py +0 -0
  214. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_asyncmy/test_driver.py +0 -0
  215. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_asyncmy/test_migrations.py +0 -0
  216. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_asyncmy/test_parameter_styles.py +0 -0
  217. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_asyncpg/__init__.py +0 -0
  218. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_asyncpg/conftest.py +0 -0
  219. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_asyncpg/test_connection.py +0 -0
  220. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_asyncpg/test_driver.py +0 -0
  221. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_asyncpg/test_execute_many.py +0 -0
  222. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_asyncpg/test_migrations.py +0 -0
  223. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_asyncpg/test_parameter_styles.py +0 -0
  224. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_bigquery/__init__.py +0 -0
  225. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_bigquery/conftest.py +0 -0
  226. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_bigquery/test_bigquery_features.py +0 -0
  227. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_bigquery/test_config.py +0 -0
  228. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_bigquery/test_connection.py +0 -0
  229. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_bigquery/test_driver.py +0 -0
  230. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_bigquery/test_migrations.py +0 -0
  231. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_bigquery/test_parameter_styles.py +0 -0
  232. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_duckdb/__init__.py +0 -0
  233. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_duckdb/test_driver.py +0 -0
  234. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_duckdb/test_migrations.py +0 -0
  235. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_duckdb/test_mixed_parameter_styles.py +0 -0
  236. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_duckdb/test_pooling.py +0 -0
  237. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_duckdb/utils.py +0 -0
  238. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_oracledb/__init__.py +0 -0
  239. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_oracledb/conftest.py +0 -0
  240. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_oracledb/test_connection.py +0 -0
  241. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_oracledb/test_driver_async.py +0 -0
  242. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_oracledb/test_driver_sync.py +0 -0
  243. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_oracledb/test_execute_many.py +0 -0
  244. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_oracledb/test_migrations.py +0 -0
  245. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_oracledb/test_oracle_features.py +0 -0
  246. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_oracledb/test_parameter_styles.py +0 -0
  247. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psqlpy/__init__.py +0 -0
  248. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psqlpy/conftest.py +0 -0
  249. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psqlpy/test_connection.py +0 -0
  250. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psqlpy/test_driver.py +0 -0
  251. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psqlpy/test_migrations.py +0 -0
  252. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psqlpy/test_parameter_styles.py +0 -0
  253. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psqlpy/test_psqlpy_features.py +0 -0
  254. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psycopg/__init__.py +0 -0
  255. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psycopg/conftest.py +0 -0
  256. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psycopg/test_async_copy.py +0 -0
  257. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psycopg/test_connection.py +0 -0
  258. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psycopg/test_driver.py +0 -0
  259. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psycopg/test_execute_many.py +0 -0
  260. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psycopg/test_migrations.py +0 -0
  261. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_psycopg/test_parameter_styles.py +0 -0
  262. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_sqlite/__init__.py +0 -0
  263. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_sqlite/conftest.py +0 -0
  264. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_sqlite/test_driver.py +0 -0
  265. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_sqlite/test_migrations.py +0 -0
  266. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_sqlite/test_parameter_styles.py +0 -0
  267. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_sqlite/test_pooling.py +0 -0
  268. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_adapters/test_sqlite/test_query_mixin.py +0 -0
  269. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_loader/__init__.py +0 -0
  270. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_loader/test_file_system_loading.py +0 -0
  271. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/integration/test_migrations/__init__.py +0 -0
  272. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/conftest.py +0 -0
  273. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_adapters/__init__.py +0 -0
  274. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_adapters/conftest.py +0 -0
  275. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_adapters/test_adapter_implementations.py +0 -0
  276. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_adapters/test_aiosqlite/__init__.py +0 -0
  277. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_adapters/test_aiosqlite/test_pool.py +0 -0
  278. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_adapters/test_async_adapters.py +0 -0
  279. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_adapters/test_sqlite/__init__.py +0 -0
  280. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_adapters/test_sqlite/test_pool.py +0 -0
  281. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_adapters/test_sync_adapters.py +0 -0
  282. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_base/__init__.py +0 -0
  283. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_base/test_sqlspec_class.py +0 -0
  284. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_builder/__init__.py +0 -0
  285. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_builder/test_insert_builder.py +0 -0
  286. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_builder/test_parameter_naming.py +0 -0
  287. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_builder_parameter_naming.py +0 -0
  288. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_core/test_cache.py +0 -0
  289. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_core/test_compiler.py +0 -0
  290. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_core/test_filters.py +0 -0
  291. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_core/test_hashing.py +0 -0
  292. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_core/test_parameters.py +0 -0
  293. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_core/test_result.py +0 -0
  294. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_core/test_statement.py +0 -0
  295. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_loader/__init__.py +0 -0
  296. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_loader/test_cache_integration.py +0 -0
  297. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_loader/test_fixtures_directory_loading.py +0 -0
  298. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_loader/test_loading_patterns.py +0 -0
  299. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_loader/test_sql_file_loader.py +0 -0
  300. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_migrations/__init__.py +0 -0
  301. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_migrations/test_migration.py +0 -0
  302. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_migrations/test_migration_commands.py +0 -0
  303. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_migrations/test_migration_execution.py +0 -0
  304. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_migrations/test_migration_runner.py +0 -0
  305. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_parsing_utils.py +0 -0
  306. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_sql_factory.py +0 -0
  307. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_utils/__init__.py +0 -0
  308. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_utils/test_correlation.py +0 -0
  309. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_utils/test_deprecation.py +0 -0
  310. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_utils/test_fixtures.py +0 -0
  311. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_utils/test_logging.py +0 -0
  312. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_utils/test_module_loader.py +0 -0
  313. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_utils/test_serializers.py +0 -0
  314. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_utils/test_singleton.py +0 -0
  315. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_utils/test_sync_tools.py +0 -0
  316. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_utils/test_text.py +0 -0
  317. {sqlspec-0.18.0 → sqlspec-0.19.0}/tests/unit/test_utils/test_type_guards.py +0 -0
  318. {sqlspec-0.18.0 → sqlspec-0.19.0}/tools/__init__.py +0 -0
  319. {sqlspec-0.18.0 → sqlspec-0.19.0}/tools/build_docs.py +0 -0
  320. {sqlspec-0.18.0 → sqlspec-0.19.0}/tools/local-infra.sh +0 -0
  321. {sqlspec-0.18.0 → sqlspec-0.19.0}/tools/pypi_readme.py +0 -0
  322. {sqlspec-0.18.0 → sqlspec-0.19.0}/tools/sphinx_ext/__init__.py +0 -0
  323. {sqlspec-0.18.0 → sqlspec-0.19.0}/tools/sphinx_ext/changelog.py +0 -0
  324. {sqlspec-0.18.0 → sqlspec-0.19.0}/tools/sphinx_ext/missing_references.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlspec
3
- Version: 0.18.0
3
+ Version: 0.19.0
4
4
  Summary: SQL Experiments in Python
5
5
  Project-URL: Discord, https://discord.gg/litestar
6
6
  Project-URL: Issue, https://github.com/litestar-org/sqlspec/issues/
@@ -13,7 +13,7 @@ maintainers = [{ name = "Litestar Developers", email = "hello@litestar.dev" }]
13
13
  name = "sqlspec"
14
14
  readme = "README.md"
15
15
  requires-python = ">=3.9, <4.0"
16
- version = "0.18.0"
16
+ version = "0.19.0"
17
17
 
18
18
  [project.urls]
19
19
  Discord = "https://discord.gg/litestar"
@@ -593,22 +593,18 @@ class SQLSpec:
593
593
  )
594
594
  )
595
595
 
596
- def _ensure_sql_loader(self) -> "SQLFileLoader":
597
- """Ensure SQL loader is initialized lazily."""
598
- if self._sql_loader is None:
599
- from sqlspec.loader import SQLFileLoader
600
-
601
- self._sql_loader = SQLFileLoader()
602
- return self._sql_loader
603
-
604
596
  def load_sql_files(self, *paths: "Union[str, Path]") -> None:
605
597
  """Load SQL files from paths or directories.
606
598
 
607
599
  Args:
608
600
  *paths: One or more file paths or directory paths to load.
609
601
  """
610
- loader = self._ensure_sql_loader()
611
- loader.load_sql(*paths)
602
+ if self._sql_loader is None:
603
+ from sqlspec.loader import SQLFileLoader
604
+
605
+ self._sql_loader = SQLFileLoader()
606
+
607
+ self._sql_loader.load_sql(*paths)
612
608
  logger.debug("Loaded SQL files: %s", paths)
613
609
 
614
610
  def add_named_sql(self, name: str, sql: str, dialect: "Optional[str]" = None) -> None:
@@ -619,8 +615,12 @@ class SQLSpec:
619
615
  sql: Raw SQL content.
620
616
  dialect: Optional dialect for the SQL statement.
621
617
  """
622
- loader = self._ensure_sql_loader()
623
- loader.add_named_sql(name, sql, dialect)
618
+ if self._sql_loader is None:
619
+ from sqlspec.loader import SQLFileLoader
620
+
621
+ self._sql_loader = SQLFileLoader()
622
+
623
+ self._sql_loader.add_named_sql(name, sql, dialect)
624
624
  logger.debug("Added named SQL: %s", name)
625
625
 
626
626
  def get_sql(self, name: str) -> "SQL":
@@ -633,8 +633,12 @@ class SQLSpec:
633
633
  Returns:
634
634
  SQL object ready for execution.
635
635
  """
636
- loader = self._ensure_sql_loader()
637
- return loader.get_sql(name)
636
+ if self._sql_loader is None:
637
+ from sqlspec.loader import SQLFileLoader
638
+
639
+ self._sql_loader = SQLFileLoader()
640
+
641
+ return self._sql_loader.get_sql(name)
638
642
 
639
643
  def list_sql_queries(self) -> "list[str]":
640
644
  """List all available query names.
@@ -0,0 +1,495 @@
1
+ # ruff: noqa: C901
2
+ import sys
3
+ from collections.abc import Sequence
4
+ from typing import TYPE_CHECKING, Any, Optional, Union, cast
5
+
6
+ if TYPE_CHECKING:
7
+ from click import Group
8
+
9
+ from sqlspec.config import AsyncDatabaseConfig, SyncDatabaseConfig
10
+
11
+ __all__ = ("add_migration_commands", "get_sqlspec_group")
12
+
13
+
14
+ def get_sqlspec_group() -> "Group":
15
+ """Get the SQLSpec CLI group.
16
+
17
+ Raises:
18
+ MissingDependencyError: If the `click` package is not installed.
19
+
20
+ Returns:
21
+ The SQLSpec CLI group.
22
+ """
23
+ from sqlspec.exceptions import MissingDependencyError
24
+
25
+ try:
26
+ import rich_click as click
27
+ except ImportError:
28
+ try:
29
+ import click # type: ignore[no-redef]
30
+ except ImportError as e:
31
+ raise MissingDependencyError(package="click", install_package="cli") from e
32
+
33
+ @click.group(name="sqlspec")
34
+ @click.option(
35
+ "--config",
36
+ help="Dotted path to SQLSpec config(s) (e.g. 'myapp.config.sqlspec_configs')",
37
+ required=True,
38
+ type=str,
39
+ )
40
+ @click.pass_context
41
+ def sqlspec_group(ctx: "click.Context", config: str) -> None:
42
+ """SQLSpec CLI commands."""
43
+ from rich import get_console
44
+
45
+ from sqlspec.utils import module_loader
46
+
47
+ console = get_console()
48
+ ctx.ensure_object(dict)
49
+ try:
50
+ config_instance = module_loader.import_string(config)
51
+ if isinstance(config_instance, Sequence):
52
+ ctx.obj["configs"] = config_instance
53
+ else:
54
+ ctx.obj["configs"] = [config_instance]
55
+ except ImportError as e:
56
+ console.print(f"[red]Error loading config: {e}[/]")
57
+ ctx.exit(1)
58
+
59
+ return sqlspec_group
60
+
61
+
62
+ def add_migration_commands(database_group: Optional["Group"] = None) -> "Group":
63
+ """Add migration commands to the database group.
64
+
65
+ Args:
66
+ database_group: The database group to add the commands to.
67
+
68
+ Raises:
69
+ MissingDependencyError: If the `click` package is not installed.
70
+
71
+ Returns:
72
+ The database group with the migration commands added.
73
+ """
74
+ from sqlspec.exceptions import MissingDependencyError
75
+
76
+ try:
77
+ import rich_click as click
78
+ except ImportError:
79
+ try:
80
+ import click # type: ignore[no-redef]
81
+ except ImportError as e:
82
+ raise MissingDependencyError(package="click", install_package="cli") from e
83
+ from rich import get_console
84
+
85
+ console = get_console()
86
+
87
+ if database_group is None:
88
+ database_group = get_sqlspec_group()
89
+
90
+ bind_key_option = click.option(
91
+ "--bind-key", help="Specify which SQLSpec config to use by bind key", type=str, default=None
92
+ )
93
+ verbose_option = click.option("--verbose", help="Enable verbose output.", type=bool, default=False, is_flag=True)
94
+ no_prompt_option = click.option(
95
+ "--no-prompt",
96
+ help="Do not prompt for confirmation before executing the command.",
97
+ type=bool,
98
+ default=False,
99
+ required=False,
100
+ show_default=True,
101
+ is_flag=True,
102
+ )
103
+ include_option = click.option(
104
+ "--include", multiple=True, help="Include only specific configurations (can be used multiple times)"
105
+ )
106
+ exclude_option = click.option(
107
+ "--exclude", multiple=True, help="Exclude specific configurations (can be used multiple times)"
108
+ )
109
+ dry_run_option = click.option(
110
+ "--dry-run", is_flag=True, default=False, help="Show what would be executed without making changes"
111
+ )
112
+
113
+ def get_config_by_bind_key(
114
+ ctx: "click.Context", bind_key: Optional[str]
115
+ ) -> "Union[AsyncDatabaseConfig[Any, Any, Any], SyncDatabaseConfig[Any, Any, Any]]":
116
+ """Get the SQLSpec config for the specified bind key.
117
+
118
+ Args:
119
+ ctx: The click context.
120
+ bind_key: The bind key to get the config for.
121
+
122
+ Returns:
123
+ The SQLSpec config for the specified bind key.
124
+ """
125
+ configs = ctx.obj["configs"]
126
+ if bind_key is None:
127
+ config = configs[0]
128
+ else:
129
+ config = None
130
+ for cfg in configs:
131
+ config_name = getattr(cfg, "name", None) or getattr(cfg, "bind_key", None)
132
+ if config_name == bind_key:
133
+ config = cfg
134
+ break
135
+
136
+ if config is None:
137
+ console.print(f"[red]No config found for bind key: {bind_key}[/]")
138
+ sys.exit(1)
139
+
140
+ # Extract the actual config from DatabaseConfig wrapper if needed
141
+ from sqlspec.extensions.litestar.config import DatabaseConfig
142
+
143
+ if isinstance(config, DatabaseConfig):
144
+ config = config.config
145
+
146
+ return cast("Union[AsyncDatabaseConfig[Any, Any, Any], SyncDatabaseConfig[Any, Any, Any]]", config)
147
+
148
+ def get_configs_with_migrations(ctx: "click.Context", enabled_only: bool = False) -> "list[tuple[str, Any]]":
149
+ """Get all configurations that have migrations enabled.
150
+
151
+ Args:
152
+ ctx: The click context.
153
+ enabled_only: If True, only return configs with enabled=True.
154
+
155
+ Returns:
156
+ List of tuples (config_name, config) for configs with migrations enabled.
157
+ """
158
+ configs = ctx.obj["configs"]
159
+ migration_configs = []
160
+
161
+ from sqlspec.extensions.litestar.config import DatabaseConfig
162
+
163
+ for config in configs:
164
+ # Extract the actual config from DatabaseConfig wrapper if needed
165
+ actual_config = config.config if isinstance(config, DatabaseConfig) else config
166
+
167
+ migration_config = getattr(actual_config, "migration_config", None)
168
+ if migration_config:
169
+ enabled = migration_config.get("enabled", True)
170
+ if not enabled_only or enabled:
171
+ config_name = (
172
+ getattr(actual_config, "name", None)
173
+ or getattr(actual_config, "bind_key", None)
174
+ or str(type(actual_config).__name__)
175
+ )
176
+ migration_configs.append((config_name, actual_config))
177
+
178
+ return migration_configs
179
+
180
+ def filter_configs(
181
+ configs: "list[tuple[str, Any]]", include: "tuple[str, ...]", exclude: "tuple[str, ...]"
182
+ ) -> "list[tuple[str, Any]]":
183
+ """Filter configuration list based on include/exclude criteria.
184
+
185
+ Args:
186
+ configs: List of (config_name, config) tuples.
187
+ include: Config names to include (empty means include all).
188
+ exclude: Config names to exclude.
189
+
190
+ Returns:
191
+ Filtered list of configurations.
192
+ """
193
+ filtered = configs
194
+ if include:
195
+ filtered = [(name, config) for name, config in filtered if name in include]
196
+ if exclude:
197
+ filtered = [(name, config) for name, config in filtered if name not in exclude]
198
+ return filtered
199
+
200
+ def process_multiple_configs(
201
+ ctx: "click.Context",
202
+ bind_key: Optional[str],
203
+ include: "tuple[str, ...]",
204
+ exclude: "tuple[str, ...]",
205
+ dry_run: bool,
206
+ operation_name: str,
207
+ ) -> "Optional[list[tuple[str, Any]]]":
208
+ """Process configuration selection for multi-config operations.
209
+
210
+ Args:
211
+ ctx: Click context.
212
+ bind_key: Specific bind key to target.
213
+ include: Config names to include.
214
+ exclude: Config names to exclude.
215
+ dry_run: Whether this is a dry run.
216
+ operation_name: Name of the operation for display.
217
+
218
+ Returns:
219
+ List of (config_name, config) tuples to process, or None for single config mode.
220
+ """
221
+ # If specific bind_key requested, use single config mode
222
+ if bind_key and not include and not exclude:
223
+ return None
224
+
225
+ # Get enabled configs by default, all configs if include/exclude specified
226
+ enabled_only = not include and not exclude
227
+ migration_configs = get_configs_with_migrations(ctx, enabled_only=enabled_only)
228
+
229
+ # If only one config and no filtering, use single config mode
230
+ if len(migration_configs) <= 1 and not include and not exclude:
231
+ return None
232
+
233
+ # Apply filtering
234
+ configs_to_process = filter_configs(migration_configs, include, exclude)
235
+
236
+ if not configs_to_process:
237
+ console.print("[yellow]No configurations match the specified criteria.[/]")
238
+ return []
239
+
240
+ # Show what will be processed
241
+ if dry_run:
242
+ console.print(f"[blue]Dry run: Would {operation_name} {len(configs_to_process)} configuration(s)[/]")
243
+ for config_name, _ in configs_to_process:
244
+ console.print(f" • {config_name}")
245
+ return []
246
+
247
+ return configs_to_process
248
+
249
+ @database_group.command(name="show-current-revision", help="Shows the current revision for the database.")
250
+ @bind_key_option
251
+ @verbose_option
252
+ @include_option
253
+ @exclude_option
254
+ def show_database_revision( # pyright: ignore[reportUnusedFunction]
255
+ bind_key: Optional[str], verbose: bool, include: "tuple[str, ...]", exclude: "tuple[str, ...]"
256
+ ) -> None:
257
+ """Show current database revision."""
258
+ from sqlspec.migrations.commands import MigrationCommands
259
+
260
+ ctx = click.get_current_context()
261
+
262
+ # Check if this is a multi-config operation
263
+ configs_to_process = process_multiple_configs(
264
+ ctx, bind_key, include, exclude, dry_run=False, operation_name="show current revision"
265
+ )
266
+
267
+ if configs_to_process is not None:
268
+ if not configs_to_process:
269
+ return
270
+
271
+ console.rule("[yellow]Listing current revisions for all configurations[/]", align="left")
272
+
273
+ for config_name, config in configs_to_process:
274
+ console.print(f"\n[blue]Configuration: {config_name}[/]")
275
+ try:
276
+ migration_commands = MigrationCommands(config=config)
277
+ migration_commands.current(verbose=verbose)
278
+ except Exception as e:
279
+ console.print(f"[red]✗ Failed to get current revision for {config_name}: {e}[/]")
280
+ else:
281
+ # Single config operation
282
+ console.rule("[yellow]Listing current revision[/]", align="left")
283
+ sqlspec_config = get_config_by_bind_key(ctx, bind_key)
284
+ migration_commands = MigrationCommands(config=sqlspec_config)
285
+ migration_commands.current(verbose=verbose)
286
+
287
+ @database_group.command(name="downgrade", help="Downgrade database to a specific revision.")
288
+ @bind_key_option
289
+ @no_prompt_option
290
+ @include_option
291
+ @exclude_option
292
+ @dry_run_option
293
+ @click.argument("revision", type=str, default="-1")
294
+ def downgrade_database( # pyright: ignore[reportUnusedFunction]
295
+ bind_key: Optional[str],
296
+ revision: str,
297
+ no_prompt: bool,
298
+ include: "tuple[str, ...]",
299
+ exclude: "tuple[str, ...]",
300
+ dry_run: bool,
301
+ ) -> None:
302
+ """Downgrade the database to the latest revision."""
303
+ from rich.prompt import Confirm
304
+
305
+ from sqlspec.migrations.commands import MigrationCommands
306
+
307
+ ctx = click.get_current_context()
308
+
309
+ # Check if this is a multi-config operation
310
+ configs_to_process = process_multiple_configs(
311
+ ctx, bind_key, include, exclude, dry_run=dry_run, operation_name=f"downgrade to {revision}"
312
+ )
313
+
314
+ if configs_to_process is not None:
315
+ if not configs_to_process:
316
+ return
317
+
318
+ if not no_prompt and not Confirm.ask(
319
+ f"[bold]Are you sure you want to downgrade {len(configs_to_process)} configuration(s) to revision {revision}?[/]"
320
+ ):
321
+ console.print("[yellow]Operation cancelled.[/]")
322
+ return
323
+
324
+ console.rule("[yellow]Starting multi-configuration downgrade process[/]", align="left")
325
+
326
+ for config_name, config in configs_to_process:
327
+ console.print(f"[blue]Downgrading configuration: {config_name}[/]")
328
+ try:
329
+ migration_commands = MigrationCommands(config=config)
330
+ migration_commands.downgrade(revision=revision)
331
+ console.print(f"[green]✓ Successfully downgraded: {config_name}[/]")
332
+ except Exception as e:
333
+ console.print(f"[red]✗ Failed to downgrade {config_name}: {e}[/]")
334
+ else:
335
+ # Single config operation
336
+ console.rule("[yellow]Starting database downgrade process[/]", align="left")
337
+ input_confirmed = (
338
+ True
339
+ if no_prompt
340
+ else Confirm.ask(f"Are you sure you want to downgrade the database to the `{revision}` revision?")
341
+ )
342
+ if input_confirmed:
343
+ sqlspec_config = get_config_by_bind_key(ctx, bind_key)
344
+ migration_commands = MigrationCommands(config=sqlspec_config)
345
+ migration_commands.downgrade(revision=revision)
346
+
347
+ @database_group.command(name="upgrade", help="Upgrade database to a specific revision.")
348
+ @bind_key_option
349
+ @no_prompt_option
350
+ @include_option
351
+ @exclude_option
352
+ @dry_run_option
353
+ @click.argument("revision", type=str, default="head")
354
+ def upgrade_database( # pyright: ignore[reportUnusedFunction]
355
+ bind_key: Optional[str],
356
+ revision: str,
357
+ no_prompt: bool,
358
+ include: "tuple[str, ...]",
359
+ exclude: "tuple[str, ...]",
360
+ dry_run: bool,
361
+ ) -> None:
362
+ """Upgrade the database to the latest revision."""
363
+ from rich.prompt import Confirm
364
+
365
+ from sqlspec.migrations.commands import MigrationCommands
366
+
367
+ ctx = click.get_current_context()
368
+
369
+ # Check if this is a multi-config operation
370
+ configs_to_process = process_multiple_configs(
371
+ ctx, bind_key, include, exclude, dry_run, operation_name=f"upgrade to {revision}"
372
+ )
373
+
374
+ if configs_to_process is not None:
375
+ if not configs_to_process:
376
+ return
377
+
378
+ if not no_prompt and not Confirm.ask(
379
+ f"[bold]Are you sure you want to upgrade {len(configs_to_process)} configuration(s) to revision {revision}?[/]"
380
+ ):
381
+ console.print("[yellow]Operation cancelled.[/]")
382
+ return
383
+
384
+ console.rule("[yellow]Starting multi-configuration upgrade process[/]", align="left")
385
+
386
+ for config_name, config in configs_to_process:
387
+ console.print(f"[blue]Upgrading configuration: {config_name}[/]")
388
+ try:
389
+ migration_commands = MigrationCommands(config=config)
390
+ migration_commands.upgrade(revision=revision)
391
+ console.print(f"[green]✓ Successfully upgraded: {config_name}[/]")
392
+ except Exception as e:
393
+ console.print(f"[red]✗ Failed to upgrade {config_name}: {e}[/]")
394
+ else:
395
+ # Single config operation
396
+ console.rule("[yellow]Starting database upgrade process[/]", align="left")
397
+ input_confirmed = (
398
+ True
399
+ if no_prompt
400
+ else Confirm.ask(f"[bold]Are you sure you want migrate the database to the `{revision}` revision?[/]")
401
+ )
402
+ if input_confirmed:
403
+ sqlspec_config = get_config_by_bind_key(ctx, bind_key)
404
+ migration_commands = MigrationCommands(config=sqlspec_config)
405
+ migration_commands.upgrade(revision=revision)
406
+
407
+ @database_group.command(help="Stamp the revision table with the given revision")
408
+ @click.argument("revision", type=str)
409
+ @bind_key_option
410
+ def stamp(bind_key: Optional[str], revision: str) -> None: # pyright: ignore[reportUnusedFunction]
411
+ """Stamp the revision table with the given revision."""
412
+ from sqlspec.migrations.commands import MigrationCommands
413
+
414
+ ctx = click.get_current_context()
415
+ sqlspec_config = get_config_by_bind_key(ctx, bind_key)
416
+ migration_commands = MigrationCommands(config=sqlspec_config)
417
+ migration_commands.stamp(revision=revision)
418
+
419
+ @database_group.command(name="init", help="Initialize migrations for the project.")
420
+ @bind_key_option
421
+ @click.argument("directory", default=None, required=False)
422
+ @click.option("--package", is_flag=True, default=True, help="Create `__init__.py` for created folder")
423
+ @no_prompt_option
424
+ def init_sqlspec( # pyright: ignore[reportUnusedFunction]
425
+ bind_key: Optional[str], directory: Optional[str], package: bool, no_prompt: bool
426
+ ) -> None:
427
+ """Initialize the database migrations."""
428
+ from rich.prompt import Confirm
429
+
430
+ from sqlspec.migrations.commands import MigrationCommands
431
+
432
+ ctx = click.get_current_context()
433
+ console.rule("[yellow]Initializing database migrations.", align="left")
434
+ input_confirmed = (
435
+ True if no_prompt else Confirm.ask("[bold]Are you sure you want initialize migrations for the project?[/]")
436
+ )
437
+ if input_confirmed:
438
+ configs = [get_config_by_bind_key(ctx, bind_key)] if bind_key is not None else ctx.obj["configs"]
439
+ from sqlspec.extensions.litestar.config import DatabaseConfig
440
+
441
+ for config in configs:
442
+ # Extract the actual config from DatabaseConfig wrapper if needed
443
+ actual_config = config.config if isinstance(config, DatabaseConfig) else config
444
+ migration_config = getattr(actual_config, "migration_config", {})
445
+ directory = migration_config.get("script_location", "migrations") if directory is None else directory
446
+ migration_commands = MigrationCommands(config=actual_config)
447
+ migration_commands.init(directory=cast("str", directory), package=package)
448
+
449
+ @database_group.command(name="make-migrations", help="Create a new migration revision.")
450
+ @bind_key_option
451
+ @click.option("-m", "--message", default=None, help="Revision message")
452
+ @no_prompt_option
453
+ def create_revision( # pyright: ignore[reportUnusedFunction]
454
+ bind_key: Optional[str], message: Optional[str], no_prompt: bool
455
+ ) -> None:
456
+ """Create a new database revision."""
457
+ from rich.prompt import Prompt
458
+
459
+ from sqlspec.migrations.commands import MigrationCommands
460
+
461
+ ctx = click.get_current_context()
462
+ console.rule("[yellow]Creating new migration revision[/]", align="left")
463
+ if message is None:
464
+ message = "new migration" if no_prompt else Prompt.ask("Please enter a message describing this revision")
465
+
466
+ sqlspec_config = get_config_by_bind_key(ctx, bind_key)
467
+ migration_commands = MigrationCommands(config=sqlspec_config)
468
+ migration_commands.revision(message=message)
469
+
470
+ @database_group.command(name="show-config", help="Show all configurations with migrations enabled.")
471
+ def show_config() -> None: # pyright: ignore[reportUnusedFunction]
472
+ """Show and display all configurations with migrations enabled."""
473
+ from rich.table import Table
474
+
475
+ ctx = click.get_current_context()
476
+ migration_configs = get_configs_with_migrations(ctx)
477
+
478
+ if not migration_configs:
479
+ console.print("[yellow]No configurations with migrations detected.[/]")
480
+ return
481
+
482
+ table = Table(title="Migration Configurations")
483
+ table.add_column("Configuration Name", style="cyan")
484
+ table.add_column("Migration Path", style="blue")
485
+ table.add_column("Status", style="green")
486
+
487
+ for config_name, config in migration_configs:
488
+ migration_config = getattr(config, "migration_config", {})
489
+ script_location = migration_config.get("script_location", "migrations")
490
+ table.add_row(config_name, script_location, "Migration Enabled")
491
+
492
+ console.print(table)
493
+ console.print(f"[blue]Found {len(migration_configs)} configuration(s) with migrations enabled.[/]")
494
+
495
+ return database_group