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,784 @@
1
+ """Application dependency providers generators.
2
+
3
+ This module contains functions to create dependency providers for services and filters.
4
+ """
5
+
6
+ import datetime
7
+ import inspect
8
+ from collections.abc import Callable, Mapping
9
+ from functools import partial
10
+ from types import GenericAlias
11
+ from typing import Annotated, Any, Literal, NamedTuple, TypedDict, cast
12
+ from uuid import UUID
13
+
14
+ from litestar.di import Provide
15
+ from litestar.exceptions import ValidationException
16
+ from litestar.params import Dependency, QueryParameter
17
+ from litestar.utils.signature import ParsedSignature
18
+ from typing_extensions import NotRequired
19
+
20
+ from sqlspec.core import (
21
+ BeforeAfterFilter,
22
+ FilterTypes,
23
+ InCollectionFilter,
24
+ LimitOffsetFilter,
25
+ NotInCollectionFilter,
26
+ NotNullFilter,
27
+ NullFilter,
28
+ OrderByFilter,
29
+ SearchFilter,
30
+ )
31
+ from sqlspec.utils.text import camelize
32
+
33
+ __all__ = (
34
+ "DEPENDENCY_DEFAULTS",
35
+ "BooleanOrNone",
36
+ "DTorNone",
37
+ "DependencyDefaults",
38
+ "FieldNameType",
39
+ "FilterConfig",
40
+ "HashableType",
41
+ "HashableValue",
42
+ "IntOrNone",
43
+ "SortField",
44
+ "SortOrder",
45
+ "SortOrderOrNone",
46
+ "StringOrNone",
47
+ "UuidOrNone",
48
+ "create_filter_dependencies",
49
+ "dep_cache",
50
+ )
51
+
52
+ DTorNone = datetime.datetime | None
53
+ StringOrNone = str | None
54
+ UuidOrNone = UUID | None
55
+ IntOrNone = int | None
56
+ BooleanOrNone = bool | None
57
+ SortOrder = Literal["asc", "desc"]
58
+ SortOrderOrNone = SortOrder | None
59
+ SortField = str | set[str] | list[str]
60
+ HashableValue = str | int | float | bool | None
61
+ HashableType = HashableValue | tuple[Any, ...] | tuple[tuple[str, Any], ...] | tuple[HashableValue, ...]
62
+
63
+
64
+ class DependencyDefaults:
65
+ FILTERS_DEPENDENCY_KEY: str = "filters"
66
+ CREATED_FILTER_DEPENDENCY_KEY: str = "created_filter"
67
+ ID_FILTER_DEPENDENCY_KEY: str = "id_filter"
68
+ LIMIT_OFFSET_FILTER_DEPENDENCY_KEY: str = "limit_offset_filter"
69
+ UPDATED_FILTER_DEPENDENCY_KEY: str = "updated_filter"
70
+ ORDER_BY_FILTER_DEPENDENCY_KEY: str = "order_by_filter"
71
+ SEARCH_FILTER_DEPENDENCY_KEY: str = "search_filter"
72
+ DEFAULT_PAGINATION_SIZE: int = 20
73
+
74
+
75
+ DEPENDENCY_DEFAULTS = DependencyDefaults()
76
+
77
+
78
+ class FieldNameType(NamedTuple):
79
+ """Type for field name and associated type information for filter configuration."""
80
+
81
+ name: str
82
+ type_hint: type[Any] = str
83
+
84
+
85
+ class _SortFieldResolution(NamedTuple):
86
+ default_field: str
87
+ default_query_value: str
88
+ allowed_fields: frozenset[str]
89
+ inbound_aliases: dict[str, str]
90
+ field_display_names: dict[str, str]
91
+ allowed_display_names: tuple[str, ...]
92
+
93
+ def normalize(self, value: str | None) -> str | None:
94
+ if value is None:
95
+ return self.default_field
96
+ return self.inbound_aliases.get(value)
97
+
98
+
99
+ class FilterConfig(TypedDict):
100
+ """Configuration for generated Litestar filter dependencies.
101
+
102
+ All keys are optional. A filter dependency is created only for each enabled
103
+ key. Field names are SQL-facing allowlist values; generated query parameter
104
+ names and order-by aliases remain API-facing.
105
+ """
106
+
107
+ id_filter: NotRequired[type[UUID | int | str]]
108
+ """Type of ID filter to enable. When set, creates an ``ids`` collection filter."""
109
+ id_field: NotRequired[str]
110
+ """SQL-facing field name for ID filtering. Defaults to ``"id"``."""
111
+ sort_field: NotRequired[SortField]
112
+ """Allowed SQL-facing field or fields for ``orderBy`` sorting."""
113
+ sort_field_aliases: NotRequired[dict[str, str]]
114
+ """Additional API-facing ``orderBy`` aliases mapped to configured ``sort_field`` values."""
115
+ sort_field_camelize: NotRequired[bool]
116
+ """Whether to accept camel-case aliases for configured sort fields. Defaults to ``True``."""
117
+ sort_order: NotRequired[SortOrder]
118
+ """Default sort order. Defaults to ``"desc"``."""
119
+ pagination_type: NotRequired[Literal["limit_offset"]]
120
+ """Pagination strategy to enable. Currently supports ``"limit_offset"``."""
121
+ pagination_size: NotRequired[int]
122
+ """Default page size for limit/offset pagination."""
123
+ search: NotRequired[str | set[str] | list[str]]
124
+ """SQL-facing field or fields to search. Strings may be comma-separated."""
125
+ search_ignore_case: NotRequired[bool]
126
+ """Whether search filtering is case-insensitive. Defaults to ``False``."""
127
+ created_at: NotRequired[bool]
128
+ """Whether to enable ``created_at`` before/after range filtering."""
129
+ updated_at: NotRequired[bool]
130
+ """Whether to enable ``updated_at`` before/after range filtering."""
131
+ not_in_fields: NotRequired[FieldNameType | set[FieldNameType] | list[str | FieldNameType]]
132
+ """Field or fields that support ``NOT IN`` collection filtering."""
133
+ in_fields: NotRequired[FieldNameType | set[FieldNameType] | list[str | FieldNameType]]
134
+ """Field or fields that support ``IN`` collection filtering."""
135
+ null_fields: NotRequired[str | set[str] | list[str]]
136
+ """Field or fields that support ``IS NULL`` filtering."""
137
+ not_null_fields: NotRequired[str | set[str] | list[str]]
138
+ """Field or fields that support ``IS NOT NULL`` filtering."""
139
+
140
+
141
+ class DependencyCache:
142
+ """Dependency cache for memoizing dynamically generated dependencies."""
143
+
144
+ def __init__(self) -> None:
145
+ self.dependencies: dict[int | str, dict[str, Provide]] = {}
146
+
147
+ def add_dependencies(self, key: int | str, dependencies: dict[str, Provide]) -> None:
148
+ self.dependencies[key] = dependencies
149
+
150
+ def get_dependencies(self, key: int | str) -> dict[str, Provide] | None:
151
+ return self.dependencies.get(key)
152
+
153
+
154
+ dep_cache = DependencyCache()
155
+
156
+
157
+ def create_filter_dependencies(
158
+ config: FilterConfig, dep_defaults: DependencyDefaults = DEPENDENCY_DEFAULTS
159
+ ) -> dict[str, Provide]:
160
+ """Create a dependency provider for the combined filter function.
161
+
162
+ Args:
163
+ config: FilterConfig instance with desired settings.
164
+ dep_defaults: Dependency defaults to use for the filter dependencies
165
+
166
+ Returns:
167
+ A dependency provider function for the combined filter function.
168
+ """
169
+ if (deps := dep_cache.get_dependencies(cache_key := hash(_make_hashable(config)))) is not None:
170
+ return deps
171
+ deps = _create_statement_filters(config, dep_defaults)
172
+ dep_cache.add_dependencies(cache_key, deps)
173
+ return deps
174
+
175
+
176
+ def _create_statement_filters(
177
+ config: FilterConfig, dep_defaults: DependencyDefaults = DEPENDENCY_DEFAULTS
178
+ ) -> dict[str, Provide]:
179
+ """Create filter dependencies based on configuration.
180
+
181
+ Args:
182
+ config: Configuration dictionary specifying which filters to enable
183
+ dep_defaults: Dependency defaults to use for the filter dependencies
184
+
185
+ Returns:
186
+ Dictionary of filter provider functions
187
+ """
188
+ filters: dict[str, Provide] = {}
189
+
190
+ if id_type := config.get("id_filter", False):
191
+ filters[dep_defaults.ID_FILTER_DEPENDENCY_KEY] = _create_provide(
192
+ _bind_provider(
193
+ _IdFilterProvider(config.get("id_field", "id"), id_type if isinstance(id_type, type) else object),
194
+ _provide_id_filter,
195
+ )
196
+ )
197
+
198
+ if config.get("created_at", False):
199
+ filters[dep_defaults.CREATED_FILTER_DEPENDENCY_KEY] = _create_provide(
200
+ _build_before_after_provider("created_at", "createdBefore", "createdAfter")
201
+ )
202
+
203
+ if config.get("updated_at", False):
204
+ filters[dep_defaults.UPDATED_FILTER_DEPENDENCY_KEY] = _create_provide(
205
+ _build_before_after_provider("updated_at", "updatedBefore", "updatedAfter")
206
+ )
207
+
208
+ if config.get("pagination_type") == "limit_offset":
209
+ filters[dep_defaults.LIMIT_OFFSET_FILTER_DEPENDENCY_KEY] = _create_provide(
210
+ _bind_provider(
211
+ _LimitOffsetFilterProvider(config.get("pagination_size", dep_defaults.DEFAULT_PAGINATION_SIZE)),
212
+ _provide_limit_offset_filter,
213
+ )
214
+ )
215
+
216
+ if search_fields := config.get("search"):
217
+ filters[dep_defaults.SEARCH_FILTER_DEPENDENCY_KEY] = _create_provide(
218
+ _bind_provider(
219
+ _SearchFilterProvider(search_fields, config.get("search_ignore_case", False)), _provide_search_filter
220
+ )
221
+ )
222
+
223
+ if sort_field := config.get("sort_field"):
224
+ filters[dep_defaults.ORDER_BY_FILTER_DEPENDENCY_KEY] = _create_provide(
225
+ _bind_provider(_OrderByProvider(sort_field, config), _provide_order_by_filter)
226
+ )
227
+
228
+ if not_in_fields := config.get("not_in_fields"):
229
+ not_in_fields = {not_in_fields} if isinstance(not_in_fields, (str, FieldNameType)) else not_in_fields
230
+
231
+ for field_def in not_in_fields:
232
+ resolved = FieldNameType(name=field_def, type_hint=str) if isinstance(field_def, str) else field_def
233
+ filters[f"{resolved.name}_not_in_filter"] = _create_provide(
234
+ _build_in_collection_provider(resolved, negated=True)
235
+ )
236
+
237
+ if in_fields := config.get("in_fields"):
238
+ in_fields = {in_fields} if isinstance(in_fields, (str, FieldNameType)) else in_fields
239
+
240
+ for field_def in in_fields:
241
+ resolved = FieldNameType(name=field_def, type_hint=str) if isinstance(field_def, str) else field_def
242
+ filters[f"{resolved.name}_in_filter"] = _create_provide(
243
+ _build_in_collection_provider(resolved, negated=False)
244
+ )
245
+
246
+ if null_fields := config.get("null_fields"):
247
+ null_fields = {null_fields} if isinstance(null_fields, str) else set(null_fields)
248
+ for field_name in null_fields:
249
+ filters[f"{field_name}_null_filter"] = _create_provide(_build_null_provider(field_name, negated=False))
250
+
251
+ if not_null_fields := config.get("not_null_fields"):
252
+ not_null_fields = {not_null_fields} if isinstance(not_null_fields, str) else set(not_null_fields)
253
+ for field_name in not_null_fields:
254
+ filters[f"{field_name}_not_null_filter"] = _create_provide(_build_null_provider(field_name, negated=True))
255
+
256
+ if filters:
257
+ filters[dep_defaults.FILTERS_DEPENDENCY_KEY] = _create_provide(_create_filter_aggregate_function(config))
258
+
259
+ return filters
260
+
261
+
262
+ def _create_filter_aggregate_function(config: FilterConfig) -> Callable[..., list[FilterTypes]]:
263
+ """Create filter aggregation function based on configuration.
264
+
265
+ Args:
266
+ config: The filter configuration.
267
+
268
+ Returns:
269
+ Function that returns list of configured filters.
270
+ """
271
+
272
+ parameters: dict[str, inspect.Parameter] = {}
273
+ annotations: dict[str, Any] = {}
274
+
275
+ if cls := config.get("id_filter"):
276
+ parameters["id_filter"] = inspect.Parameter(
277
+ name="id_filter",
278
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
279
+ default=Dependency(skip_validation=True),
280
+ annotation=InCollectionFilter[cls], # type: ignore[valid-type]
281
+ )
282
+ annotations["id_filter"] = InCollectionFilter[cls] # type: ignore[valid-type]
283
+
284
+ if config.get("created_at"):
285
+ parameters["created_filter"] = inspect.Parameter(
286
+ name="created_filter",
287
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
288
+ default=Dependency(skip_validation=True),
289
+ annotation=BeforeAfterFilter,
290
+ )
291
+ annotations["created_filter"] = BeforeAfterFilter
292
+
293
+ if config.get("updated_at"):
294
+ parameters["updated_filter"] = inspect.Parameter(
295
+ name="updated_filter",
296
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
297
+ default=Dependency(skip_validation=True),
298
+ annotation=BeforeAfterFilter,
299
+ )
300
+ annotations["updated_filter"] = BeforeAfterFilter
301
+
302
+ if config.get("search"):
303
+ parameters["search_filter"] = inspect.Parameter(
304
+ name="search_filter",
305
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
306
+ default=Dependency(skip_validation=True),
307
+ annotation=SearchFilter,
308
+ )
309
+ annotations["search_filter"] = SearchFilter
310
+
311
+ if config.get("pagination_type") == "limit_offset":
312
+ parameters["limit_offset_filter"] = inspect.Parameter(
313
+ name="limit_offset_filter",
314
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
315
+ default=Dependency(skip_validation=True),
316
+ annotation=LimitOffsetFilter,
317
+ )
318
+ annotations["limit_offset_filter"] = LimitOffsetFilter
319
+
320
+ if config.get("sort_field"):
321
+ parameters["order_by_filter"] = inspect.Parameter(
322
+ name="order_by_filter",
323
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
324
+ default=Dependency(skip_validation=True),
325
+ annotation=OrderByFilter,
326
+ )
327
+ annotations["order_by_filter"] = OrderByFilter
328
+
329
+ if not_in_fields := config.get("not_in_fields"):
330
+ for field_def in not_in_fields:
331
+ field_def = FieldNameType(name=field_def, type_hint=str) if isinstance(field_def, str) else field_def
332
+ parameters[f"{field_def.name}_not_in_filter"] = inspect.Parameter(
333
+ name=f"{field_def.name}_not_in_filter",
334
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
335
+ default=Dependency(skip_validation=True),
336
+ annotation=NotInCollectionFilter[Any],
337
+ )
338
+ annotations[f"{field_def.name}_not_in_filter"] = NotInCollectionFilter[Any]
339
+
340
+ if in_fields := config.get("in_fields"):
341
+ for field_def in in_fields:
342
+ field_def = FieldNameType(name=field_def, type_hint=str) if isinstance(field_def, str) else field_def
343
+ parameters[f"{field_def.name}_in_filter"] = inspect.Parameter(
344
+ name=f"{field_def.name}_in_filter",
345
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
346
+ default=Dependency(skip_validation=True),
347
+ annotation=InCollectionFilter[Any],
348
+ )
349
+ annotations[f"{field_def.name}_in_filter"] = InCollectionFilter[Any]
350
+
351
+ if null_fields := config.get("null_fields"):
352
+ null_fields = {null_fields} if isinstance(null_fields, str) else set(null_fields)
353
+ for field_name in null_fields:
354
+ parameters[f"{field_name}_null_filter"] = inspect.Parameter(
355
+ name=f"{field_name}_null_filter",
356
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
357
+ default=Dependency(skip_validation=True),
358
+ annotation=NullFilter | None,
359
+ )
360
+ annotations[f"{field_name}_null_filter"] = NullFilter | None
361
+
362
+ if not_null_fields := config.get("not_null_fields"):
363
+ not_null_fields = {not_null_fields} if isinstance(not_null_fields, str) else set(not_null_fields)
364
+ for field_name in not_null_fields:
365
+ parameters[f"{field_name}_not_null_filter"] = inspect.Parameter(
366
+ name=f"{field_name}_not_null_filter",
367
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
368
+ default=Dependency(skip_validation=True),
369
+ annotation=NotNullFilter | None,
370
+ )
371
+ annotations[f"{field_name}_not_null_filter"] = NotNullFilter | None
372
+
373
+ return _make_aggregate_filter_provider(list(parameters.values()), annotations)
374
+
375
+
376
+ def _make_hashable(value: Any) -> HashableType:
377
+ """Convert a value into a hashable type for caching purposes.
378
+
379
+ Args:
380
+ value: Any value that needs to be made hashable.
381
+
382
+ Returns:
383
+ A hashable version of the value.
384
+ """
385
+ if isinstance(value, dict):
386
+ items = []
387
+ for k in sorted(value.keys()): # pyright: ignore
388
+ v = value[k]
389
+ items.append((str(k), _make_hashable(v)))
390
+ return tuple(items)
391
+ if isinstance(value, (list, set)):
392
+ hashable_items = [_make_hashable(item) for item in value]
393
+ filtered_items = [item for item in hashable_items if item is not None]
394
+ return tuple(sorted(filtered_items, key=str))
395
+ if isinstance(value, (str, int, float, bool, type(None))):
396
+ return value
397
+ return str(value)
398
+
399
+
400
+ def _set_provider_metadata(
401
+ provider: Any, signature: inspect.Signature, annotations: dict[str, Any]
402
+ ) -> Callable[..., Any]:
403
+ provider.__signature__ = signature
404
+ provider.__annotations__ = annotations
405
+ return cast("Callable[..., Any]", provider)
406
+
407
+
408
+ def _bind_provider(context: Any, provider: Callable[..., Any]) -> Callable[..., Any]:
409
+ return _set_provider_metadata(partial(provider, context), context.signature, context.annotations)
410
+
411
+
412
+ def _create_provide(provider: Callable[..., Any]) -> Provide:
413
+ dependency = Provide(provider, sync_to_thread=False)
414
+ dependency.parsed_fn_signature = ParsedSignature.from_signature(
415
+ inspect.signature(provider), getattr(provider, "__annotations__", {})
416
+ )
417
+ return dependency
418
+
419
+
420
+ def _aggregate_filter_provider(**kwargs: Any) -> list[FilterTypes]:
421
+ filters: list[FilterTypes] = []
422
+ for filter_value in kwargs.values():
423
+ if filter_value is None:
424
+ continue
425
+ if isinstance(filter_value, list):
426
+ filters.extend(filter_value)
427
+ elif (isinstance(filter_value, SearchFilter) and filter_value.value is None) or (
428
+ isinstance(filter_value, OrderByFilter) and filter_value.field_name is None
429
+ ):
430
+ continue
431
+ else:
432
+ filters.append(filter_value)
433
+ return filters
434
+
435
+
436
+ def _make_aggregate_filter_provider(
437
+ parameters: list[inspect.Parameter], annotations: dict[str, Any]
438
+ ) -> Callable[..., list[FilterTypes]]:
439
+ aggregate_annotations = dict(annotations)
440
+ aggregate_annotations["return"] = list[FilterTypes]
441
+ return _set_provider_metadata(
442
+ partial(_aggregate_filter_provider),
443
+ inspect.Signature(parameters=parameters, return_annotation=list[FilterTypes]),
444
+ aggregate_annotations,
445
+ )
446
+
447
+
448
+ def _collection_value_annotation(collection_type: type[Any], value_type: type[Any]) -> Any:
449
+ return GenericAlias(collection_type, (value_type,)) | None
450
+
451
+
452
+ class _CollectionFilterProvider:
453
+ """Per-field `IN` / `NOT IN` provider with a unique parameter name (issue #435)."""
454
+
455
+ def __init__(self, field: FieldNameType, *, negated: bool) -> None:
456
+ self.type_hint = field.type_hint
457
+ self.field_name = field.name
458
+ self.param_name = f"{field.name}_values"
459
+ self.filter_cls: Any = NotInCollectionFilter if negated else InCollectionFilter
460
+ self.return_annotation = self.filter_cls[field.type_hint] | None
461
+ annotation = Annotated[ # type: ignore[valid-type]
462
+ _collection_value_annotation(list, field.type_hint),
463
+ QueryParameter(name=camelize(f"{field.name}_{'not_in' if negated else 'in'}"), required=False),
464
+ ]
465
+ self.signature = inspect.Signature(
466
+ parameters=[
467
+ inspect.Parameter(
468
+ self.param_name, kind=inspect.Parameter.KEYWORD_ONLY, default=None, annotation=annotation
469
+ )
470
+ ],
471
+ return_annotation=self.return_annotation,
472
+ )
473
+ self.annotations = {self.param_name: annotation, "return": self.return_annotation}
474
+
475
+ def __call__(self, **kwargs: Any) -> Any:
476
+ values = kwargs.get(self.param_name)
477
+ return self.filter_cls[self.type_hint](field_name=self.field_name, values=values) if values else None
478
+
479
+
480
+ class _NullFilterProvider:
481
+ def __init__(self, field_name: str, *, negated: bool) -> None:
482
+ suffix = "is_not_null" if negated else "is_null"
483
+ self.field_name = field_name
484
+ self.param_name = f"{field_name}_{suffix}"
485
+ self.filter_cls: type[Any] = NotNullFilter if negated else NullFilter
486
+ self.return_annotation = self.filter_cls | None
487
+ annotation = Annotated[bool | None, QueryParameter(name=camelize(self.param_name), required=False)]
488
+ self.signature = inspect.Signature(
489
+ parameters=[
490
+ inspect.Parameter(
491
+ self.param_name, kind=inspect.Parameter.KEYWORD_ONLY, default=None, annotation=annotation
492
+ )
493
+ ],
494
+ return_annotation=self.return_annotation,
495
+ )
496
+ self.annotations = {self.param_name: annotation, "return": self.return_annotation}
497
+
498
+ def __call__(self, **kwargs: Any) -> Any:
499
+ return self.filter_cls(field_name=self.field_name) if kwargs.get(self.param_name) else None
500
+
501
+
502
+ class _BeforeAfterFilterProvider:
503
+ """Before/after provider with unique parameter names for sibling dependencies."""
504
+
505
+ def __init__(self, field_name: str, before_alias: str, after_alias: str) -> None:
506
+ self.field_name = field_name
507
+ self.before_param = f"{field_name}_before"
508
+ self.after_param = f"{field_name}_after"
509
+ before_annotation = Annotated[DTorNone, QueryParameter(name=before_alias, required=False)]
510
+ after_annotation = Annotated[DTorNone, QueryParameter(name=after_alias, required=False)]
511
+ self.signature = inspect.Signature(
512
+ parameters=[
513
+ inspect.Parameter(
514
+ self.before_param, kind=inspect.Parameter.KEYWORD_ONLY, default=None, annotation=before_annotation
515
+ ),
516
+ inspect.Parameter(
517
+ self.after_param, kind=inspect.Parameter.KEYWORD_ONLY, default=None, annotation=after_annotation
518
+ ),
519
+ ],
520
+ return_annotation=BeforeAfterFilter,
521
+ )
522
+ self.annotations = {
523
+ self.before_param: before_annotation,
524
+ self.after_param: after_annotation,
525
+ "return": BeforeAfterFilter,
526
+ }
527
+
528
+ def __call__(self, **kwargs: Any) -> BeforeAfterFilter:
529
+ return BeforeAfterFilter(self.field_name, kwargs.get(self.before_param), kwargs.get(self.after_param))
530
+
531
+
532
+ class _IdFilterProvider:
533
+ def __init__(self, field_name: str, id_type: type[Any]) -> None:
534
+ self.field_name = field_name
535
+ self.return_annotation = InCollectionFilter[id_type] # type: ignore[valid-type]
536
+ annotation = Annotated[_collection_value_annotation(list, id_type), QueryParameter(name="ids", required=False)] # type: ignore[valid-type]
537
+ self.signature = inspect.Signature(
538
+ parameters=[
539
+ inspect.Parameter("ids", kind=inspect.Parameter.KEYWORD_ONLY, default=None, annotation=annotation)
540
+ ],
541
+ return_annotation=self.return_annotation,
542
+ )
543
+ self.annotations = {"ids": annotation, "return": self.return_annotation}
544
+
545
+ def __call__(self, ids: list[Any] | None = None) -> InCollectionFilter[Any]:
546
+ return InCollectionFilter(field_name=self.field_name, values=ids)
547
+
548
+
549
+ class _LimitOffsetFilterProvider:
550
+ def __init__(self, default_page_size: int) -> None:
551
+ self.default_page_size = default_page_size
552
+ self.return_annotation = LimitOffsetFilter
553
+ current_annotation = Annotated[int, QueryParameter(name="currentPage", required=False, ge=1)]
554
+ size_annotation = Annotated[int, QueryParameter(name="pageSize", required=False, ge=1)]
555
+ self.signature = inspect.Signature(
556
+ parameters=[
557
+ inspect.Parameter(
558
+ "current_page", kind=inspect.Parameter.KEYWORD_ONLY, default=1, annotation=current_annotation
559
+ ),
560
+ inspect.Parameter(
561
+ "page_size",
562
+ kind=inspect.Parameter.KEYWORD_ONLY,
563
+ default=default_page_size,
564
+ annotation=size_annotation,
565
+ ),
566
+ ],
567
+ return_annotation=self.return_annotation,
568
+ )
569
+ self.annotations = {
570
+ "current_page": current_annotation,
571
+ "page_size": size_annotation,
572
+ "return": self.return_annotation,
573
+ }
574
+
575
+ def __call__(self, current_page: int = 1, page_size: int | None = None) -> LimitOffsetFilter:
576
+ resolved_page_size = page_size if page_size is not None else self.default_page_size
577
+ return LimitOffsetFilter(resolved_page_size, resolved_page_size * (current_page - 1))
578
+
579
+
580
+ class _SearchFilterProvider:
581
+ def __init__(self, search_fields: str | set[str] | list[str], ignore_case_default: bool) -> None:
582
+ self.search_fields = search_fields
583
+ self.ignore_case_default = ignore_case_default
584
+ self.return_annotation = SearchFilter
585
+ search_annotation = Annotated[
586
+ StringOrNone, QueryParameter(name="searchString", required=False, title="Field to search")
587
+ ]
588
+ ignore_annotation = Annotated[
589
+ BooleanOrNone,
590
+ QueryParameter(name="searchIgnoreCase", required=False, title="Search should be case sensitive"),
591
+ ]
592
+ self.signature = inspect.Signature(
593
+ parameters=[
594
+ inspect.Parameter(
595
+ "search_string", kind=inspect.Parameter.KEYWORD_ONLY, default=None, annotation=search_annotation
596
+ ),
597
+ inspect.Parameter(
598
+ "ignore_case",
599
+ kind=inspect.Parameter.KEYWORD_ONLY,
600
+ default=ignore_case_default,
601
+ annotation=ignore_annotation,
602
+ ),
603
+ ],
604
+ return_annotation=self.return_annotation,
605
+ )
606
+ self.annotations = {
607
+ "search_string": search_annotation,
608
+ "ignore_case": ignore_annotation,
609
+ "return": SearchFilter,
610
+ }
611
+
612
+ def __call__(self, search_string: StringOrNone = None, ignore_case: BooleanOrNone = None) -> SearchFilter:
613
+ field_names: set[Any] = (
614
+ set(self.search_fields.split(",")) if isinstance(self.search_fields, str) else set(self.search_fields)
615
+ )
616
+ return SearchFilter(
617
+ field_name=field_names,
618
+ value=search_string,
619
+ ignore_case=self.ignore_case_default if ignore_case is None else ignore_case,
620
+ )
621
+
622
+
623
+ class _OrderByProvider:
624
+ def __init__(self, sort_field: SortField, config: FilterConfig) -> None:
625
+ self.sort_resolution = _resolve_sort_field_aliases(
626
+ sort_field,
627
+ sort_field_aliases=config.get("sort_field_aliases"),
628
+ sort_field_camelize=config.get("sort_field_camelize", True),
629
+ )
630
+ self.allowed_field_names = ", ".join(self.sort_resolution.allowed_display_names)
631
+ self.sort_order_default: SortOrder = config.get("sort_order", "desc")
632
+ self.return_annotation = OrderByFilter
633
+ field_annotation = Annotated[
634
+ StringOrNone, QueryParameter(name="orderBy", required=False, title="Order by field")
635
+ ]
636
+ order_annotation = Annotated[
637
+ SortOrderOrNone, QueryParameter(name="sortOrder", required=False, title="Field to search")
638
+ ]
639
+ self.signature = inspect.Signature(
640
+ parameters=[
641
+ inspect.Parameter(
642
+ "field_name",
643
+ kind=inspect.Parameter.KEYWORD_ONLY,
644
+ default=self.sort_resolution.default_query_value,
645
+ annotation=field_annotation,
646
+ ),
647
+ inspect.Parameter(
648
+ "sort_order",
649
+ kind=inspect.Parameter.KEYWORD_ONLY,
650
+ default=self.sort_order_default,
651
+ annotation=order_annotation,
652
+ ),
653
+ ],
654
+ return_annotation=self.return_annotation,
655
+ )
656
+ self.annotations = {"field_name": field_annotation, "sort_order": order_annotation, "return": OrderByFilter}
657
+
658
+ def __call__(self, field_name: StringOrNone = None, sort_order: SortOrderOrNone = None) -> OrderByFilter:
659
+ resolved_field = (
660
+ self.sort_resolution.normalize(field_name) if field_name else self.sort_resolution.default_field
661
+ )
662
+ if resolved_field is None:
663
+ msg = f"Invalid orderBy field '{field_name}'. Allowed fields: {self.allowed_field_names}"
664
+ raise ValidationException(detail=msg)
665
+ return OrderByFilter(field_name=resolved_field, sort_order=sort_order or self.sort_order_default)
666
+
667
+
668
+ def _resolve_sort_field_aliases(
669
+ sort_field: SortField, sort_field_aliases: Mapping[str, str] | None = None, sort_field_camelize: bool = True
670
+ ) -> _SortFieldResolution:
671
+ fields = _coerce_sort_fields(sort_field)
672
+ allowed_fields = frozenset(fields)
673
+ inbound_aliases: dict[str, str] = {}
674
+ field_display_names = {field: field for field in fields}
675
+
676
+ for field in fields:
677
+ _add_sort_field_alias(inbound_aliases, alias=field, field=field)
678
+
679
+ if sort_field_camelize:
680
+ for field in fields:
681
+ alias = camelize(field)
682
+ _add_sort_field_alias(inbound_aliases, alias=alias, field=field)
683
+ field_display_names[field] = alias
684
+
685
+ if sort_field_aliases:
686
+ for alias, field in sort_field_aliases.items():
687
+ if field not in allowed_fields:
688
+ msg = f"sort field alias '{alias}' targets unknown sort field '{field}'"
689
+ raise ValueError(msg)
690
+ _add_sort_field_alias(inbound_aliases, alias=alias, field=field)
691
+ field_display_names[field] = alias
692
+
693
+ allowed_display_names = tuple(field_display_names[field] for field in fields)
694
+ return _SortFieldResolution(
695
+ default_field=fields[0],
696
+ default_query_value=field_display_names[fields[0]],
697
+ allowed_fields=allowed_fields,
698
+ inbound_aliases=inbound_aliases,
699
+ field_display_names=field_display_names,
700
+ allowed_display_names=allowed_display_names,
701
+ )
702
+
703
+
704
+ def _coerce_sort_fields(sort_field: SortField) -> tuple[str, ...]:
705
+ if isinstance(sort_field, str):
706
+ return (sort_field,)
707
+ fields = tuple(sorted(sort_field)) if isinstance(sort_field, set) else tuple(sort_field)
708
+ if not fields:
709
+ msg = "sort_field must include at least one field"
710
+ raise ValueError(msg)
711
+ return fields
712
+
713
+
714
+ def _add_sort_field_alias(inbound_aliases: dict[str, str], *, alias: str, field: str) -> None:
715
+ existing_field = inbound_aliases.get(alias)
716
+ if existing_field is None or existing_field == field:
717
+ inbound_aliases[alias] = field
718
+ return
719
+
720
+ msg = f"ambiguous sort field alias '{alias}' maps to both '{existing_field}' and '{field}'"
721
+ raise ValueError(msg)
722
+
723
+
724
+ def _provide_collection_filter(context: _CollectionFilterProvider, **kwargs: Any) -> Any:
725
+ values = kwargs.get(context.param_name)
726
+ return context.filter_cls[context.type_hint](field_name=context.field_name, values=values) if values else None
727
+
728
+
729
+ def _provide_null_filter(context: _NullFilterProvider, **kwargs: Any) -> Any:
730
+ return context.filter_cls(field_name=context.field_name) if kwargs.get(context.param_name) else None
731
+
732
+
733
+ def _provide_before_after_filter(context: _BeforeAfterFilterProvider, **kwargs: Any) -> BeforeAfterFilter:
734
+ return BeforeAfterFilter(context.field_name, kwargs.get(context.before_param), kwargs.get(context.after_param))
735
+
736
+
737
+ def _provide_id_filter(context: _IdFilterProvider, ids: list[Any] | None = None) -> InCollectionFilter[Any]:
738
+ return InCollectionFilter(field_name=context.field_name, values=ids)
739
+
740
+
741
+ def _provide_limit_offset_filter(
742
+ context: _LimitOffsetFilterProvider, current_page: int = 1, page_size: int | None = None
743
+ ) -> LimitOffsetFilter:
744
+ resolved_page_size = page_size if page_size is not None else context.default_page_size
745
+ return LimitOffsetFilter(resolved_page_size, resolved_page_size * (current_page - 1))
746
+
747
+
748
+ def _provide_search_filter(
749
+ context: _SearchFilterProvider, search_string: StringOrNone = None, ignore_case: BooleanOrNone = None
750
+ ) -> SearchFilter:
751
+ field_names: set[Any] = (
752
+ set(context.search_fields.split(",")) if isinstance(context.search_fields, str) else set(context.search_fields)
753
+ )
754
+ return SearchFilter(
755
+ field_name=field_names,
756
+ value=search_string,
757
+ ignore_case=context.ignore_case_default if ignore_case is None else ignore_case,
758
+ )
759
+
760
+
761
+ def _provide_order_by_filter(
762
+ context: _OrderByProvider, field_name: StringOrNone = None, sort_order: SortOrderOrNone = None
763
+ ) -> OrderByFilter:
764
+ resolved_field = (
765
+ context.sort_resolution.normalize(field_name) if field_name else context.sort_resolution.default_field
766
+ )
767
+ if resolved_field is None:
768
+ msg = f"Invalid orderBy field '{field_name}'. Allowed fields: {context.allowed_field_names}"
769
+ raise ValidationException(detail=msg)
770
+ return OrderByFilter(field_name=resolved_field, sort_order=sort_order or context.sort_order_default)
771
+
772
+
773
+ def _build_in_collection_provider(field: FieldNameType, *, negated: bool) -> Callable[..., Any]:
774
+ return _bind_provider(_CollectionFilterProvider(field, negated=negated), _provide_collection_filter)
775
+
776
+
777
+ def _build_null_provider(field_name: str, *, negated: bool) -> Callable[..., Any]:
778
+ return _bind_provider(_NullFilterProvider(field_name, negated=negated), _provide_null_filter)
779
+
780
+
781
+ def _build_before_after_provider(field_name: str, before_alias: str, after_alias: str) -> Callable[..., Any]:
782
+ return _bind_provider(
783
+ _BeforeAfterFilterProvider(field_name, before_alias, after_alias), _provide_before_after_filter
784
+ )