sqlspec 0.47.0__cp314-cp314-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (621) hide show
  1. f68e0789eb443ecb1c2c__mypyc.cp314-win_amd64.pyd +0 -0
  2. sqlspec/__init__.py +167 -0
  3. sqlspec/__main__.py +12 -0
  4. sqlspec/__metadata__.py +14 -0
  5. sqlspec/_typing.py +714 -0
  6. sqlspec/adapters/__init__.py +0 -0
  7. sqlspec/adapters/adbc/__init__.py +13 -0
  8. sqlspec/adapters/adbc/_typing.py +106 -0
  9. sqlspec/adapters/adbc/adk/__init__.py +5 -0
  10. sqlspec/adapters/adbc/adk/store.py +1280 -0
  11. sqlspec/adapters/adbc/config.py +378 -0
  12. sqlspec/adapters/adbc/core.cp314-win_amd64.pyd +0 -0
  13. sqlspec/adapters/adbc/core.py +922 -0
  14. sqlspec/adapters/adbc/data_dictionary.py +339 -0
  15. sqlspec/adapters/adbc/driver.py +534 -0
  16. sqlspec/adapters/adbc/events/__init__.py +5 -0
  17. sqlspec/adapters/adbc/events/store.py +285 -0
  18. sqlspec/adapters/adbc/litestar/__init__.py +5 -0
  19. sqlspec/adapters/adbc/litestar/store.py +534 -0
  20. sqlspec/adapters/adbc/type_converter.cp314-win_amd64.pyd +0 -0
  21. sqlspec/adapters/adbc/type_converter.py +142 -0
  22. sqlspec/adapters/aiomysql/__init__.py +21 -0
  23. sqlspec/adapters/aiomysql/_typing.py +137 -0
  24. sqlspec/adapters/aiomysql/adk/__init__.py +5 -0
  25. sqlspec/adapters/aiomysql/adk/store.py +678 -0
  26. sqlspec/adapters/aiomysql/config.py +305 -0
  27. sqlspec/adapters/aiomysql/core.cp314-win_amd64.pyd +0 -0
  28. sqlspec/adapters/aiomysql/core.py +536 -0
  29. sqlspec/adapters/aiomysql/data_dictionary.py +121 -0
  30. sqlspec/adapters/aiomysql/driver.py +386 -0
  31. sqlspec/adapters/aiomysql/events/__init__.py +5 -0
  32. sqlspec/adapters/aiomysql/events/store.py +104 -0
  33. sqlspec/adapters/aiomysql/litestar/__init__.py +5 -0
  34. sqlspec/adapters/aiomysql/litestar/store.py +314 -0
  35. sqlspec/adapters/aiosqlite/__init__.py +26 -0
  36. sqlspec/adapters/aiosqlite/_typing.py +109 -0
  37. sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
  38. sqlspec/adapters/aiosqlite/adk/store.py +829 -0
  39. sqlspec/adapters/aiosqlite/config.py +315 -0
  40. sqlspec/adapters/aiosqlite/core.cp314-win_amd64.pyd +0 -0
  41. sqlspec/adapters/aiosqlite/core.py +315 -0
  42. sqlspec/adapters/aiosqlite/data_dictionary.py +202 -0
  43. sqlspec/adapters/aiosqlite/driver.py +311 -0
  44. sqlspec/adapters/aiosqlite/events/__init__.py +5 -0
  45. sqlspec/adapters/aiosqlite/events/store.py +20 -0
  46. sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
  47. sqlspec/adapters/aiosqlite/litestar/store.py +279 -0
  48. sqlspec/adapters/aiosqlite/pool.cp314-win_amd64.pyd +0 -0
  49. sqlspec/adapters/aiosqlite/pool.py +734 -0
  50. sqlspec/adapters/asyncmy/__init__.py +21 -0
  51. sqlspec/adapters/asyncmy/_typing.py +113 -0
  52. sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
  53. sqlspec/adapters/asyncmy/adk/store.py +644 -0
  54. sqlspec/adapters/asyncmy/config.py +307 -0
  55. sqlspec/adapters/asyncmy/core.cp314-win_amd64.pyd +0 -0
  56. sqlspec/adapters/asyncmy/core.py +538 -0
  57. sqlspec/adapters/asyncmy/data_dictionary.py +122 -0
  58. sqlspec/adapters/asyncmy/driver.py +391 -0
  59. sqlspec/adapters/asyncmy/events/__init__.py +5 -0
  60. sqlspec/adapters/asyncmy/events/store.py +104 -0
  61. sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
  62. sqlspec/adapters/asyncmy/litestar/store.py +296 -0
  63. sqlspec/adapters/asyncpg/__init__.py +26 -0
  64. sqlspec/adapters/asyncpg/_typing.py +103 -0
  65. sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
  66. sqlspec/adapters/asyncpg/adk/store.py +483 -0
  67. sqlspec/adapters/asyncpg/config.py +575 -0
  68. sqlspec/adapters/asyncpg/core.cp314-win_amd64.pyd +0 -0
  69. sqlspec/adapters/asyncpg/core.py +480 -0
  70. sqlspec/adapters/asyncpg/data_dictionary.py +157 -0
  71. sqlspec/adapters/asyncpg/driver.py +487 -0
  72. sqlspec/adapters/asyncpg/events/__init__.py +6 -0
  73. sqlspec/adapters/asyncpg/events/_hub.py +181 -0
  74. sqlspec/adapters/asyncpg/events/backend.py +210 -0
  75. sqlspec/adapters/asyncpg/events/store.py +40 -0
  76. sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
  77. sqlspec/adapters/asyncpg/litestar/store.py +251 -0
  78. sqlspec/adapters/bigquery/__init__.py +15 -0
  79. sqlspec/adapters/bigquery/_typing.py +108 -0
  80. sqlspec/adapters/bigquery/config.py +362 -0
  81. sqlspec/adapters/bigquery/core.cp314-win_amd64.pyd +0 -0
  82. sqlspec/adapters/bigquery/core.py +768 -0
  83. sqlspec/adapters/bigquery/data_dictionary.py +120 -0
  84. sqlspec/adapters/bigquery/driver.py +542 -0
  85. sqlspec/adapters/bigquery/events/__init__.py +5 -0
  86. sqlspec/adapters/bigquery/events/store.py +139 -0
  87. sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
  88. sqlspec/adapters/bigquery/litestar/store.py +325 -0
  89. sqlspec/adapters/bigquery/type_converter.cp314-win_amd64.pyd +0 -0
  90. sqlspec/adapters/bigquery/type_converter.py +107 -0
  91. sqlspec/adapters/cockroach_asyncpg/__init__.py +26 -0
  92. sqlspec/adapters/cockroach_asyncpg/_typing.py +73 -0
  93. sqlspec/adapters/cockroach_asyncpg/adk/__init__.py +3 -0
  94. sqlspec/adapters/cockroach_asyncpg/adk/store.py +465 -0
  95. sqlspec/adapters/cockroach_asyncpg/config.py +248 -0
  96. sqlspec/adapters/cockroach_asyncpg/core.cp314-win_amd64.pyd +0 -0
  97. sqlspec/adapters/cockroach_asyncpg/core.py +55 -0
  98. sqlspec/adapters/cockroach_asyncpg/data_dictionary.py +110 -0
  99. sqlspec/adapters/cockroach_asyncpg/driver.py +142 -0
  100. sqlspec/adapters/cockroach_asyncpg/events/__init__.py +3 -0
  101. sqlspec/adapters/cockroach_asyncpg/events/store.py +20 -0
  102. sqlspec/adapters/cockroach_asyncpg/litestar/__init__.py +3 -0
  103. sqlspec/adapters/cockroach_asyncpg/litestar/store.py +142 -0
  104. sqlspec/adapters/cockroach_psycopg/__init__.py +39 -0
  105. sqlspec/adapters/cockroach_psycopg/_typing.py +137 -0
  106. sqlspec/adapters/cockroach_psycopg/adk/__init__.py +13 -0
  107. sqlspec/adapters/cockroach_psycopg/adk/store.py +1039 -0
  108. sqlspec/adapters/cockroach_psycopg/config.py +511 -0
  109. sqlspec/adapters/cockroach_psycopg/core.cp314-win_amd64.pyd +0 -0
  110. sqlspec/adapters/cockroach_psycopg/core.py +63 -0
  111. sqlspec/adapters/cockroach_psycopg/data_dictionary.py +220 -0
  112. sqlspec/adapters/cockroach_psycopg/driver.py +273 -0
  113. sqlspec/adapters/cockroach_psycopg/events/__init__.py +6 -0
  114. sqlspec/adapters/cockroach_psycopg/events/store.py +34 -0
  115. sqlspec/adapters/cockroach_psycopg/litestar/__init__.py +3 -0
  116. sqlspec/adapters/cockroach_psycopg/litestar/store.py +327 -0
  117. sqlspec/adapters/duckdb/__init__.py +29 -0
  118. sqlspec/adapters/duckdb/_typing.py +104 -0
  119. sqlspec/adapters/duckdb/adk/__init__.py +14 -0
  120. sqlspec/adapters/duckdb/adk/store.py +935 -0
  121. sqlspec/adapters/duckdb/config.py +386 -0
  122. sqlspec/adapters/duckdb/core.cp314-win_amd64.pyd +0 -0
  123. sqlspec/adapters/duckdb/core.py +332 -0
  124. sqlspec/adapters/duckdb/data_dictionary.py +140 -0
  125. sqlspec/adapters/duckdb/driver.py +426 -0
  126. sqlspec/adapters/duckdb/events/__init__.py +5 -0
  127. sqlspec/adapters/duckdb/events/store.py +57 -0
  128. sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
  129. sqlspec/adapters/duckdb/litestar/store.py +330 -0
  130. sqlspec/adapters/duckdb/pool.cp314-win_amd64.pyd +0 -0
  131. sqlspec/adapters/duckdb/pool.py +350 -0
  132. sqlspec/adapters/duckdb/type_converter.cp314-win_amd64.pyd +0 -0
  133. sqlspec/adapters/duckdb/type_converter.py +118 -0
  134. sqlspec/adapters/mysqlconnector/__init__.py +39 -0
  135. sqlspec/adapters/mysqlconnector/_typing.py +186 -0
  136. sqlspec/adapters/mysqlconnector/adk/__init__.py +15 -0
  137. sqlspec/adapters/mysqlconnector/adk/store.py +1183 -0
  138. sqlspec/adapters/mysqlconnector/config.py +421 -0
  139. sqlspec/adapters/mysqlconnector/core.cp314-win_amd64.pyd +0 -0
  140. sqlspec/adapters/mysqlconnector/core.py +472 -0
  141. sqlspec/adapters/mysqlconnector/data_dictionary.py +230 -0
  142. sqlspec/adapters/mysqlconnector/driver.py +516 -0
  143. sqlspec/adapters/mysqlconnector/events/__init__.py +8 -0
  144. sqlspec/adapters/mysqlconnector/events/store.py +98 -0
  145. sqlspec/adapters/mysqlconnector/litestar/__init__.py +5 -0
  146. sqlspec/adapters/mysqlconnector/litestar/store.py +426 -0
  147. sqlspec/adapters/oracledb/__init__.py +39 -0
  148. sqlspec/adapters/oracledb/_json_handlers.cp314-win_amd64.pyd +0 -0
  149. sqlspec/adapters/oracledb/_json_handlers.py +196 -0
  150. sqlspec/adapters/oracledb/_param_types.cp314-win_amd64.pyd +0 -0
  151. sqlspec/adapters/oracledb/_param_types.py +46 -0
  152. sqlspec/adapters/oracledb/_typing.py +258 -0
  153. sqlspec/adapters/oracledb/_uuid_handlers.cp314-win_amd64.pyd +0 -0
  154. sqlspec/adapters/oracledb/_uuid_handlers.py +163 -0
  155. sqlspec/adapters/oracledb/_vector_handlers.cp314-win_amd64.pyd +0 -0
  156. sqlspec/adapters/oracledb/_vector_handlers.py +228 -0
  157. sqlspec/adapters/oracledb/adk/__init__.py +21 -0
  158. sqlspec/adapters/oracledb/adk/store.py +2453 -0
  159. sqlspec/adapters/oracledb/config.py +575 -0
  160. sqlspec/adapters/oracledb/core.cp314-win_amd64.pyd +0 -0
  161. sqlspec/adapters/oracledb/core.py +820 -0
  162. sqlspec/adapters/oracledb/data_dictionary.py +404 -0
  163. sqlspec/adapters/oracledb/driver.py +1277 -0
  164. sqlspec/adapters/oracledb/events/__init__.py +16 -0
  165. sqlspec/adapters/oracledb/events/_hub.py +345 -0
  166. sqlspec/adapters/oracledb/events/backend.py +300 -0
  167. sqlspec/adapters/oracledb/events/store.py +420 -0
  168. sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
  169. sqlspec/adapters/oracledb/litestar/store.py +781 -0
  170. sqlspec/adapters/oracledb/migrations.py +539 -0
  171. sqlspec/adapters/oracledb/type_converter.cp314-win_amd64.pyd +0 -0
  172. sqlspec/adapters/oracledb/type_converter.py +211 -0
  173. sqlspec/adapters/psqlpy/__init__.py +18 -0
  174. sqlspec/adapters/psqlpy/_typing.py +121 -0
  175. sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
  176. sqlspec/adapters/psqlpy/adk/store.py +591 -0
  177. sqlspec/adapters/psqlpy/config.py +376 -0
  178. sqlspec/adapters/psqlpy/core.cp314-win_amd64.pyd +0 -0
  179. sqlspec/adapters/psqlpy/core.py +694 -0
  180. sqlspec/adapters/psqlpy/data_dictionary.py +121 -0
  181. sqlspec/adapters/psqlpy/driver.py +411 -0
  182. sqlspec/adapters/psqlpy/events/__init__.py +6 -0
  183. sqlspec/adapters/psqlpy/events/_hub.py +204 -0
  184. sqlspec/adapters/psqlpy/events/backend.py +210 -0
  185. sqlspec/adapters/psqlpy/events/store.py +20 -0
  186. sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
  187. sqlspec/adapters/psqlpy/litestar/store.py +270 -0
  188. sqlspec/adapters/psqlpy/type_converter.cp314-win_amd64.pyd +0 -0
  189. sqlspec/adapters/psqlpy/type_converter.py +113 -0
  190. sqlspec/adapters/psycopg/__init__.py +38 -0
  191. sqlspec/adapters/psycopg/_typing.py +218 -0
  192. sqlspec/adapters/psycopg/adk/__init__.py +10 -0
  193. sqlspec/adapters/psycopg/adk/store.py +1106 -0
  194. sqlspec/adapters/psycopg/config.py +695 -0
  195. sqlspec/adapters/psycopg/core.cp314-win_amd64.pyd +0 -0
  196. sqlspec/adapters/psycopg/core.py +520 -0
  197. sqlspec/adapters/psycopg/data_dictionary.py +278 -0
  198. sqlspec/adapters/psycopg/driver.py +1033 -0
  199. sqlspec/adapters/psycopg/events/__init__.py +20 -0
  200. sqlspec/adapters/psycopg/events/_hub.py +388 -0
  201. sqlspec/adapters/psycopg/events/backend.py +398 -0
  202. sqlspec/adapters/psycopg/events/store.py +42 -0
  203. sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
  204. sqlspec/adapters/psycopg/litestar/store.py +554 -0
  205. sqlspec/adapters/psycopg/type_converter.cp314-win_amd64.pyd +0 -0
  206. sqlspec/adapters/psycopg/type_converter.py +93 -0
  207. sqlspec/adapters/pymysql/__init__.py +21 -0
  208. sqlspec/adapters/pymysql/_typing.py +92 -0
  209. sqlspec/adapters/pymysql/adk/__init__.py +5 -0
  210. sqlspec/adapters/pymysql/adk/store.py +657 -0
  211. sqlspec/adapters/pymysql/config.py +176 -0
  212. sqlspec/adapters/pymysql/core.cp314-win_amd64.pyd +0 -0
  213. sqlspec/adapters/pymysql/core.py +469 -0
  214. sqlspec/adapters/pymysql/data_dictionary.py +120 -0
  215. sqlspec/adapters/pymysql/driver.py +271 -0
  216. sqlspec/adapters/pymysql/events/__init__.py +5 -0
  217. sqlspec/adapters/pymysql/events/store.py +50 -0
  218. sqlspec/adapters/pymysql/litestar/__init__.py +5 -0
  219. sqlspec/adapters/pymysql/litestar/store.py +232 -0
  220. sqlspec/adapters/pymysql/pool.cp314-win_amd64.pyd +0 -0
  221. sqlspec/adapters/pymysql/pool.py +184 -0
  222. sqlspec/adapters/spanner/__init__.py +33 -0
  223. sqlspec/adapters/spanner/_typing.py +102 -0
  224. sqlspec/adapters/spanner/adk/__init__.py +5 -0
  225. sqlspec/adapters/spanner/adk/store.py +758 -0
  226. sqlspec/adapters/spanner/config.py +355 -0
  227. sqlspec/adapters/spanner/core.cp314-win_amd64.pyd +0 -0
  228. sqlspec/adapters/spanner/core.py +263 -0
  229. sqlspec/adapters/spanner/data_dictionary.py +120 -0
  230. sqlspec/adapters/spanner/driver.py +407 -0
  231. sqlspec/adapters/spanner/events/__init__.py +5 -0
  232. sqlspec/adapters/spanner/events/store.py +187 -0
  233. sqlspec/adapters/spanner/litestar/__init__.py +5 -0
  234. sqlspec/adapters/spanner/litestar/store.py +291 -0
  235. sqlspec/adapters/spanner/type_converter.cp314-win_amd64.pyd +0 -0
  236. sqlspec/adapters/spanner/type_converter.py +342 -0
  237. sqlspec/adapters/sqlite/__init__.py +19 -0
  238. sqlspec/adapters/sqlite/_typing.py +123 -0
  239. sqlspec/adapters/sqlite/adk/__init__.py +5 -0
  240. sqlspec/adapters/sqlite/adk/store.py +992 -0
  241. sqlspec/adapters/sqlite/config.py +240 -0
  242. sqlspec/adapters/sqlite/core.cp314-win_amd64.pyd +0 -0
  243. sqlspec/adapters/sqlite/core.py +357 -0
  244. sqlspec/adapters/sqlite/data_dictionary.py +198 -0
  245. sqlspec/adapters/sqlite/driver.py +527 -0
  246. sqlspec/adapters/sqlite/events/__init__.py +5 -0
  247. sqlspec/adapters/sqlite/events/store.py +20 -0
  248. sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
  249. sqlspec/adapters/sqlite/litestar/store.py +316 -0
  250. sqlspec/adapters/sqlite/pool.cp314-win_amd64.pyd +0 -0
  251. sqlspec/adapters/sqlite/pool.py +237 -0
  252. sqlspec/adapters/sqlite/type_converter.cp314-win_amd64.pyd +0 -0
  253. sqlspec/adapters/sqlite/type_converter.py +114 -0
  254. sqlspec/base.py +832 -0
  255. sqlspec/builder/__init__.py +181 -0
  256. sqlspec/builder/_base.cp314-win_amd64.pyd +0 -0
  257. sqlspec/builder/_base.py +1071 -0
  258. sqlspec/builder/_column.cp314-win_amd64.pyd +0 -0
  259. sqlspec/builder/_column.py +521 -0
  260. sqlspec/builder/_ddl.cp314-win_amd64.pyd +0 -0
  261. sqlspec/builder/_ddl.py +1691 -0
  262. sqlspec/builder/_delete.cp314-win_amd64.pyd +0 -0
  263. sqlspec/builder/_delete.py +95 -0
  264. sqlspec/builder/_dml.cp314-win_amd64.pyd +0 -0
  265. sqlspec/builder/_dml.py +386 -0
  266. sqlspec/builder/_explain.cp314-win_amd64.pyd +0 -0
  267. sqlspec/builder/_explain.py +579 -0
  268. sqlspec/builder/_expression_wrappers.cp314-win_amd64.pyd +0 -0
  269. sqlspec/builder/_expression_wrappers.py +46 -0
  270. sqlspec/builder/_factory.cp314-win_amd64.pyd +0 -0
  271. sqlspec/builder/_factory.py +1884 -0
  272. sqlspec/builder/_insert.cp314-win_amd64.pyd +0 -0
  273. sqlspec/builder/_insert.py +405 -0
  274. sqlspec/builder/_join.cp314-win_amd64.pyd +0 -0
  275. sqlspec/builder/_join.py +489 -0
  276. sqlspec/builder/_merge.cp314-win_amd64.pyd +0 -0
  277. sqlspec/builder/_merge.py +823 -0
  278. sqlspec/builder/_parsing_utils.cp314-win_amd64.pyd +0 -0
  279. sqlspec/builder/_parsing_utils.py +295 -0
  280. sqlspec/builder/_select.cp314-win_amd64.pyd +0 -0
  281. sqlspec/builder/_select.py +1666 -0
  282. sqlspec/builder/_temporal.cp314-win_amd64.pyd +0 -0
  283. sqlspec/builder/_temporal.py +167 -0
  284. sqlspec/builder/_update.cp314-win_amd64.pyd +0 -0
  285. sqlspec/builder/_update.py +173 -0
  286. sqlspec/builder/_vector_distance.cp314-win_amd64.pyd +0 -0
  287. sqlspec/builder/_vector_distance.py +330 -0
  288. sqlspec/cli.py +1095 -0
  289. sqlspec/config.py +2383 -0
  290. sqlspec/core/__init__.py +372 -0
  291. sqlspec/core/_correlation.cp314-win_amd64.pyd +0 -0
  292. sqlspec/core/_correlation.py +176 -0
  293. sqlspec/core/_pagination.py +42 -0
  294. sqlspec/core/_pool.cp314-win_amd64.pyd +0 -0
  295. sqlspec/core/_pool.py +76 -0
  296. sqlspec/core/cache.cp314-win_amd64.pyd +0 -0
  297. sqlspec/core/cache.py +1085 -0
  298. sqlspec/core/compiler.cp314-win_amd64.pyd +0 -0
  299. sqlspec/core/compiler.py +1090 -0
  300. sqlspec/core/config_runtime.cp314-win_amd64.pyd +0 -0
  301. sqlspec/core/config_runtime.py +174 -0
  302. sqlspec/core/explain.cp314-win_amd64.pyd +0 -0
  303. sqlspec/core/explain.py +275 -0
  304. sqlspec/core/filters.cp314-win_amd64.pyd +0 -0
  305. sqlspec/core/filters.py +969 -0
  306. sqlspec/core/hashing.cp314-win_amd64.pyd +0 -0
  307. sqlspec/core/hashing.py +266 -0
  308. sqlspec/core/metrics.cp314-win_amd64.pyd +0 -0
  309. sqlspec/core/metrics.py +83 -0
  310. sqlspec/core/parameters/__init__.py +72 -0
  311. sqlspec/core/parameters/_alignment.cp314-win_amd64.pyd +0 -0
  312. sqlspec/core/parameters/_alignment.py +283 -0
  313. sqlspec/core/parameters/_converter.cp314-win_amd64.pyd +0 -0
  314. sqlspec/core/parameters/_converter.py +554 -0
  315. sqlspec/core/parameters/_processor.cp314-win_amd64.pyd +0 -0
  316. sqlspec/core/parameters/_processor.py +1182 -0
  317. sqlspec/core/parameters/_registry.cp314-win_amd64.pyd +0 -0
  318. sqlspec/core/parameters/_registry.py +206 -0
  319. sqlspec/core/parameters/_transformers.cp314-win_amd64.pyd +0 -0
  320. sqlspec/core/parameters/_transformers.py +324 -0
  321. sqlspec/core/parameters/_types.cp314-win_amd64.pyd +0 -0
  322. sqlspec/core/parameters/_types.py +536 -0
  323. sqlspec/core/parameters/_validator.cp314-win_amd64.pyd +0 -0
  324. sqlspec/core/parameters/_validator.py +171 -0
  325. sqlspec/core/pipeline.cp314-win_amd64.pyd +0 -0
  326. sqlspec/core/pipeline.py +333 -0
  327. sqlspec/core/query_modifiers.cp314-win_amd64.pyd +0 -0
  328. sqlspec/core/query_modifiers.py +508 -0
  329. sqlspec/core/result/__init__.py +25 -0
  330. sqlspec/core/result/_base.cp314-win_amd64.pyd +0 -0
  331. sqlspec/core/result/_base.py +1232 -0
  332. sqlspec/core/result/_io.cp314-win_amd64.pyd +0 -0
  333. sqlspec/core/result/_io.py +28 -0
  334. sqlspec/core/splitter.cp314-win_amd64.pyd +0 -0
  335. sqlspec/core/splitter.py +1021 -0
  336. sqlspec/core/sqlcommenter.cp314-win_amd64.pyd +0 -0
  337. sqlspec/core/sqlcommenter.py +249 -0
  338. sqlspec/core/stack.cp314-win_amd64.pyd +0 -0
  339. sqlspec/core/stack.py +163 -0
  340. sqlspec/core/statement.cp314-win_amd64.pyd +0 -0
  341. sqlspec/core/statement.py +1865 -0
  342. sqlspec/core/type_converter.cp314-win_amd64.pyd +0 -0
  343. sqlspec/core/type_converter.py +340 -0
  344. sqlspec/data_dictionary/__init__.py +22 -0
  345. sqlspec/data_dictionary/_loader.cp314-win_amd64.pyd +0 -0
  346. sqlspec/data_dictionary/_loader.py +138 -0
  347. sqlspec/data_dictionary/_registry.cp314-win_amd64.pyd +0 -0
  348. sqlspec/data_dictionary/_registry.py +74 -0
  349. sqlspec/data_dictionary/_types.cp314-win_amd64.pyd +0 -0
  350. sqlspec/data_dictionary/_types.py +121 -0
  351. sqlspec/data_dictionary/dialects/__init__.py +21 -0
  352. sqlspec/data_dictionary/dialects/bigquery.cp314-win_amd64.pyd +0 -0
  353. sqlspec/data_dictionary/dialects/bigquery.py +81 -0
  354. sqlspec/data_dictionary/dialects/cockroachdb.cp314-win_amd64.pyd +0 -0
  355. sqlspec/data_dictionary/dialects/cockroachdb.py +54 -0
  356. sqlspec/data_dictionary/dialects/duckdb.cp314-win_amd64.pyd +0 -0
  357. sqlspec/data_dictionary/dialects/duckdb.py +47 -0
  358. sqlspec/data_dictionary/dialects/mysql.cp314-win_amd64.pyd +0 -0
  359. sqlspec/data_dictionary/dialects/mysql.py +53 -0
  360. sqlspec/data_dictionary/dialects/oracle.cp314-win_amd64.pyd +0 -0
  361. sqlspec/data_dictionary/dialects/oracle.py +197 -0
  362. sqlspec/data_dictionary/dialects/postgres.cp314-win_amd64.pyd +0 -0
  363. sqlspec/data_dictionary/dialects/postgres.py +69 -0
  364. sqlspec/data_dictionary/dialects/spanner.cp314-win_amd64.pyd +0 -0
  365. sqlspec/data_dictionary/dialects/spanner.py +37 -0
  366. sqlspec/data_dictionary/dialects/sqlite.cp314-win_amd64.pyd +0 -0
  367. sqlspec/data_dictionary/dialects/sqlite.py +59 -0
  368. sqlspec/data_dictionary/sql/.gitkeep +0 -0
  369. sqlspec/data_dictionary/sql/bigquery/columns.sql +23 -0
  370. sqlspec/data_dictionary/sql/bigquery/foreign_keys.sql +34 -0
  371. sqlspec/data_dictionary/sql/bigquery/indexes.sql +19 -0
  372. sqlspec/data_dictionary/sql/bigquery/tables.sql +33 -0
  373. sqlspec/data_dictionary/sql/bigquery/version.sql +3 -0
  374. sqlspec/data_dictionary/sql/cockroachdb/columns.sql +34 -0
  375. sqlspec/data_dictionary/sql/cockroachdb/foreign_keys.sql +40 -0
  376. sqlspec/data_dictionary/sql/cockroachdb/indexes.sql +32 -0
  377. sqlspec/data_dictionary/sql/cockroachdb/tables.sql +44 -0
  378. sqlspec/data_dictionary/sql/cockroachdb/version.sql +3 -0
  379. sqlspec/data_dictionary/sql/duckdb/columns.sql +23 -0
  380. sqlspec/data_dictionary/sql/duckdb/foreign_keys.sql +36 -0
  381. sqlspec/data_dictionary/sql/duckdb/indexes.sql +19 -0
  382. sqlspec/data_dictionary/sql/duckdb/tables.sql +38 -0
  383. sqlspec/data_dictionary/sql/duckdb/version.sql +3 -0
  384. sqlspec/data_dictionary/sql/mysql/columns.sql +23 -0
  385. sqlspec/data_dictionary/sql/mysql/foreign_keys.sql +28 -0
  386. sqlspec/data_dictionary/sql/mysql/indexes.sql +26 -0
  387. sqlspec/data_dictionary/sql/mysql/tables.sql +33 -0
  388. sqlspec/data_dictionary/sql/mysql/version.sql +3 -0
  389. sqlspec/data_dictionary/sql/oracle/columns.sql +23 -0
  390. sqlspec/data_dictionary/sql/oracle/foreign_keys.sql +48 -0
  391. sqlspec/data_dictionary/sql/oracle/indexes.sql +44 -0
  392. sqlspec/data_dictionary/sql/oracle/tables.sql +25 -0
  393. sqlspec/data_dictionary/sql/oracle/version.sql +20 -0
  394. sqlspec/data_dictionary/sql/postgres/columns.sql +34 -0
  395. sqlspec/data_dictionary/sql/postgres/foreign_keys.sql +40 -0
  396. sqlspec/data_dictionary/sql/postgres/indexes.sql +56 -0
  397. sqlspec/data_dictionary/sql/postgres/tables.sql +44 -0
  398. sqlspec/data_dictionary/sql/postgres/version.sql +3 -0
  399. sqlspec/data_dictionary/sql/spanner/columns.sql +23 -0
  400. sqlspec/data_dictionary/sql/spanner/foreign_keys.sql +70 -0
  401. sqlspec/data_dictionary/sql/spanner/indexes.sql +30 -0
  402. sqlspec/data_dictionary/sql/spanner/tables.sql +9 -0
  403. sqlspec/data_dictionary/sql/spanner/version.sql +3 -0
  404. sqlspec/data_dictionary/sql/sqlite/columns.sql +23 -0
  405. sqlspec/data_dictionary/sql/sqlite/foreign_keys.sql +22 -0
  406. sqlspec/data_dictionary/sql/sqlite/indexes.sql +7 -0
  407. sqlspec/data_dictionary/sql/sqlite/tables.sql +28 -0
  408. sqlspec/data_dictionary/sql/sqlite/version.sql +3 -0
  409. sqlspec/dialects/__init__.py +22 -0
  410. sqlspec/dialects/_compat.cp314-win_amd64.pyd +0 -0
  411. sqlspec/dialects/_compat.py +14 -0
  412. sqlspec/dialects/postgres/__init__.py +9 -0
  413. sqlspec/dialects/postgres/_generators.cp314-win_amd64.pyd +0 -0
  414. sqlspec/dialects/postgres/_generators.py +57 -0
  415. sqlspec/dialects/postgres/_operators.cp314-win_amd64.pyd +0 -0
  416. sqlspec/dialects/postgres/_operators.py +81 -0
  417. sqlspec/dialects/postgres/_paradedb.py +50 -0
  418. sqlspec/dialects/postgres/_pgvector.py +36 -0
  419. sqlspec/dialects/spanner/__init__.py +6 -0
  420. sqlspec/dialects/spanner/_generators.cp314-win_amd64.pyd +0 -0
  421. sqlspec/dialects/spanner/_generators.py +206 -0
  422. sqlspec/dialects/spanner/_spangres.py +77 -0
  423. sqlspec/dialects/spanner/_spanner.py +179 -0
  424. sqlspec/driver/__init__.py +49 -0
  425. sqlspec/driver/_async.cp314-win_amd64.pyd +0 -0
  426. sqlspec/driver/_async.py +1830 -0
  427. sqlspec/driver/_common.cp314-win_amd64.pyd +0 -0
  428. sqlspec/driver/_common.py +2292 -0
  429. sqlspec/driver/_exception_handler.cp314-win_amd64.pyd +0 -0
  430. sqlspec/driver/_exception_handler.py +108 -0
  431. sqlspec/driver/_query_cache.cp314-win_amd64.pyd +0 -0
  432. sqlspec/driver/_query_cache.py +96 -0
  433. sqlspec/driver/_sql_helpers.cp314-win_amd64.pyd +0 -0
  434. sqlspec/driver/_sql_helpers.py +139 -0
  435. sqlspec/driver/_storage_helpers.cp314-win_amd64.pyd +0 -0
  436. sqlspec/driver/_storage_helpers.py +153 -0
  437. sqlspec/driver/_sync.cp314-win_amd64.pyd +0 -0
  438. sqlspec/driver/_sync.py +1817 -0
  439. sqlspec/exceptions.cp314-win_amd64.pyd +0 -0
  440. sqlspec/exceptions.py +480 -0
  441. sqlspec/extensions/__init__.py +0 -0
  442. sqlspec/extensions/adk/__init__.py +84 -0
  443. sqlspec/extensions/adk/_config_utils.py +199 -0
  444. sqlspec/extensions/adk/_types.cp314-win_amd64.pyd +0 -0
  445. sqlspec/extensions/adk/_types.py +41 -0
  446. sqlspec/extensions/adk/artifact/__init__.py +57 -0
  447. sqlspec/extensions/adk/artifact/_types.cp314-win_amd64.pyd +0 -0
  448. sqlspec/extensions/adk/artifact/_types.py +32 -0
  449. sqlspec/extensions/adk/artifact/service.py +508 -0
  450. sqlspec/extensions/adk/artifact/store.py +361 -0
  451. sqlspec/extensions/adk/converters.py +212 -0
  452. sqlspec/extensions/adk/memory/__init__.py +69 -0
  453. sqlspec/extensions/adk/memory/_types.cp314-win_amd64.pyd +0 -0
  454. sqlspec/extensions/adk/memory/_types.py +30 -0
  455. sqlspec/extensions/adk/memory/converters.py +225 -0
  456. sqlspec/extensions/adk/memory/service.py +316 -0
  457. sqlspec/extensions/adk/memory/store.py +525 -0
  458. sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +184 -0
  459. sqlspec/extensions/adk/migrations/__init__.py +0 -0
  460. sqlspec/extensions/adk/service.py +279 -0
  461. sqlspec/extensions/adk/store.py +590 -0
  462. sqlspec/extensions/events/__init__.py +51 -0
  463. sqlspec/extensions/events/_channel.py +703 -0
  464. sqlspec/extensions/events/_hints.cp314-win_amd64.pyd +0 -0
  465. sqlspec/extensions/events/_hints.py +45 -0
  466. sqlspec/extensions/events/_models.py +23 -0
  467. sqlspec/extensions/events/_payload.cp314-win_amd64.pyd +0 -0
  468. sqlspec/extensions/events/_payload.py +69 -0
  469. sqlspec/extensions/events/_protocols.py +134 -0
  470. sqlspec/extensions/events/_queue.py +462 -0
  471. sqlspec/extensions/events/_store.py +209 -0
  472. sqlspec/extensions/events/migrations/0001_create_event_queue.py +59 -0
  473. sqlspec/extensions/events/migrations/__init__.py +3 -0
  474. sqlspec/extensions/fastapi/__init__.py +22 -0
  475. sqlspec/extensions/fastapi/extension.py +391 -0
  476. sqlspec/extensions/fastapi/providers.cp314-win_amd64.pyd +0 -0
  477. sqlspec/extensions/fastapi/providers.py +712 -0
  478. sqlspec/extensions/flask/__init__.py +38 -0
  479. sqlspec/extensions/flask/_state.py +87 -0
  480. sqlspec/extensions/flask/_utils.py +71 -0
  481. sqlspec/extensions/flask/extension.py +539 -0
  482. sqlspec/extensions/litestar/__init__.py +31 -0
  483. sqlspec/extensions/litestar/_utils.py +52 -0
  484. sqlspec/extensions/litestar/channels.py +165 -0
  485. sqlspec/extensions/litestar/cli.py +102 -0
  486. sqlspec/extensions/litestar/config.py +90 -0
  487. sqlspec/extensions/litestar/handlers.py +316 -0
  488. sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
  489. sqlspec/extensions/litestar/migrations/__init__.py +3 -0
  490. sqlspec/extensions/litestar/plugin.py +1066 -0
  491. sqlspec/extensions/litestar/providers.cp314-win_amd64.pyd +0 -0
  492. sqlspec/extensions/litestar/providers.py +784 -0
  493. sqlspec/extensions/litestar/store.py +298 -0
  494. sqlspec/extensions/otel/__init__.py +58 -0
  495. sqlspec/extensions/prometheus/__init__.py +113 -0
  496. sqlspec/extensions/sanic/__init__.py +19 -0
  497. sqlspec/extensions/sanic/_state.py +43 -0
  498. sqlspec/extensions/sanic/_utils.py +127 -0
  499. sqlspec/extensions/sanic/extension.py +647 -0
  500. sqlspec/extensions/starlette/__init__.py +22 -0
  501. sqlspec/extensions/starlette/_state.py +42 -0
  502. sqlspec/extensions/starlette/_utils.py +96 -0
  503. sqlspec/extensions/starlette/extension.py +374 -0
  504. sqlspec/extensions/starlette/middleware.py +281 -0
  505. sqlspec/loader.cp314-win_amd64.pyd +0 -0
  506. sqlspec/loader.py +727 -0
  507. sqlspec/migrations/__init__.py +39 -0
  508. sqlspec/migrations/base.cp314-win_amd64.pyd +0 -0
  509. sqlspec/migrations/base.py +862 -0
  510. sqlspec/migrations/commands.py +2151 -0
  511. sqlspec/migrations/context.cp314-win_amd64.pyd +0 -0
  512. sqlspec/migrations/context.py +157 -0
  513. sqlspec/migrations/fix.cp314-win_amd64.pyd +0 -0
  514. sqlspec/migrations/fix.py +204 -0
  515. sqlspec/migrations/loaders.cp314-win_amd64.pyd +0 -0
  516. sqlspec/migrations/loaders.py +443 -0
  517. sqlspec/migrations/runner.cp314-win_amd64.pyd +0 -0
  518. sqlspec/migrations/runner.py +1195 -0
  519. sqlspec/migrations/squash.cp314-win_amd64.pyd +0 -0
  520. sqlspec/migrations/squash.py +490 -0
  521. sqlspec/migrations/templates.cp314-win_amd64.pyd +0 -0
  522. sqlspec/migrations/templates.py +234 -0
  523. sqlspec/migrations/tracker.cp314-win_amd64.pyd +0 -0
  524. sqlspec/migrations/tracker.py +792 -0
  525. sqlspec/migrations/utils.cp314-win_amd64.pyd +0 -0
  526. sqlspec/migrations/utils.py +256 -0
  527. sqlspec/migrations/validation.cp314-win_amd64.pyd +0 -0
  528. sqlspec/migrations/validation.py +359 -0
  529. sqlspec/migrations/version.cp314-win_amd64.pyd +0 -0
  530. sqlspec/migrations/version.py +446 -0
  531. sqlspec/observability/__init__.py +57 -0
  532. sqlspec/observability/_common.cp314-win_amd64.pyd +0 -0
  533. sqlspec/observability/_common.py +77 -0
  534. sqlspec/observability/_config.cp314-win_amd64.pyd +0 -0
  535. sqlspec/observability/_config.py +364 -0
  536. sqlspec/observability/_diagnostics.cp314-win_amd64.pyd +0 -0
  537. sqlspec/observability/_diagnostics.py +74 -0
  538. sqlspec/observability/_dispatcher.cp314-win_amd64.pyd +0 -0
  539. sqlspec/observability/_dispatcher.py +200 -0
  540. sqlspec/observability/_formatters/__init__.py +13 -0
  541. sqlspec/observability/_formatters/_aws.cp314-win_amd64.pyd +0 -0
  542. sqlspec/observability/_formatters/_aws.py +102 -0
  543. sqlspec/observability/_formatters/_azure.cp314-win_amd64.pyd +0 -0
  544. sqlspec/observability/_formatters/_azure.py +96 -0
  545. sqlspec/observability/_formatters/_base.cp314-win_amd64.pyd +0 -0
  546. sqlspec/observability/_formatters/_base.py +57 -0
  547. sqlspec/observability/_formatters/_gcp.cp314-win_amd64.pyd +0 -0
  548. sqlspec/observability/_formatters/_gcp.py +131 -0
  549. sqlspec/observability/_formatting.py +58 -0
  550. sqlspec/observability/_observer.cp314-win_amd64.pyd +0 -0
  551. sqlspec/observability/_observer.py +361 -0
  552. sqlspec/observability/_runtime.cp314-win_amd64.pyd +0 -0
  553. sqlspec/observability/_runtime.py +461 -0
  554. sqlspec/observability/_sampling.cp314-win_amd64.pyd +0 -0
  555. sqlspec/observability/_sampling.py +188 -0
  556. sqlspec/observability/_spans.cp314-win_amd64.pyd +0 -0
  557. sqlspec/observability/_spans.py +161 -0
  558. sqlspec/protocols.py +955 -0
  559. sqlspec/py.typed +0 -0
  560. sqlspec/service.py +433 -0
  561. sqlspec/storage/__init__.py +48 -0
  562. sqlspec/storage/_arrow_payload.py +68 -0
  563. sqlspec/storage/_paths.cp314-win_amd64.pyd +0 -0
  564. sqlspec/storage/_paths.py +58 -0
  565. sqlspec/storage/_utils.py +46 -0
  566. sqlspec/storage/backends/__init__.py +1 -0
  567. sqlspec/storage/backends/base.cp314-win_amd64.pyd +0 -0
  568. sqlspec/storage/backends/base.py +374 -0
  569. sqlspec/storage/backends/fsspec.py +574 -0
  570. sqlspec/storage/backends/local.py +468 -0
  571. sqlspec/storage/backends/obstore.py +956 -0
  572. sqlspec/storage/errors.cp314-win_amd64.pyd +0 -0
  573. sqlspec/storage/errors.py +102 -0
  574. sqlspec/storage/pipeline.cp314-win_amd64.pyd +0 -0
  575. sqlspec/storage/pipeline.py +628 -0
  576. sqlspec/storage/registry.cp314-win_amd64.pyd +0 -0
  577. sqlspec/storage/registry.py +329 -0
  578. sqlspec/typing.py +405 -0
  579. sqlspec/utils/__init__.py +7 -0
  580. sqlspec/utils/arrow_helpers.py +384 -0
  581. sqlspec/utils/config_tools.cp314-win_amd64.pyd +0 -0
  582. sqlspec/utils/config_tools.py +314 -0
  583. sqlspec/utils/correlation.cp314-win_amd64.pyd +0 -0
  584. sqlspec/utils/correlation.py +134 -0
  585. sqlspec/utils/deprecation.cp314-win_amd64.pyd +0 -0
  586. sqlspec/utils/deprecation.py +157 -0
  587. sqlspec/utils/dispatch.cp314-win_amd64.pyd +0 -0
  588. sqlspec/utils/dispatch.py +101 -0
  589. sqlspec/utils/fixtures.cp314-win_amd64.pyd +0 -0
  590. sqlspec/utils/fixtures.py +260 -0
  591. sqlspec/utils/logging.cp314-win_amd64.pyd +0 -0
  592. sqlspec/utils/logging.py +251 -0
  593. sqlspec/utils/module_loader.py +306 -0
  594. sqlspec/utils/portal.cp314-win_amd64.pyd +0 -0
  595. sqlspec/utils/portal.py +377 -0
  596. sqlspec/utils/schema.cp314-win_amd64.pyd +0 -0
  597. sqlspec/utils/schema.py +1040 -0
  598. sqlspec/utils/serializers/__init__.py +30 -0
  599. sqlspec/utils/serializers/_json.cp314-win_amd64.pyd +0 -0
  600. sqlspec/utils/serializers/_json.py +415 -0
  601. sqlspec/utils/serializers/_numpy.cp314-win_amd64.pyd +0 -0
  602. sqlspec/utils/serializers/_numpy.py +65 -0
  603. sqlspec/utils/serializers/_schema.cp314-win_amd64.pyd +0 -0
  604. sqlspec/utils/serializers/_schema.py +285 -0
  605. sqlspec/utils/singleton.cp314-win_amd64.pyd +0 -0
  606. sqlspec/utils/singleton.py +41 -0
  607. sqlspec/utils/sync_tools.cp314-win_amd64.pyd +0 -0
  608. sqlspec/utils/sync_tools.py +316 -0
  609. sqlspec/utils/text.cp314-win_amd64.pyd +0 -0
  610. sqlspec/utils/text.py +109 -0
  611. sqlspec/utils/type_converters.cp314-win_amd64.pyd +0 -0
  612. sqlspec/utils/type_converters.py +216 -0
  613. sqlspec/utils/type_guards.cp314-win_amd64.pyd +0 -0
  614. sqlspec/utils/type_guards.py +1508 -0
  615. sqlspec/utils/uuids.cp314-win_amd64.pyd +0 -0
  616. sqlspec/utils/uuids.py +241 -0
  617. sqlspec-0.47.0.dist-info/METADATA +202 -0
  618. sqlspec-0.47.0.dist-info/RECORD +621 -0
  619. sqlspec-0.47.0.dist-info/WHEEL +4 -0
  620. sqlspec-0.47.0.dist-info/entry_points.txt +6 -0
  621. sqlspec-0.47.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,1508 @@
1
+ """Type guard functions for runtime type checking in SQLSpec.
2
+
3
+ This module provides type-safe runtime checks that help the type checker
4
+ understand type narrowing, replacing defensive hasattr() and duck typing patterns.
5
+ """
6
+
7
+ from collections.abc import Sequence
8
+ from collections.abc import Set as AbstractSet
9
+ from dataclasses import Field
10
+ from dataclasses import fields as dataclasses_fields
11
+ from dataclasses import is_dataclass as dataclasses_is_dataclass
12
+ from functools import lru_cache
13
+ from typing import TYPE_CHECKING, Any, cast
14
+
15
+ from sqlglot import exp
16
+ from typing_extensions import is_typeddict
17
+
18
+ from sqlspec._typing import Empty
19
+ from sqlspec.protocols import (
20
+ DictProtocol,
21
+ HasExpressionAndParametersProtocol,
22
+ HasExpressionAndSQLProtocol,
23
+ HasExpressionProtocol,
24
+ HasMigrationConfigProtocol,
25
+ HasParameterBuilderProtocol,
26
+ HasSQLGlotExpressionProtocol,
27
+ HasStatementConfigFactoryProtocol,
28
+ HasValueProtocol,
29
+ SupportsArrowResults,
30
+ WithMethodProtocol,
31
+ )
32
+ from sqlspec.typing import (
33
+ ATTRS_INSTALLED,
34
+ LITESTAR_INSTALLED,
35
+ MSGSPEC_INSTALLED,
36
+ PYDANTIC_INSTALLED,
37
+ BaseModel,
38
+ DataclassProtocol,
39
+ DTOData,
40
+ Struct,
41
+ attrs_fields,
42
+ attrs_has,
43
+ )
44
+ from sqlspec.utils.text import camelize, kebabize, pascalize
45
+
46
+ if TYPE_CHECKING:
47
+ from typing import TypeGuard
48
+
49
+ from sqlspec._typing import AttrsInstanceStub, BaseModelStub, DTODataStub, StructStub
50
+ from sqlspec.core import StatementFilter
51
+ from sqlspec.core.parameters import TypedParameter
52
+ from sqlspec.protocols import (
53
+ ArrowTableStatsProtocol,
54
+ AsyncDeleteProtocol,
55
+ AsyncReadableProtocol,
56
+ AsyncReadBytesProtocol,
57
+ AsyncWriteBytesProtocol,
58
+ CursorMetadataProtocol,
59
+ HasAddListenerProtocol,
60
+ HasAsDictProtocol,
61
+ HasConfigProtocol,
62
+ HasConnectionConfigProtocol,
63
+ HasDatabaseUrlAndBindKeyProtocol,
64
+ HasErrorsProtocol,
65
+ HasExtensionConfigProtocol,
66
+ HasFieldNameProtocol,
67
+ HasFilterAttributesProtocol,
68
+ HasGetDataProtocol,
69
+ HasLastRowIdProtocol,
70
+ HasNameProtocol,
71
+ HasNotifiesProtocol,
72
+ HasRowcountProtocol,
73
+ HasSqliteErrorProtocol,
74
+ HasSqlStateProtocol,
75
+ HasStatementTypeProtocol,
76
+ HasTracerProviderProtocol,
77
+ HasTypeCodeProtocol,
78
+ HasTypecodeProtocol,
79
+ HasTypecodeSizedProtocol,
80
+ HasWhereProtocol,
81
+ MappingLikeProtocol,
82
+ NotificationProtocol,
83
+ PipelineCapableProtocol,
84
+ QueryResultProtocol,
85
+ ReadableProtocol,
86
+ SpanAttributeProtocol,
87
+ SupportsArrayProtocol,
88
+ SupportsCloseProtocol,
89
+ SupportsDtypeStrProtocol,
90
+ SupportsJsonTypeProtocol,
91
+ )
92
+ from sqlspec.typing import SupportedSchemaModel
93
+
94
+ __all__ = (
95
+ "dataclass_to_dict",
96
+ "expression_has_limit",
97
+ "extract_dataclass_fields",
98
+ "extract_dataclass_items",
99
+ "get_initial_expression",
100
+ "get_literal_parent",
101
+ "get_msgspec_rename_config",
102
+ "get_node_expressions",
103
+ "get_node_this",
104
+ "get_param_style_and_name",
105
+ "get_value_attribute",
106
+ "has_add_listener",
107
+ "has_array_interface",
108
+ "has_arrow_table_stats",
109
+ "has_asdict_method",
110
+ "has_config_attribute",
111
+ "has_connection_config",
112
+ "has_cursor_metadata",
113
+ "has_database_url_and_bind_key",
114
+ "has_dict_attribute",
115
+ "has_dtype_str",
116
+ "has_errors",
117
+ "has_expression_and_parameters",
118
+ "has_expression_and_sql",
119
+ "has_expression_attr",
120
+ "has_expressions_attribute",
121
+ "has_extension_config",
122
+ "has_field_name",
123
+ "has_filter_attributes",
124
+ "has_get_data",
125
+ "has_lastrowid",
126
+ "has_migration_config",
127
+ "has_name",
128
+ "has_notifies",
129
+ "has_parameter_builder",
130
+ "has_parent_attribute",
131
+ "has_pipeline_capability",
132
+ "has_query_result_metadata",
133
+ "has_rowcount",
134
+ "has_span_attribute",
135
+ "has_sqlglot_expression",
136
+ "has_sqlite_error",
137
+ "has_sqlstate",
138
+ "has_statement_config_factory",
139
+ "has_statement_type",
140
+ "has_this_attribute",
141
+ "has_tracer_provider",
142
+ "has_type_code",
143
+ "has_typecode",
144
+ "has_typecode_and_len",
145
+ "has_value_attribute",
146
+ "has_with_method",
147
+ "is_async_readable",
148
+ "is_attrs_instance",
149
+ "is_attrs_instance_with_field",
150
+ "is_attrs_instance_without_field",
151
+ "is_attrs_schema",
152
+ "is_copy_statement",
153
+ "is_dataclass",
154
+ "is_dataclass_instance",
155
+ "is_dataclass_with_field",
156
+ "is_dataclass_without_field",
157
+ "is_dict",
158
+ "is_dict_row",
159
+ "is_dict_with_field",
160
+ "is_dict_without_field",
161
+ "is_dto_data",
162
+ "is_expression",
163
+ "is_iterable_parameters",
164
+ "is_local_path",
165
+ "is_mapping_like",
166
+ "is_msgspec_struct",
167
+ "is_msgspec_struct_with_field",
168
+ "is_msgspec_struct_without_field",
169
+ "is_notification",
170
+ "is_number_literal",
171
+ "is_pydantic_model",
172
+ "is_pydantic_model_with_field",
173
+ "is_pydantic_model_without_field",
174
+ "is_readable",
175
+ "is_schema",
176
+ "is_schema_or_dict",
177
+ "is_schema_or_dict_with_field",
178
+ "is_schema_or_dict_without_field",
179
+ "is_schema_with_field",
180
+ "is_schema_without_field",
181
+ "is_statement_filter",
182
+ "is_string_literal",
183
+ "is_typed_dict",
184
+ "is_typed_parameter",
185
+ "supports_arrow_results",
186
+ "supports_async_delete",
187
+ "supports_async_read_bytes",
188
+ "supports_async_write_bytes",
189
+ "supports_close",
190
+ "supports_json_type",
191
+ "supports_where",
192
+ )
193
+
194
+
195
+ def is_readable(obj: Any) -> "TypeGuard[ReadableProtocol]":
196
+ """Check if an object is readable (has a read method)."""
197
+ try:
198
+ return callable(obj.read)
199
+ except AttributeError:
200
+ return False
201
+
202
+
203
+ def is_async_readable(obj: Any) -> "TypeGuard[AsyncReadableProtocol]":
204
+ """Check if an object exposes an async read method."""
205
+ try:
206
+ return callable(obj.read)
207
+ except AttributeError:
208
+ return False
209
+
210
+
211
+ def is_notification(obj: Any) -> "TypeGuard[NotificationProtocol]":
212
+ """Check if an object is a database notification with channel and payload."""
213
+ try:
214
+ return hasattr(obj, "channel") and hasattr(obj, "payload")
215
+ except AttributeError:
216
+ return False
217
+
218
+
219
+ def has_pipeline_capability(obj: Any) -> "TypeGuard[PipelineCapableProtocol]":
220
+ """Check if a connection supports pipeline execution."""
221
+ try:
222
+ return callable(obj.run_pipeline)
223
+ except AttributeError:
224
+ return False
225
+
226
+
227
+ def has_query_result_metadata(obj: Any) -> "TypeGuard[QueryResultProtocol]":
228
+ """Check if an object has query result metadata (tag/status)."""
229
+ try:
230
+ return hasattr(obj, "tag") or hasattr(obj, "status")
231
+ except AttributeError:
232
+ return False
233
+
234
+
235
+ def has_array_interface(obj: Any) -> "TypeGuard[SupportsArrayProtocol]":
236
+ """Check if an object supports the array interface (like NumPy arrays)."""
237
+ try:
238
+ return hasattr(obj, "__array__")
239
+ except AttributeError:
240
+ return False
241
+
242
+
243
+ def has_cursor_metadata(obj: Any) -> "TypeGuard[CursorMetadataProtocol]":
244
+ """Check if an object has cursor metadata (description)."""
245
+ try:
246
+ return hasattr(obj, "description")
247
+ except AttributeError:
248
+ return False
249
+
250
+
251
+ def has_add_listener(obj: Any) -> "TypeGuard[HasAddListenerProtocol]":
252
+ """Check if an object exposes add_listener()."""
253
+ try:
254
+ return callable(obj.add_listener)
255
+ except AttributeError:
256
+ return False
257
+
258
+
259
+ def has_notifies(obj: Any) -> "TypeGuard[HasNotifiesProtocol]":
260
+ """Check if an object exposes notifies."""
261
+ try:
262
+ return hasattr(obj, "notifies")
263
+ except AttributeError:
264
+ return False
265
+
266
+
267
+ def has_extension_config(obj: Any) -> "TypeGuard[HasExtensionConfigProtocol]":
268
+ """Check if an object exposes extension_config mapping."""
269
+ try:
270
+ return hasattr(obj, "extension_config")
271
+ except AttributeError:
272
+ return False
273
+
274
+
275
+ def has_config_attribute(obj: Any) -> "TypeGuard[HasConfigProtocol]":
276
+ """Check if an object exposes config attribute."""
277
+ try:
278
+ return hasattr(obj, "config")
279
+ except AttributeError:
280
+ return False
281
+
282
+
283
+ def has_connection_config(obj: Any) -> "TypeGuard[HasConnectionConfigProtocol]":
284
+ """Check if an object exposes connection_config mapping."""
285
+ try:
286
+ return hasattr(obj, "connection_config")
287
+ except AttributeError:
288
+ return False
289
+
290
+
291
+ def has_database_url_and_bind_key(obj: Any) -> "TypeGuard[HasDatabaseUrlAndBindKeyProtocol]":
292
+ """Check if an object exposes database_url and bind_key."""
293
+ try:
294
+ return hasattr(obj, "database_url") and hasattr(obj, "bind_key")
295
+ except AttributeError:
296
+ return False
297
+
298
+
299
+ def has_name(obj: Any) -> "TypeGuard[HasNameProtocol]":
300
+ """Check if an object exposes __name__."""
301
+ try:
302
+ return hasattr(obj, "__name__")
303
+ except AttributeError:
304
+ return False
305
+
306
+
307
+ def has_field_name(obj: Any) -> "TypeGuard[HasFieldNameProtocol]":
308
+ """Check if an object exposes field_name attribute."""
309
+ try:
310
+ return hasattr(obj, "field_name")
311
+ except AttributeError:
312
+ return False
313
+
314
+
315
+ def has_filter_attributes(obj: Any) -> "TypeGuard[HasFilterAttributesProtocol]":
316
+ """Check if an object exposes filter attribute set."""
317
+ try:
318
+ return hasattr(obj, "field_name") and hasattr(obj, "operation") and hasattr(obj, "value")
319
+ except AttributeError:
320
+ return False
321
+
322
+
323
+ def has_get_data(obj: Any) -> "TypeGuard[HasGetDataProtocol]":
324
+ """Check if an object exposes get_data()."""
325
+ try:
326
+ return callable(obj.get_data)
327
+ except AttributeError:
328
+ return False
329
+
330
+
331
+ def has_arrow_table_stats(obj: Any) -> "TypeGuard[ArrowTableStatsProtocol]":
332
+ """Check if an object exposes Arrow row/byte stats."""
333
+ try:
334
+ return hasattr(obj, "num_rows") and hasattr(obj, "nbytes")
335
+ except AttributeError:
336
+ return False
337
+
338
+
339
+ def has_rowcount(obj: Any) -> "TypeGuard[HasRowcountProtocol]":
340
+ """Check if a cursor exposes rowcount metadata."""
341
+ try:
342
+ return hasattr(obj, "rowcount")
343
+ except AttributeError:
344
+ return False
345
+
346
+
347
+ def has_lastrowid(obj: Any) -> "TypeGuard[HasLastRowIdProtocol]":
348
+ """Check if a cursor exposes lastrowid metadata."""
349
+ try:
350
+ return hasattr(obj, "lastrowid")
351
+ except AttributeError:
352
+ return False
353
+
354
+
355
+ def has_dtype_str(obj: Any) -> "TypeGuard[SupportsDtypeStrProtocol]":
356
+ """Check if a dtype exposes string descriptor."""
357
+ try:
358
+ return hasattr(obj, "str")
359
+ except AttributeError:
360
+ return False
361
+
362
+
363
+ def has_statement_type(obj: Any) -> "TypeGuard[HasStatementTypeProtocol]":
364
+ """Check if a cursor exposes statement_type metadata."""
365
+ try:
366
+ return hasattr(obj, "statement_type")
367
+ except AttributeError:
368
+ return False
369
+
370
+
371
+ def has_typecode(obj: Any) -> "TypeGuard[HasTypecodeProtocol]":
372
+ """Check if an array-like object exposes typecode."""
373
+ try:
374
+ return hasattr(obj, "typecode")
375
+ except AttributeError:
376
+ return False
377
+
378
+
379
+ def has_typecode_and_len(obj: Any) -> "TypeGuard[HasTypecodeSizedProtocol]":
380
+ """Check if an array-like object exposes typecode and length."""
381
+ try:
382
+ return hasattr(obj, "typecode") and hasattr(obj, "__len__")
383
+ except AttributeError:
384
+ return False
385
+
386
+
387
+ def has_type_code(obj: Any) -> "TypeGuard[HasTypeCodeProtocol]":
388
+ """Check if an object exposes type_code."""
389
+ try:
390
+ return hasattr(obj, "type_code")
391
+ except AttributeError:
392
+ return False
393
+
394
+
395
+ def has_sqlstate(obj: Any) -> "TypeGuard[HasSqlStateProtocol]":
396
+ """Check if an exception exposes sqlstate."""
397
+ try:
398
+ return hasattr(obj, "sqlstate")
399
+ except AttributeError:
400
+ return False
401
+
402
+
403
+ def has_sqlite_error(obj: Any) -> "TypeGuard[HasSqliteErrorProtocol]":
404
+ """Check if an exception exposes sqlite error details."""
405
+ try:
406
+ return hasattr(obj, "sqlite_errorcode")
407
+ except AttributeError:
408
+ return False
409
+
410
+
411
+ def has_value_attribute(obj: Any) -> "TypeGuard[HasValueProtocol]":
412
+ """Check if an object exposes a value attribute."""
413
+ try:
414
+ return hasattr(obj, "value")
415
+ except AttributeError:
416
+ return False
417
+
418
+
419
+ def has_errors(obj: Any) -> "TypeGuard[HasErrorsProtocol]":
420
+ """Check if an exception exposes errors."""
421
+ try:
422
+ return hasattr(obj, "errors")
423
+ except AttributeError:
424
+ return False
425
+
426
+
427
+ def has_span_attribute(obj: Any) -> "TypeGuard[SpanAttributeProtocol]":
428
+ """Check if a span exposes set_attribute."""
429
+ try:
430
+ return callable(obj.set_attribute)
431
+ except AttributeError:
432
+ return False
433
+
434
+
435
+ def has_tracer_provider(obj: Any) -> "TypeGuard[HasTracerProviderProtocol]":
436
+ """Check if an object exposes get_tracer."""
437
+ try:
438
+ return callable(obj.get_tracer)
439
+ except AttributeError:
440
+ return False
441
+
442
+
443
+ def supports_async_read_bytes(obj: Any) -> "TypeGuard[AsyncReadBytesProtocol]":
444
+ """Check if backend supports async read_bytes."""
445
+ try:
446
+ return callable(obj.read_bytes_async)
447
+ except AttributeError:
448
+ return False
449
+
450
+
451
+ def supports_async_write_bytes(obj: Any) -> "TypeGuard[AsyncWriteBytesProtocol]":
452
+ """Check if backend supports async write_bytes."""
453
+ try:
454
+ return callable(obj.write_bytes_async)
455
+ except AttributeError:
456
+ return False
457
+
458
+
459
+ def supports_json_type(obj: Any) -> "TypeGuard[SupportsJsonTypeProtocol]":
460
+ """Check if an object exposes JSON type support."""
461
+ try:
462
+ return hasattr(obj, "JSON")
463
+ except AttributeError:
464
+ return False
465
+
466
+
467
+ def supports_close(obj: Any) -> "TypeGuard[SupportsCloseProtocol]":
468
+ """Check if an object exposes close()."""
469
+ try:
470
+ return callable(obj.close)
471
+ except AttributeError:
472
+ return False
473
+
474
+
475
+ def supports_async_delete(obj: Any) -> "TypeGuard[AsyncDeleteProtocol]":
476
+ """Check if backend supports async delete."""
477
+ try:
478
+ return callable(obj.delete_async)
479
+ except AttributeError:
480
+ return False
481
+
482
+
483
+ def supports_where(obj: Any) -> "TypeGuard[HasWhereProtocol]":
484
+ """Check if an SQL expression supports WHERE clauses."""
485
+ try:
486
+ return callable(obj.where)
487
+ except AttributeError:
488
+ return False
489
+
490
+
491
+ def is_typed_dict(obj: Any) -> "TypeGuard[type]":
492
+ """Check if an object is a TypedDict class.
493
+
494
+ Args:
495
+ obj: The object to check
496
+
497
+ Returns:
498
+ True if the object is a TypedDict class, False otherwise
499
+ """
500
+ return is_typeddict(obj)
501
+
502
+
503
+ def is_statement_filter(obj: Any) -> "TypeGuard[StatementFilter]":
504
+ """Check if an object implements the StatementFilter protocol.
505
+
506
+ Args:
507
+ obj: The object to check
508
+
509
+ Returns:
510
+ True if the object is a StatementFilter, False otherwise
511
+ """
512
+ return getattr(obj, "_is_statement_filter", False) is True
513
+
514
+
515
+ def is_dict_row(row: Any) -> "TypeGuard[dict[str, Any]]":
516
+ """Check if a row is a dictionary.
517
+
518
+ Args:
519
+ row: The row to check
520
+
521
+ Returns:
522
+ True if the row is a dictionary, False otherwise
523
+ """
524
+ return type(row) is dict
525
+
526
+
527
+ def is_mapping_like(obj: Any) -> "TypeGuard[MappingLikeProtocol]":
528
+ """Check if an object can be converted to dict via dict() constructor.
529
+
530
+ This matches database row types like sqlite3.Row, asyncpg.Record, psycopg.Row
531
+ that have keys() method and support __getitem__ access.
532
+
533
+ Args:
534
+ obj: The object to check
535
+
536
+ Returns:
537
+ True if the object has keys() method and __getitem__, False otherwise
538
+ """
539
+ try:
540
+ return callable(obj.keys)
541
+ except AttributeError:
542
+ return False
543
+
544
+
545
+ def has_asdict_method(obj: Any) -> "TypeGuard[HasAsDictProtocol]":
546
+ """Check if an object has _asdict() method (e.g., NamedTuple).
547
+
548
+ Args:
549
+ obj: The object to check
550
+
551
+ Returns:
552
+ True if the object has _asdict() method, False otherwise
553
+ """
554
+ try:
555
+ return callable(obj._asdict)
556
+ except AttributeError:
557
+ return False
558
+
559
+
560
+ def is_iterable_parameters(parameters: Any) -> "TypeGuard[Sequence[Any]]":
561
+ """Check if parameters are iterable (but not string or dict).
562
+
563
+ Args:
564
+ parameters: The parameters to check
565
+
566
+ Returns:
567
+ True if the parameters are iterable, False otherwise
568
+ """
569
+ return isinstance(parameters, Sequence) and not isinstance(parameters, (str, bytes, dict))
570
+
571
+
572
+ def has_with_method(obj: Any) -> "TypeGuard[WithMethodProtocol]":
573
+ """Check if an object has a callable 'with_' method.
574
+
575
+ This is a more specific check than hasattr for SQLGlot expressions.
576
+
577
+ Args:
578
+ obj: The object to check
579
+
580
+ Returns:
581
+ True if the object has a callable with_ method, False otherwise
582
+ """
583
+ return isinstance(obj, WithMethodProtocol)
584
+
585
+
586
+ def is_dataclass_instance(obj: Any) -> "TypeGuard[DataclassProtocol]":
587
+ """Check if an object is a dataclass instance.
588
+
589
+ Args:
590
+ obj: An object to check.
591
+
592
+ Returns:
593
+ True if the object is a dataclass instance.
594
+ """
595
+ if isinstance(obj, type):
596
+ return False
597
+ return dataclasses_is_dataclass(obj)
598
+
599
+
600
+ def is_dataclass(obj: Any) -> "TypeGuard[DataclassProtocol]":
601
+ """Check if an object is a dataclass.
602
+
603
+ Args:
604
+ obj: Value to check.
605
+
606
+ Returns:
607
+ bool
608
+ """
609
+ return dataclasses_is_dataclass(obj)
610
+
611
+
612
+ def is_dataclass_with_field(obj: Any, field_name: str) -> "TypeGuard[DataclassProtocol]":
613
+ """Check if an object is a dataclass and has a specific field.
614
+
615
+ Args:
616
+ obj: Value to check.
617
+ field_name: Field name to check for.
618
+
619
+ Returns:
620
+ bool
621
+ """
622
+ if not is_dataclass(obj):
623
+ return False
624
+ return any(field.name == field_name for field in dataclasses_fields(obj))
625
+
626
+
627
+ def is_dataclass_without_field(obj: Any, field_name: str) -> "TypeGuard[DataclassProtocol]":
628
+ """Check if an object is a dataclass and does not have a specific field.
629
+
630
+ Args:
631
+ obj: Value to check.
632
+ field_name: Field name to check for.
633
+
634
+ Returns:
635
+ bool
636
+ """
637
+ if not is_dataclass(obj):
638
+ return False
639
+ return all(field.name != field_name for field in dataclasses_fields(obj))
640
+
641
+
642
+ def is_pydantic_model(obj: Any) -> "TypeGuard[BaseModelStub]":
643
+ """Check if a value is a pydantic model class or instance.
644
+
645
+ Args:
646
+ obj: Value to check.
647
+
648
+ Returns:
649
+ bool
650
+ """
651
+ if not PYDANTIC_INSTALLED:
652
+ return False
653
+ if isinstance(obj, type):
654
+ try:
655
+ return issubclass(obj, BaseModel)
656
+ except TypeError:
657
+ return False
658
+ return isinstance(obj, BaseModel)
659
+
660
+
661
+ def is_pydantic_model_with_field(obj: Any, field_name: str) -> "TypeGuard[BaseModelStub]":
662
+ """Check if a pydantic model has a specific field.
663
+
664
+ Args:
665
+ obj: Value to check.
666
+ field_name: Field name to check for.
667
+
668
+ Returns:
669
+ bool
670
+ """
671
+ if not is_pydantic_model(obj):
672
+ return False
673
+ try:
674
+ fields = obj.model_fields
675
+ except AttributeError:
676
+ try:
677
+ fields = obj.__fields__ # type: ignore[attr-defined]
678
+ except AttributeError:
679
+ return False
680
+ return field_name in fields
681
+
682
+
683
+ def is_pydantic_model_without_field(obj: Any, field_name: str) -> "TypeGuard[BaseModelStub]":
684
+ """Check if a pydantic model does not have a specific field.
685
+
686
+ Args:
687
+ obj: Value to check.
688
+ field_name: Field name to check for.
689
+
690
+ Returns:
691
+ bool
692
+ """
693
+ if not is_pydantic_model(obj):
694
+ return False
695
+ try:
696
+ fields = obj.model_fields
697
+ except AttributeError:
698
+ try:
699
+ fields = obj.__fields__ # type: ignore[attr-defined]
700
+ except AttributeError:
701
+ return True
702
+ return field_name not in fields
703
+
704
+
705
+ def is_msgspec_struct(obj: Any) -> "TypeGuard[StructStub]":
706
+ """Check if a value is a msgspec struct class or instance.
707
+
708
+ Args:
709
+ obj: Value to check.
710
+
711
+ Returns:
712
+ bool
713
+ """
714
+ if not MSGSPEC_INSTALLED:
715
+ return False
716
+ if isinstance(obj, type):
717
+ try:
718
+ return issubclass(obj, Struct)
719
+ except TypeError:
720
+ return False
721
+ return isinstance(obj, Struct)
722
+
723
+
724
+ def is_msgspec_struct_with_field(obj: Any, field_name: str) -> "TypeGuard[StructStub]":
725
+ """Check if a msgspec struct has a specific field.
726
+
727
+ Args:
728
+ obj: Value to check.
729
+ field_name: Field name to check for.
730
+
731
+ Returns:
732
+ bool
733
+ """
734
+ if not is_msgspec_struct(obj):
735
+ return False
736
+ from msgspec import structs
737
+
738
+ struct_type = obj if isinstance(obj, type) else type(obj)
739
+ fields = structs.fields(cast("Any", struct_type))
740
+ return any(field.name == field_name for field in fields)
741
+
742
+
743
+ def is_msgspec_struct_without_field(obj: Any, field_name: str) -> "TypeGuard[StructStub]":
744
+ """Check if a msgspec struct does not have a specific field.
745
+
746
+ Args:
747
+ obj: Value to check.
748
+ field_name: Field name to check for.
749
+
750
+ Returns:
751
+ bool
752
+ """
753
+ if not is_msgspec_struct(obj):
754
+ return False
755
+ from msgspec import structs
756
+
757
+ struct_type = obj if isinstance(obj, type) else type(obj)
758
+ fields = structs.fields(cast("Any", struct_type))
759
+ return all(field.name != field_name for field in fields)
760
+
761
+
762
+ @lru_cache(maxsize=500)
763
+ def _detect_rename_pattern(field_name: str, encode_name: str) -> "str | None":
764
+ """Detect the rename pattern by comparing field name transformations.
765
+
766
+ Args:
767
+ field_name: Original field name (e.g., "user_id")
768
+ encode_name: Encoded field name (e.g., "userId")
769
+
770
+ Returns:
771
+ The detected rename pattern ("camel", "kebab", "pascal") or None
772
+ """
773
+ if encode_name == camelize(field_name) and encode_name != field_name:
774
+ return "camel"
775
+
776
+ if encode_name == kebabize(field_name) and encode_name != field_name:
777
+ return "kebab"
778
+
779
+ if encode_name == pascalize(field_name) and encode_name != field_name:
780
+ return "pascal"
781
+ return None
782
+
783
+
784
+ def get_msgspec_rename_config(schema_type: type) -> "str | None":
785
+ """Extract msgspec rename configuration from a struct type.
786
+
787
+ Analyzes field name transformations to detect the rename pattern used by msgspec.
788
+ Since msgspec doesn't store the original rename parameter directly, we infer it
789
+ by comparing field names with their encode_name values.
790
+
791
+ Args:
792
+ schema_type: The msgspec struct type to inspect.
793
+
794
+ Returns:
795
+ The rename configuration value ("camel", "kebab", "pascal", etc.) if detected,
796
+ None if no rename configuration exists or if not a msgspec struct.
797
+
798
+ Examples:
799
+ >>> class User(msgspec.Struct, rename="camel"):
800
+ ... user_id: int
801
+ >>> get_msgspec_rename_config(User)
802
+ "camel"
803
+
804
+ >>> class Product(msgspec.Struct):
805
+ ... product_id: int
806
+ >>> get_msgspec_rename_config(Product)
807
+ None
808
+ """
809
+ if not MSGSPEC_INSTALLED:
810
+ return None
811
+
812
+ if not is_msgspec_struct(schema_type):
813
+ return None
814
+
815
+ from msgspec import structs
816
+
817
+ fields: tuple[Any, ...] = structs.fields(cast("Any", schema_type))
818
+ if not fields:
819
+ return None
820
+
821
+ for field in fields:
822
+ if field.name != field.encode_name:
823
+ return _detect_rename_pattern(field.name, field.encode_name)
824
+
825
+ return None
826
+
827
+
828
+ def is_attrs_instance(obj: Any) -> "TypeGuard[AttrsInstanceStub]":
829
+ """Check if a value is an attrs class instance.
830
+
831
+ Args:
832
+ obj: Value to check.
833
+
834
+ Returns:
835
+ bool
836
+ """
837
+ return bool(ATTRS_INSTALLED) and attrs_has(obj.__class__)
838
+
839
+
840
+ def is_attrs_schema(cls: Any) -> "TypeGuard[type[AttrsInstanceStub]]":
841
+ """Check if a class type is an attrs schema.
842
+
843
+ Args:
844
+ cls: Class to check.
845
+
846
+ Returns:
847
+ bool
848
+ """
849
+ return bool(ATTRS_INSTALLED) and attrs_has(cls)
850
+
851
+
852
+ def is_attrs_instance_with_field(obj: Any, field_name: str) -> "TypeGuard[AttrsInstanceStub]":
853
+ """Check if an attrs instance has a specific field.
854
+
855
+ Args:
856
+ obj: Value to check.
857
+ field_name: Field name to check for.
858
+
859
+ Returns:
860
+ bool
861
+ """
862
+ if not is_attrs_instance(obj):
863
+ return False
864
+ return any(field.name == field_name for field in attrs_fields(obj.__class__))
865
+
866
+
867
+ def is_attrs_instance_without_field(obj: Any, field_name: str) -> "TypeGuard[AttrsInstanceStub]":
868
+ """Check if an attrs instance does not have a specific field.
869
+
870
+ Args:
871
+ obj: Value to check.
872
+ field_name: Field name to check for.
873
+
874
+ Returns:
875
+ bool
876
+ """
877
+ if not is_attrs_instance(obj):
878
+ return False
879
+ return all(field.name != field_name for field in attrs_fields(obj.__class__))
880
+
881
+
882
+ def is_dict(obj: Any) -> "TypeGuard[dict[str, Any]]":
883
+ """Check if a value is a dictionary.
884
+
885
+ Args:
886
+ obj: Value to check.
887
+
888
+ Returns:
889
+ bool
890
+ """
891
+ return type(obj) is dict
892
+
893
+
894
+ def is_dict_with_field(obj: Any, field_name: str) -> "TypeGuard[dict[str, Any]]":
895
+ """Check if a dictionary has a specific field.
896
+
897
+ Args:
898
+ obj: Value to check.
899
+ field_name: Field name to check for.
900
+
901
+ Returns:
902
+ bool
903
+ """
904
+ return is_dict(obj) and field_name in obj
905
+
906
+
907
+ def is_dict_without_field(obj: Any, field_name: str) -> "TypeGuard[dict[str, Any]]":
908
+ """Check if a dictionary does not have a specific field.
909
+
910
+ Args:
911
+ obj: Value to check.
912
+ field_name: Field name to check for.
913
+
914
+ Returns:
915
+ bool
916
+ """
917
+ return is_dict(obj) and field_name not in obj
918
+
919
+
920
+ def is_schema(obj: Any) -> "TypeGuard[SupportedSchemaModel]":
921
+ """Check if a value is a msgspec Struct, Pydantic model, attrs instance, or schema class.
922
+
923
+ Args:
924
+ obj: Value to check.
925
+
926
+ Returns:
927
+ bool
928
+ """
929
+ return (
930
+ is_msgspec_struct(obj)
931
+ or is_pydantic_model(obj)
932
+ or is_attrs_instance(obj)
933
+ or is_attrs_schema(obj)
934
+ or is_dataclass(obj)
935
+ )
936
+
937
+
938
+ def is_schema_or_dict(obj: Any) -> "TypeGuard[SupportedSchemaModel | dict[str, Any]]":
939
+ """Check if a value is a msgspec Struct, Pydantic model, or dict.
940
+
941
+ Args:
942
+ obj: Value to check.
943
+
944
+ Returns:
945
+ bool
946
+ """
947
+ return is_schema(obj) or is_dict(obj)
948
+
949
+
950
+ def is_schema_with_field(obj: Any, field_name: str) -> "TypeGuard[SupportedSchemaModel]":
951
+ """Check if a value is a msgspec Struct or Pydantic model with a specific field.
952
+
953
+ Args:
954
+ obj: Value to check.
955
+ field_name: Field name to check for.
956
+
957
+ Returns:
958
+ bool
959
+ """
960
+ return is_msgspec_struct_with_field(obj, field_name) or is_pydantic_model_with_field(obj, field_name)
961
+
962
+
963
+ def is_schema_without_field(obj: Any, field_name: str) -> "TypeGuard[SupportedSchemaModel]":
964
+ """Check if a value is a msgspec Struct or Pydantic model without a specific field.
965
+
966
+ Args:
967
+ obj: Value to check.
968
+ field_name: Field name to check for.
969
+
970
+ Returns:
971
+ bool
972
+ """
973
+ return not is_schema_with_field(obj, field_name)
974
+
975
+
976
+ def is_schema_or_dict_with_field(obj: Any, field_name: str) -> "TypeGuard[SupportedSchemaModel | dict[str, Any]]":
977
+ """Check if a value is a msgspec Struct, Pydantic model, or dict with a specific field.
978
+
979
+ Args:
980
+ obj: Value to check.
981
+ field_name: Field name to check for.
982
+
983
+ Returns:
984
+ bool
985
+ """
986
+ return is_schema_with_field(obj, field_name) or is_dict_with_field(obj, field_name)
987
+
988
+
989
+ def is_schema_or_dict_without_field(obj: Any, field_name: str) -> "TypeGuard[SupportedSchemaModel | dict[str, Any]]":
990
+ """Check if a value is a msgspec Struct, Pydantic model, or dict without a specific field.
991
+
992
+ Args:
993
+ obj: Value to check.
994
+ field_name: Field name to check for.
995
+
996
+ Returns:
997
+ bool
998
+ """
999
+ return not is_schema_or_dict_with_field(obj, field_name)
1000
+
1001
+
1002
+ def is_dto_data(v: Any) -> "TypeGuard[DTODataStub[Any]]":
1003
+ """Check if a value is a Litestar DTOData object.
1004
+
1005
+ Args:
1006
+ v: Value to check.
1007
+
1008
+ Returns:
1009
+ bool
1010
+ """
1011
+ return bool(LITESTAR_INSTALLED) and isinstance(v, DTOData)
1012
+
1013
+
1014
+ def is_expression(obj: Any) -> "TypeGuard[exp.Expr]":
1015
+ """Check if a value is a sqlglot Expression.
1016
+
1017
+ Args:
1018
+ obj: Value to check.
1019
+
1020
+ Returns:
1021
+ bool
1022
+ """
1023
+ return isinstance(obj, exp.Expr)
1024
+
1025
+
1026
+ def has_dict_attribute(obj: Any) -> "TypeGuard[DictProtocol]":
1027
+ """Check if an object has a __dict__ attribute.
1028
+
1029
+ Args:
1030
+ obj: Value to check.
1031
+
1032
+ Returns:
1033
+ bool
1034
+ """
1035
+ return isinstance(obj, DictProtocol)
1036
+
1037
+
1038
+ def extract_dataclass_fields(
1039
+ obj: "DataclassProtocol",
1040
+ exclude_none: bool = False,
1041
+ exclude_empty: bool = False,
1042
+ include: "AbstractSet[str] | None" = None,
1043
+ exclude: "AbstractSet[str] | None" = None,
1044
+ ) -> "tuple[Field[Any], ...]":
1045
+ """Extract dataclass fields.
1046
+
1047
+ Args:
1048
+ obj: A dataclass instance.
1049
+ exclude_none: Whether to exclude None values.
1050
+ exclude_empty: Whether to exclude Empty values.
1051
+ include: An iterable of fields to include.
1052
+ exclude: An iterable of fields to exclude.
1053
+
1054
+ Raises:
1055
+ ValueError: If there are fields that are both included and excluded.
1056
+
1057
+ Returns:
1058
+ A tuple of dataclass fields.
1059
+ """
1060
+ include = include or set()
1061
+ exclude = exclude or set()
1062
+
1063
+ if common := (include & exclude):
1064
+ msg = f"Fields {common} are both included and excluded."
1065
+ raise ValueError(msg)
1066
+
1067
+ dataclass_fields: list[Field[Any]] = list(dataclasses_fields(obj))
1068
+ if exclude_none:
1069
+ dataclass_fields = [field for field in dataclass_fields if object.__getattribute__(obj, field.name) is not None]
1070
+ if exclude_empty:
1071
+ dataclass_fields = [
1072
+ field for field in dataclass_fields if object.__getattribute__(obj, field.name) is not Empty
1073
+ ]
1074
+ if include:
1075
+ dataclass_fields = [field for field in dataclass_fields if field.name in include]
1076
+ if exclude:
1077
+ dataclass_fields = [field for field in dataclass_fields if field.name not in exclude]
1078
+
1079
+ return tuple(dataclass_fields)
1080
+
1081
+
1082
+ def extract_dataclass_items(
1083
+ obj: "DataclassProtocol",
1084
+ exclude_none: bool = False,
1085
+ exclude_empty: bool = False,
1086
+ include: "AbstractSet[str] | None" = None,
1087
+ exclude: "AbstractSet[str] | None" = None,
1088
+ ) -> "tuple[tuple[str, Any], ...]":
1089
+ """Extract name-value pairs from a dataclass instance.
1090
+
1091
+ Args:
1092
+ obj: A dataclass instance.
1093
+ exclude_none: Whether to exclude None values.
1094
+ exclude_empty: Whether to exclude Empty values.
1095
+ include: An iterable of fields to include.
1096
+ exclude: An iterable of fields to exclude.
1097
+
1098
+ Returns:
1099
+ A tuple of key/value pairs.
1100
+ """
1101
+ dataclass_fields = extract_dataclass_fields(obj, exclude_none, exclude_empty, include, exclude)
1102
+ return tuple((field.name, object.__getattribute__(obj, field.name)) for field in dataclass_fields)
1103
+
1104
+
1105
+ def dataclass_to_dict(
1106
+ obj: "DataclassProtocol",
1107
+ exclude_none: bool = False,
1108
+ exclude_empty: bool = False,
1109
+ convert_nested: bool = True,
1110
+ exclude: "AbstractSet[str] | None" = None,
1111
+ ) -> "dict[str, Any]":
1112
+ """Convert a dataclass instance to a dictionary.
1113
+
1114
+ Args:
1115
+ obj: A dataclass instance.
1116
+ exclude_none: Whether to exclude None values.
1117
+ exclude_empty: Whether to exclude Empty values.
1118
+ convert_nested: Whether to recursively convert nested dataclasses.
1119
+ exclude: An iterable of fields to exclude.
1120
+
1121
+ Returns:
1122
+ A dictionary of key/value pairs.
1123
+ """
1124
+ ret = {}
1125
+ for field in extract_dataclass_fields(obj, exclude_none, exclude_empty, exclude=exclude):
1126
+ value = object.__getattribute__(obj, field.name)
1127
+ if is_dataclass_instance(value) and convert_nested:
1128
+ ret[field.name] = dataclass_to_dict(value, exclude_none, exclude_empty)
1129
+ else:
1130
+ ret[field.name] = value
1131
+ return cast("dict[str, Any]", ret)
1132
+
1133
+
1134
+ def get_node_this(node: "exp.Expr", default: Any | None = None) -> Any:
1135
+ """Safely get the 'this' attribute from a SQLGlot node.
1136
+
1137
+ Args:
1138
+ node: The SQLGlot expression node
1139
+ default: Default value if 'this' attribute doesn't exist
1140
+
1141
+ Returns:
1142
+ The value of node.this or the default value
1143
+ """
1144
+ try:
1145
+ return node.this
1146
+ except AttributeError:
1147
+ return default
1148
+
1149
+
1150
+ def has_this_attribute(node: "exp.Expr") -> bool:
1151
+ """Check if a node has the 'this' attribute without using hasattr().
1152
+
1153
+ Args:
1154
+ node: The SQLGlot expression node
1155
+
1156
+ Returns:
1157
+ True if the node has a 'this' attribute, False otherwise
1158
+ """
1159
+ try:
1160
+ _ = node.this
1161
+ except AttributeError:
1162
+ return False
1163
+ return True
1164
+
1165
+
1166
+ def get_node_expressions(node: "exp.Expression", default: Any | None = None) -> Any:
1167
+ """Safely get the 'expressions' attribute from a SQLGlot node.
1168
+
1169
+ Args:
1170
+ node: The SQLGlot expression node
1171
+ default: Default value if 'expressions' attribute doesn't exist
1172
+
1173
+ Returns:
1174
+ The value of node.expressions or the default value
1175
+ """
1176
+ try:
1177
+ return node.expressions
1178
+ except AttributeError:
1179
+ return default
1180
+
1181
+
1182
+ def has_expressions_attribute(node: "exp.Expression") -> bool:
1183
+ """Check if a node has the 'expressions' attribute without using hasattr().
1184
+
1185
+ Args:
1186
+ node: The SQLGlot expression node
1187
+
1188
+ Returns:
1189
+ True if the node has an 'expressions' attribute, False otherwise
1190
+ """
1191
+ try:
1192
+ _ = node.expressions
1193
+ except AttributeError:
1194
+ return False
1195
+ return True
1196
+
1197
+
1198
+ def get_literal_parent(literal: "exp.Expression", default: Any | None = None) -> Any:
1199
+ """Safely get the 'parent' attribute from a SQLGlot literal.
1200
+
1201
+ Args:
1202
+ literal: The SQLGlot expression
1203
+ default: Default value if 'parent' attribute doesn't exist
1204
+
1205
+ Returns:
1206
+ The value of literal.parent or the default value
1207
+ """
1208
+ try:
1209
+ return literal.parent
1210
+ except AttributeError:
1211
+ return default
1212
+
1213
+
1214
+ def has_parent_attribute(literal: "exp.Expression") -> bool:
1215
+ """Check if a literal has the 'parent' attribute without using hasattr().
1216
+
1217
+ Args:
1218
+ literal: The SQLGlot expression
1219
+
1220
+ Returns:
1221
+ True if the literal has a 'parent' attribute, False otherwise
1222
+ """
1223
+ try:
1224
+ _ = literal.parent
1225
+ except AttributeError:
1226
+ return False
1227
+ return True
1228
+
1229
+
1230
+ def is_string_literal(literal: "exp.Literal") -> bool:
1231
+ """Check if a literal is a string literal without using hasattr().
1232
+
1233
+ Args:
1234
+ literal: The SQLGlot Literal expression
1235
+
1236
+ Returns:
1237
+ True if the literal is a string, False otherwise
1238
+ """
1239
+ try:
1240
+ return bool(literal.is_string)
1241
+ except AttributeError:
1242
+ try:
1243
+ return isinstance(literal.this, str)
1244
+ except AttributeError:
1245
+ return False
1246
+
1247
+
1248
+ def is_number_literal(literal: "exp.Literal") -> bool:
1249
+ """Check if a literal is a number literal without using hasattr().
1250
+
1251
+ Args:
1252
+ literal: The SQLGlot Literal expression
1253
+
1254
+ Returns:
1255
+ True if the literal is a number, False otherwise
1256
+ """
1257
+ try:
1258
+ return bool(literal.is_number)
1259
+ except AttributeError:
1260
+ try:
1261
+ if literal.this is not None:
1262
+ float(str(literal.this))
1263
+ return True
1264
+ except (AttributeError, ValueError, TypeError):
1265
+ pass
1266
+ return False
1267
+
1268
+
1269
+ def get_initial_expression(context: Any) -> "exp.Expr | None":
1270
+ """Safely get initial_expression from context.
1271
+
1272
+ Args:
1273
+ context: SQL processing context
1274
+
1275
+ Returns:
1276
+ The initial expression or None if not available
1277
+ """
1278
+ try:
1279
+ return context.initial_expression # type: ignore[no-any-return]
1280
+ except AttributeError:
1281
+ return None
1282
+
1283
+
1284
+ def expression_has_limit(expr: "exp.Expression | None") -> bool:
1285
+ """Check if an expression has a limit clause.
1286
+
1287
+ Args:
1288
+ expr: SQLGlot expression to check
1289
+
1290
+ Returns:
1291
+ True if expression has limit in args, False otherwise
1292
+ """
1293
+ if expr is None:
1294
+ return False
1295
+ try:
1296
+ return "limit" in expr.args
1297
+ except AttributeError:
1298
+ return False
1299
+
1300
+
1301
+ def get_value_attribute(obj: Any) -> Any:
1302
+ """Safely get the 'value' attribute from an object.
1303
+
1304
+ Args:
1305
+ obj: Object to get value from
1306
+
1307
+ Returns:
1308
+ The value attribute or the object itself if no value attribute
1309
+ """
1310
+ if isinstance(obj, HasValueProtocol):
1311
+ return obj.value
1312
+ return obj
1313
+
1314
+
1315
+ def get_param_style_and_name(param: Any) -> "tuple[str | None, str | None]":
1316
+ """Safely get style and name attributes from a parameter.
1317
+
1318
+ Args:
1319
+ param: Parameter object
1320
+
1321
+ Returns:
1322
+ Tuple of (style, name) or (None, None) if attributes don't exist
1323
+ """
1324
+ try:
1325
+ style = param.style
1326
+ name = param.name
1327
+ except AttributeError:
1328
+ return None, None
1329
+ return style, name
1330
+
1331
+
1332
+ def is_copy_statement(expression: Any) -> "TypeGuard[exp.Expr]":
1333
+ """Check if the SQL expression is a PostgreSQL COPY statement.
1334
+
1335
+ Args:
1336
+ expression: The SQL expression to check
1337
+
1338
+ Returns:
1339
+ True if this is a COPY statement, False otherwise
1340
+ """
1341
+ if expression is None:
1342
+ return False
1343
+
1344
+ try:
1345
+ copy_expr = exp.Copy
1346
+ except AttributeError:
1347
+ copy_expr = None
1348
+ if copy_expr is not None and isinstance(expression, copy_expr):
1349
+ return True
1350
+
1351
+ if isinstance(expression, (exp.Command, exp.Anonymous)):
1352
+ sql_text = str(expression).strip().upper()
1353
+ return sql_text.startswith("COPY ")
1354
+
1355
+ return False
1356
+
1357
+
1358
+ def is_typed_parameter(obj: Any) -> "TypeGuard[TypedParameter]":
1359
+ """Check if an object is a typed parameter.
1360
+
1361
+ Args:
1362
+ obj: The object to check
1363
+
1364
+ Returns:
1365
+ True if the object is a TypedParameter, False otherwise
1366
+ """
1367
+ from sqlspec.core.parameters import TypedParameter
1368
+
1369
+ return isinstance(obj, TypedParameter)
1370
+
1371
+
1372
+ def has_expression_and_sql(obj: Any) -> "TypeGuard[HasExpressionAndSQLProtocol]":
1373
+ """Check if an object has both 'expression' and 'sql' attributes.
1374
+
1375
+ This is commonly used to identify SQL objects in the builder system.
1376
+
1377
+ Args:
1378
+ obj: The object to check
1379
+
1380
+ Returns:
1381
+ True if the object has both attributes, False otherwise
1382
+ """
1383
+ return isinstance(obj, HasExpressionAndSQLProtocol)
1384
+
1385
+
1386
+ def has_expression_and_parameters(obj: Any) -> "TypeGuard[HasExpressionAndParametersProtocol]":
1387
+ """Check if an object has both 'expression' and 'parameters' attributes.
1388
+
1389
+ This is used to identify objects that contain both SQL expressions
1390
+ and parameter mappings.
1391
+
1392
+ Args:
1393
+ obj: The object to check
1394
+
1395
+ Returns:
1396
+ True if the object has both attributes, False otherwise
1397
+ """
1398
+ return isinstance(obj, HasExpressionAndParametersProtocol)
1399
+
1400
+
1401
+ WINDOWS_DRIVE_PATTERN_LENGTH = 3
1402
+
1403
+
1404
+ def is_local_path(uri: str) -> bool:
1405
+ r"""Check if URI represents a local filesystem path.
1406
+
1407
+ Detects local paths including:
1408
+ - file:// URIs
1409
+ - Absolute paths (Unix: /, Windows: C:\\)
1410
+ - Relative paths (., .., ~)
1411
+
1412
+ Args:
1413
+ uri: URI or path string to check.
1414
+
1415
+ Returns:
1416
+ True if uri is a local path, False for remote URIs.
1417
+
1418
+ Examples:
1419
+ >>> is_local_path("file:///data/file.txt")
1420
+ True
1421
+ >>> is_local_path("/absolute/path")
1422
+ True
1423
+ >>> is_local_path("s3://bucket/key")
1424
+ False
1425
+ """
1426
+ if not uri:
1427
+ return False
1428
+
1429
+ if "://" in uri and not uri.startswith("file://"):
1430
+ return False
1431
+
1432
+ if uri.startswith("file://"):
1433
+ return True
1434
+
1435
+ if uri.startswith("/"):
1436
+ return True
1437
+
1438
+ if uri.startswith((".", "~")):
1439
+ return True
1440
+
1441
+ if len(uri) >= WINDOWS_DRIVE_PATTERN_LENGTH and uri[1:3] == ":\\":
1442
+ return True
1443
+
1444
+ return "/" in uri or "\\" in uri
1445
+
1446
+
1447
+ def supports_arrow_results(obj: Any) -> "TypeGuard[SupportsArrowResults]":
1448
+ """Check if object supports Arrow result format.
1449
+
1450
+ Use this type guard to check if a driver or adapter supports returning
1451
+ query results in Apache Arrow format via select_to_arrow() method.
1452
+
1453
+ Args:
1454
+ obj: Object to check for Arrow results support.
1455
+
1456
+ Returns:
1457
+ True if object implements SupportsArrowResults protocol.
1458
+
1459
+ Examples:
1460
+ >>> from sqlspec.adapters.duckdb import DuckDBDriver
1461
+ >>> driver = DuckDBDriver(...)
1462
+ >>> supports_arrow_results(driver)
1463
+ True
1464
+ """
1465
+ return isinstance(obj, SupportsArrowResults)
1466
+
1467
+
1468
+ def has_parameter_builder(obj: Any) -> "TypeGuard[HasParameterBuilderProtocol]":
1469
+ """Check if an object has an add_parameter method."""
1470
+ return isinstance(obj, HasParameterBuilderProtocol)
1471
+
1472
+
1473
+ def has_expression_attr(obj: Any) -> "TypeGuard[HasExpressionProtocol]":
1474
+ """Check if an object has an _expression attribute."""
1475
+ return isinstance(obj, HasExpressionProtocol)
1476
+
1477
+
1478
+ def has_sqlglot_expression(obj: Any) -> "TypeGuard[HasSQLGlotExpressionProtocol]":
1479
+ """Check if an object has a sqlglot_expression property."""
1480
+ return isinstance(obj, HasSQLGlotExpressionProtocol)
1481
+
1482
+
1483
+ def has_statement_config_factory(obj: Any) -> "TypeGuard[HasStatementConfigFactoryProtocol]":
1484
+ """Check if an object has a _create_statement_config method.
1485
+
1486
+ Used to check if a config object can create statement configs dynamically.
1487
+
1488
+ Args:
1489
+ obj: The object to check.
1490
+
1491
+ Returns:
1492
+ True if the object has a _create_statement_config method.
1493
+ """
1494
+ return isinstance(obj, HasStatementConfigFactoryProtocol)
1495
+
1496
+
1497
+ def has_migration_config(obj: Any) -> "TypeGuard[HasMigrationConfigProtocol]":
1498
+ """Check if an object has a migration_config attribute.
1499
+
1500
+ Used to check if a database config supports migrations.
1501
+
1502
+ Args:
1503
+ obj: The object to check.
1504
+
1505
+ Returns:
1506
+ True if the object has a migration_config attribute.
1507
+ """
1508
+ return isinstance(obj, HasMigrationConfigProtocol)