sqlspec 0.36.0__cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.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 (531) hide show
  1. ac8f31065839703b4e70__mypyc.cpython-310-aarch64-linux-gnu.so +0 -0
  2. sqlspec/__init__.py +140 -0
  3. sqlspec/__main__.py +12 -0
  4. sqlspec/__metadata__.py +14 -0
  5. sqlspec/_serialization.py +315 -0
  6. sqlspec/_typing.py +700 -0
  7. sqlspec/adapters/__init__.py +0 -0
  8. sqlspec/adapters/adbc/__init__.py +5 -0
  9. sqlspec/adapters/adbc/_typing.py +82 -0
  10. sqlspec/adapters/adbc/adk/__init__.py +5 -0
  11. sqlspec/adapters/adbc/adk/store.py +1273 -0
  12. sqlspec/adapters/adbc/config.py +295 -0
  13. sqlspec/adapters/adbc/core.cpython-310-aarch64-linux-gnu.so +0 -0
  14. sqlspec/adapters/adbc/core.py +735 -0
  15. sqlspec/adapters/adbc/data_dictionary.py +334 -0
  16. sqlspec/adapters/adbc/driver.py +529 -0
  17. sqlspec/adapters/adbc/events/__init__.py +5 -0
  18. sqlspec/adapters/adbc/events/store.py +285 -0
  19. sqlspec/adapters/adbc/litestar/__init__.py +5 -0
  20. sqlspec/adapters/adbc/litestar/store.py +502 -0
  21. sqlspec/adapters/adbc/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  22. sqlspec/adapters/adbc/type_converter.py +140 -0
  23. sqlspec/adapters/aiosqlite/__init__.py +25 -0
  24. sqlspec/adapters/aiosqlite/_typing.py +82 -0
  25. sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
  26. sqlspec/adapters/aiosqlite/adk/store.py +818 -0
  27. sqlspec/adapters/aiosqlite/config.py +334 -0
  28. sqlspec/adapters/aiosqlite/core.cpython-310-aarch64-linux-gnu.so +0 -0
  29. sqlspec/adapters/aiosqlite/core.py +315 -0
  30. sqlspec/adapters/aiosqlite/data_dictionary.py +208 -0
  31. sqlspec/adapters/aiosqlite/driver.py +313 -0
  32. sqlspec/adapters/aiosqlite/events/__init__.py +5 -0
  33. sqlspec/adapters/aiosqlite/events/store.py +20 -0
  34. sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
  35. sqlspec/adapters/aiosqlite/litestar/store.py +279 -0
  36. sqlspec/adapters/aiosqlite/pool.py +533 -0
  37. sqlspec/adapters/asyncmy/__init__.py +21 -0
  38. sqlspec/adapters/asyncmy/_typing.py +87 -0
  39. sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
  40. sqlspec/adapters/asyncmy/adk/store.py +703 -0
  41. sqlspec/adapters/asyncmy/config.py +302 -0
  42. sqlspec/adapters/asyncmy/core.cpython-310-aarch64-linux-gnu.so +0 -0
  43. sqlspec/adapters/asyncmy/core.py +360 -0
  44. sqlspec/adapters/asyncmy/data_dictionary.py +124 -0
  45. sqlspec/adapters/asyncmy/driver.py +383 -0
  46. sqlspec/adapters/asyncmy/events/__init__.py +5 -0
  47. sqlspec/adapters/asyncmy/events/store.py +104 -0
  48. sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
  49. sqlspec/adapters/asyncmy/litestar/store.py +296 -0
  50. sqlspec/adapters/asyncpg/__init__.py +19 -0
  51. sqlspec/adapters/asyncpg/_typing.py +88 -0
  52. sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
  53. sqlspec/adapters/asyncpg/adk/store.py +748 -0
  54. sqlspec/adapters/asyncpg/config.py +569 -0
  55. sqlspec/adapters/asyncpg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  56. sqlspec/adapters/asyncpg/core.py +367 -0
  57. sqlspec/adapters/asyncpg/data_dictionary.py +162 -0
  58. sqlspec/adapters/asyncpg/driver.py +487 -0
  59. sqlspec/adapters/asyncpg/events/__init__.py +6 -0
  60. sqlspec/adapters/asyncpg/events/backend.py +286 -0
  61. sqlspec/adapters/asyncpg/events/store.py +40 -0
  62. sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
  63. sqlspec/adapters/asyncpg/litestar/store.py +251 -0
  64. sqlspec/adapters/bigquery/__init__.py +14 -0
  65. sqlspec/adapters/bigquery/_typing.py +86 -0
  66. sqlspec/adapters/bigquery/adk/__init__.py +5 -0
  67. sqlspec/adapters/bigquery/adk/store.py +827 -0
  68. sqlspec/adapters/bigquery/config.py +353 -0
  69. sqlspec/adapters/bigquery/core.cpython-310-aarch64-linux-gnu.so +0 -0
  70. sqlspec/adapters/bigquery/core.py +715 -0
  71. sqlspec/adapters/bigquery/data_dictionary.py +128 -0
  72. sqlspec/adapters/bigquery/driver.py +548 -0
  73. sqlspec/adapters/bigquery/events/__init__.py +5 -0
  74. sqlspec/adapters/bigquery/events/store.py +139 -0
  75. sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
  76. sqlspec/adapters/bigquery/litestar/store.py +325 -0
  77. sqlspec/adapters/bigquery/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  78. sqlspec/adapters/bigquery/type_converter.py +107 -0
  79. sqlspec/adapters/cockroach_asyncpg/__init__.py +24 -0
  80. sqlspec/adapters/cockroach_asyncpg/_typing.py +72 -0
  81. sqlspec/adapters/cockroach_asyncpg/adk/__init__.py +3 -0
  82. sqlspec/adapters/cockroach_asyncpg/adk/store.py +410 -0
  83. sqlspec/adapters/cockroach_asyncpg/config.py +238 -0
  84. sqlspec/adapters/cockroach_asyncpg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  85. sqlspec/adapters/cockroach_asyncpg/core.py +55 -0
  86. sqlspec/adapters/cockroach_asyncpg/data_dictionary.py +107 -0
  87. sqlspec/adapters/cockroach_asyncpg/driver.py +144 -0
  88. sqlspec/adapters/cockroach_asyncpg/events/__init__.py +3 -0
  89. sqlspec/adapters/cockroach_asyncpg/events/store.py +20 -0
  90. sqlspec/adapters/cockroach_asyncpg/litestar/__init__.py +3 -0
  91. sqlspec/adapters/cockroach_asyncpg/litestar/store.py +142 -0
  92. sqlspec/adapters/cockroach_psycopg/__init__.py +38 -0
  93. sqlspec/adapters/cockroach_psycopg/_typing.py +129 -0
  94. sqlspec/adapters/cockroach_psycopg/adk/__init__.py +13 -0
  95. sqlspec/adapters/cockroach_psycopg/adk/store.py +868 -0
  96. sqlspec/adapters/cockroach_psycopg/config.py +484 -0
  97. sqlspec/adapters/cockroach_psycopg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  98. sqlspec/adapters/cockroach_psycopg/core.py +63 -0
  99. sqlspec/adapters/cockroach_psycopg/data_dictionary.py +215 -0
  100. sqlspec/adapters/cockroach_psycopg/driver.py +284 -0
  101. sqlspec/adapters/cockroach_psycopg/events/__init__.py +6 -0
  102. sqlspec/adapters/cockroach_psycopg/events/store.py +34 -0
  103. sqlspec/adapters/cockroach_psycopg/litestar/__init__.py +3 -0
  104. sqlspec/adapters/cockroach_psycopg/litestar/store.py +325 -0
  105. sqlspec/adapters/duckdb/__init__.py +25 -0
  106. sqlspec/adapters/duckdb/_typing.py +81 -0
  107. sqlspec/adapters/duckdb/adk/__init__.py +14 -0
  108. sqlspec/adapters/duckdb/adk/store.py +850 -0
  109. sqlspec/adapters/duckdb/config.py +463 -0
  110. sqlspec/adapters/duckdb/core.cpython-310-aarch64-linux-gnu.so +0 -0
  111. sqlspec/adapters/duckdb/core.py +257 -0
  112. sqlspec/adapters/duckdb/data_dictionary.py +140 -0
  113. sqlspec/adapters/duckdb/driver.py +430 -0
  114. sqlspec/adapters/duckdb/events/__init__.py +5 -0
  115. sqlspec/adapters/duckdb/events/store.py +57 -0
  116. sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
  117. sqlspec/adapters/duckdb/litestar/store.py +330 -0
  118. sqlspec/adapters/duckdb/pool.py +293 -0
  119. sqlspec/adapters/duckdb/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  120. sqlspec/adapters/duckdb/type_converter.py +118 -0
  121. sqlspec/adapters/mock/__init__.py +72 -0
  122. sqlspec/adapters/mock/_typing.py +147 -0
  123. sqlspec/adapters/mock/config.py +483 -0
  124. sqlspec/adapters/mock/core.py +319 -0
  125. sqlspec/adapters/mock/data_dictionary.py +366 -0
  126. sqlspec/adapters/mock/driver.py +721 -0
  127. sqlspec/adapters/mysqlconnector/__init__.py +36 -0
  128. sqlspec/adapters/mysqlconnector/_typing.py +141 -0
  129. sqlspec/adapters/mysqlconnector/adk/__init__.py +15 -0
  130. sqlspec/adapters/mysqlconnector/adk/store.py +1060 -0
  131. sqlspec/adapters/mysqlconnector/config.py +394 -0
  132. sqlspec/adapters/mysqlconnector/core.cpython-310-aarch64-linux-gnu.so +0 -0
  133. sqlspec/adapters/mysqlconnector/core.py +303 -0
  134. sqlspec/adapters/mysqlconnector/data_dictionary.py +235 -0
  135. sqlspec/adapters/mysqlconnector/driver.py +483 -0
  136. sqlspec/adapters/mysqlconnector/events/__init__.py +8 -0
  137. sqlspec/adapters/mysqlconnector/events/store.py +98 -0
  138. sqlspec/adapters/mysqlconnector/litestar/__init__.py +5 -0
  139. sqlspec/adapters/mysqlconnector/litestar/store.py +426 -0
  140. sqlspec/adapters/oracledb/__init__.py +60 -0
  141. sqlspec/adapters/oracledb/_numpy_handlers.py +141 -0
  142. sqlspec/adapters/oracledb/_typing.py +182 -0
  143. sqlspec/adapters/oracledb/_uuid_handlers.py +166 -0
  144. sqlspec/adapters/oracledb/adk/__init__.py +10 -0
  145. sqlspec/adapters/oracledb/adk/store.py +2369 -0
  146. sqlspec/adapters/oracledb/config.py +550 -0
  147. sqlspec/adapters/oracledb/core.cpython-310-aarch64-linux-gnu.so +0 -0
  148. sqlspec/adapters/oracledb/core.py +543 -0
  149. sqlspec/adapters/oracledb/data_dictionary.py +536 -0
  150. sqlspec/adapters/oracledb/driver.py +1229 -0
  151. sqlspec/adapters/oracledb/events/__init__.py +16 -0
  152. sqlspec/adapters/oracledb/events/backend.py +347 -0
  153. sqlspec/adapters/oracledb/events/store.py +420 -0
  154. sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
  155. sqlspec/adapters/oracledb/litestar/store.py +781 -0
  156. sqlspec/adapters/oracledb/migrations.py +535 -0
  157. sqlspec/adapters/oracledb/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  158. sqlspec/adapters/oracledb/type_converter.py +211 -0
  159. sqlspec/adapters/psqlpy/__init__.py +17 -0
  160. sqlspec/adapters/psqlpy/_typing.py +79 -0
  161. sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
  162. sqlspec/adapters/psqlpy/adk/store.py +766 -0
  163. sqlspec/adapters/psqlpy/config.py +304 -0
  164. sqlspec/adapters/psqlpy/core.cpython-310-aarch64-linux-gnu.so +0 -0
  165. sqlspec/adapters/psqlpy/core.py +480 -0
  166. sqlspec/adapters/psqlpy/data_dictionary.py +126 -0
  167. sqlspec/adapters/psqlpy/driver.py +438 -0
  168. sqlspec/adapters/psqlpy/events/__init__.py +6 -0
  169. sqlspec/adapters/psqlpy/events/backend.py +310 -0
  170. sqlspec/adapters/psqlpy/events/store.py +20 -0
  171. sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
  172. sqlspec/adapters/psqlpy/litestar/store.py +270 -0
  173. sqlspec/adapters/psqlpy/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  174. sqlspec/adapters/psqlpy/type_converter.py +113 -0
  175. sqlspec/adapters/psycopg/__init__.py +32 -0
  176. sqlspec/adapters/psycopg/_typing.py +164 -0
  177. sqlspec/adapters/psycopg/adk/__init__.py +10 -0
  178. sqlspec/adapters/psycopg/adk/store.py +1387 -0
  179. sqlspec/adapters/psycopg/config.py +576 -0
  180. sqlspec/adapters/psycopg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  181. sqlspec/adapters/psycopg/core.py +450 -0
  182. sqlspec/adapters/psycopg/data_dictionary.py +289 -0
  183. sqlspec/adapters/psycopg/driver.py +975 -0
  184. sqlspec/adapters/psycopg/events/__init__.py +20 -0
  185. sqlspec/adapters/psycopg/events/backend.py +458 -0
  186. sqlspec/adapters/psycopg/events/store.py +42 -0
  187. sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
  188. sqlspec/adapters/psycopg/litestar/store.py +552 -0
  189. sqlspec/adapters/psycopg/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  190. sqlspec/adapters/psycopg/type_converter.py +93 -0
  191. sqlspec/adapters/pymysql/__init__.py +21 -0
  192. sqlspec/adapters/pymysql/_typing.py +71 -0
  193. sqlspec/adapters/pymysql/adk/__init__.py +5 -0
  194. sqlspec/adapters/pymysql/adk/store.py +540 -0
  195. sqlspec/adapters/pymysql/config.py +195 -0
  196. sqlspec/adapters/pymysql/core.cpython-310-aarch64-linux-gnu.so +0 -0
  197. sqlspec/adapters/pymysql/core.py +299 -0
  198. sqlspec/adapters/pymysql/data_dictionary.py +122 -0
  199. sqlspec/adapters/pymysql/driver.py +259 -0
  200. sqlspec/adapters/pymysql/events/__init__.py +5 -0
  201. sqlspec/adapters/pymysql/events/store.py +50 -0
  202. sqlspec/adapters/pymysql/litestar/__init__.py +5 -0
  203. sqlspec/adapters/pymysql/litestar/store.py +232 -0
  204. sqlspec/adapters/pymysql/pool.py +137 -0
  205. sqlspec/adapters/spanner/__init__.py +40 -0
  206. sqlspec/adapters/spanner/_typing.py +86 -0
  207. sqlspec/adapters/spanner/adk/__init__.py +5 -0
  208. sqlspec/adapters/spanner/adk/store.py +732 -0
  209. sqlspec/adapters/spanner/config.py +352 -0
  210. sqlspec/adapters/spanner/core.cpython-310-aarch64-linux-gnu.so +0 -0
  211. sqlspec/adapters/spanner/core.py +188 -0
  212. sqlspec/adapters/spanner/data_dictionary.py +120 -0
  213. sqlspec/adapters/spanner/dialect/__init__.py +6 -0
  214. sqlspec/adapters/spanner/dialect/_spangres.py +57 -0
  215. sqlspec/adapters/spanner/dialect/_spanner.py +130 -0
  216. sqlspec/adapters/spanner/driver.py +373 -0
  217. sqlspec/adapters/spanner/events/__init__.py +5 -0
  218. sqlspec/adapters/spanner/events/store.py +187 -0
  219. sqlspec/adapters/spanner/litestar/__init__.py +5 -0
  220. sqlspec/adapters/spanner/litestar/store.py +291 -0
  221. sqlspec/adapters/spanner/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  222. sqlspec/adapters/spanner/type_converter.py +331 -0
  223. sqlspec/adapters/sqlite/__init__.py +19 -0
  224. sqlspec/adapters/sqlite/_typing.py +80 -0
  225. sqlspec/adapters/sqlite/adk/__init__.py +5 -0
  226. sqlspec/adapters/sqlite/adk/store.py +958 -0
  227. sqlspec/adapters/sqlite/config.py +280 -0
  228. sqlspec/adapters/sqlite/core.cpython-310-aarch64-linux-gnu.so +0 -0
  229. sqlspec/adapters/sqlite/core.py +312 -0
  230. sqlspec/adapters/sqlite/data_dictionary.py +202 -0
  231. sqlspec/adapters/sqlite/driver.py +359 -0
  232. sqlspec/adapters/sqlite/events/__init__.py +5 -0
  233. sqlspec/adapters/sqlite/events/store.py +20 -0
  234. sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
  235. sqlspec/adapters/sqlite/litestar/store.py +316 -0
  236. sqlspec/adapters/sqlite/pool.py +198 -0
  237. sqlspec/adapters/sqlite/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  238. sqlspec/adapters/sqlite/type_converter.py +114 -0
  239. sqlspec/base.py +747 -0
  240. sqlspec/builder/__init__.py +179 -0
  241. sqlspec/builder/_base.cpython-310-aarch64-linux-gnu.so +0 -0
  242. sqlspec/builder/_base.py +1022 -0
  243. sqlspec/builder/_column.cpython-310-aarch64-linux-gnu.so +0 -0
  244. sqlspec/builder/_column.py +521 -0
  245. sqlspec/builder/_ddl.cpython-310-aarch64-linux-gnu.so +0 -0
  246. sqlspec/builder/_ddl.py +1642 -0
  247. sqlspec/builder/_delete.cpython-310-aarch64-linux-gnu.so +0 -0
  248. sqlspec/builder/_delete.py +95 -0
  249. sqlspec/builder/_dml.cpython-310-aarch64-linux-gnu.so +0 -0
  250. sqlspec/builder/_dml.py +365 -0
  251. sqlspec/builder/_explain.cpython-310-aarch64-linux-gnu.so +0 -0
  252. sqlspec/builder/_explain.py +579 -0
  253. sqlspec/builder/_expression_wrappers.cpython-310-aarch64-linux-gnu.so +0 -0
  254. sqlspec/builder/_expression_wrappers.py +46 -0
  255. sqlspec/builder/_factory.cpython-310-aarch64-linux-gnu.so +0 -0
  256. sqlspec/builder/_factory.py +1697 -0
  257. sqlspec/builder/_insert.cpython-310-aarch64-linux-gnu.so +0 -0
  258. sqlspec/builder/_insert.py +328 -0
  259. sqlspec/builder/_join.cpython-310-aarch64-linux-gnu.so +0 -0
  260. sqlspec/builder/_join.py +499 -0
  261. sqlspec/builder/_merge.cpython-310-aarch64-linux-gnu.so +0 -0
  262. sqlspec/builder/_merge.py +821 -0
  263. sqlspec/builder/_parsing_utils.cpython-310-aarch64-linux-gnu.so +0 -0
  264. sqlspec/builder/_parsing_utils.py +297 -0
  265. sqlspec/builder/_select.cpython-310-aarch64-linux-gnu.so +0 -0
  266. sqlspec/builder/_select.py +1660 -0
  267. sqlspec/builder/_temporal.cpython-310-aarch64-linux-gnu.so +0 -0
  268. sqlspec/builder/_temporal.py +139 -0
  269. sqlspec/builder/_update.cpython-310-aarch64-linux-gnu.so +0 -0
  270. sqlspec/builder/_update.py +173 -0
  271. sqlspec/builder/_vector_expressions.py +267 -0
  272. sqlspec/cli.py +911 -0
  273. sqlspec/config.py +1755 -0
  274. sqlspec/core/__init__.py +374 -0
  275. sqlspec/core/_correlation.cpython-310-aarch64-linux-gnu.so +0 -0
  276. sqlspec/core/_correlation.py +176 -0
  277. sqlspec/core/cache.cpython-310-aarch64-linux-gnu.so +0 -0
  278. sqlspec/core/cache.py +1069 -0
  279. sqlspec/core/compiler.cpython-310-aarch64-linux-gnu.so +0 -0
  280. sqlspec/core/compiler.py +954 -0
  281. sqlspec/core/explain.cpython-310-aarch64-linux-gnu.so +0 -0
  282. sqlspec/core/explain.py +275 -0
  283. sqlspec/core/filters.cpython-310-aarch64-linux-gnu.so +0 -0
  284. sqlspec/core/filters.py +952 -0
  285. sqlspec/core/hashing.cpython-310-aarch64-linux-gnu.so +0 -0
  286. sqlspec/core/hashing.py +262 -0
  287. sqlspec/core/metrics.cpython-310-aarch64-linux-gnu.so +0 -0
  288. sqlspec/core/metrics.py +83 -0
  289. sqlspec/core/parameters/__init__.py +71 -0
  290. sqlspec/core/parameters/_alignment.cpython-310-aarch64-linux-gnu.so +0 -0
  291. sqlspec/core/parameters/_alignment.py +270 -0
  292. sqlspec/core/parameters/_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  293. sqlspec/core/parameters/_converter.py +543 -0
  294. sqlspec/core/parameters/_processor.cpython-310-aarch64-linux-gnu.so +0 -0
  295. sqlspec/core/parameters/_processor.py +505 -0
  296. sqlspec/core/parameters/_registry.cpython-310-aarch64-linux-gnu.so +0 -0
  297. sqlspec/core/parameters/_registry.py +206 -0
  298. sqlspec/core/parameters/_transformers.cpython-310-aarch64-linux-gnu.so +0 -0
  299. sqlspec/core/parameters/_transformers.py +292 -0
  300. sqlspec/core/parameters/_types.cpython-310-aarch64-linux-gnu.so +0 -0
  301. sqlspec/core/parameters/_types.py +499 -0
  302. sqlspec/core/parameters/_validator.cpython-310-aarch64-linux-gnu.so +0 -0
  303. sqlspec/core/parameters/_validator.py +180 -0
  304. sqlspec/core/pipeline.cpython-310-aarch64-linux-gnu.so +0 -0
  305. sqlspec/core/pipeline.py +319 -0
  306. sqlspec/core/query_modifiers.cpython-310-aarch64-linux-gnu.so +0 -0
  307. sqlspec/core/query_modifiers.py +437 -0
  308. sqlspec/core/result/__init__.py +23 -0
  309. sqlspec/core/result/_base.cpython-310-aarch64-linux-gnu.so +0 -0
  310. sqlspec/core/result/_base.py +1121 -0
  311. sqlspec/core/result/_io.cpython-310-aarch64-linux-gnu.so +0 -0
  312. sqlspec/core/result/_io.py +28 -0
  313. sqlspec/core/splitter.cpython-310-aarch64-linux-gnu.so +0 -0
  314. sqlspec/core/splitter.py +966 -0
  315. sqlspec/core/stack.cpython-310-aarch64-linux-gnu.so +0 -0
  316. sqlspec/core/stack.py +163 -0
  317. sqlspec/core/statement.cpython-310-aarch64-linux-gnu.so +0 -0
  318. sqlspec/core/statement.py +1503 -0
  319. sqlspec/core/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  320. sqlspec/core/type_converter.py +339 -0
  321. sqlspec/data_dictionary/__init__.py +22 -0
  322. sqlspec/data_dictionary/_loader.py +123 -0
  323. sqlspec/data_dictionary/_registry.cpython-310-aarch64-linux-gnu.so +0 -0
  324. sqlspec/data_dictionary/_registry.py +74 -0
  325. sqlspec/data_dictionary/_types.cpython-310-aarch64-linux-gnu.so +0 -0
  326. sqlspec/data_dictionary/_types.py +121 -0
  327. sqlspec/data_dictionary/dialects/__init__.py +21 -0
  328. sqlspec/data_dictionary/dialects/bigquery.cpython-310-aarch64-linux-gnu.so +0 -0
  329. sqlspec/data_dictionary/dialects/bigquery.py +49 -0
  330. sqlspec/data_dictionary/dialects/cockroachdb.cpython-310-aarch64-linux-gnu.so +0 -0
  331. sqlspec/data_dictionary/dialects/cockroachdb.py +43 -0
  332. sqlspec/data_dictionary/dialects/duckdb.cpython-310-aarch64-linux-gnu.so +0 -0
  333. sqlspec/data_dictionary/dialects/duckdb.py +47 -0
  334. sqlspec/data_dictionary/dialects/mysql.cpython-310-aarch64-linux-gnu.so +0 -0
  335. sqlspec/data_dictionary/dialects/mysql.py +42 -0
  336. sqlspec/data_dictionary/dialects/oracle.cpython-310-aarch64-linux-gnu.so +0 -0
  337. sqlspec/data_dictionary/dialects/oracle.py +34 -0
  338. sqlspec/data_dictionary/dialects/postgres.cpython-310-aarch64-linux-gnu.so +0 -0
  339. sqlspec/data_dictionary/dialects/postgres.py +46 -0
  340. sqlspec/data_dictionary/dialects/spanner.cpython-310-aarch64-linux-gnu.so +0 -0
  341. sqlspec/data_dictionary/dialects/spanner.py +37 -0
  342. sqlspec/data_dictionary/dialects/sqlite.cpython-310-aarch64-linux-gnu.so +0 -0
  343. sqlspec/data_dictionary/dialects/sqlite.py +42 -0
  344. sqlspec/data_dictionary/sql/.gitkeep +0 -0
  345. sqlspec/data_dictionary/sql/bigquery/columns.sql +23 -0
  346. sqlspec/data_dictionary/sql/bigquery/foreign_keys.sql +34 -0
  347. sqlspec/data_dictionary/sql/bigquery/indexes.sql +19 -0
  348. sqlspec/data_dictionary/sql/bigquery/tables.sql +33 -0
  349. sqlspec/data_dictionary/sql/bigquery/version.sql +3 -0
  350. sqlspec/data_dictionary/sql/cockroachdb/columns.sql +34 -0
  351. sqlspec/data_dictionary/sql/cockroachdb/foreign_keys.sql +40 -0
  352. sqlspec/data_dictionary/sql/cockroachdb/indexes.sql +32 -0
  353. sqlspec/data_dictionary/sql/cockroachdb/tables.sql +44 -0
  354. sqlspec/data_dictionary/sql/cockroachdb/version.sql +3 -0
  355. sqlspec/data_dictionary/sql/duckdb/columns.sql +23 -0
  356. sqlspec/data_dictionary/sql/duckdb/foreign_keys.sql +36 -0
  357. sqlspec/data_dictionary/sql/duckdb/indexes.sql +19 -0
  358. sqlspec/data_dictionary/sql/duckdb/tables.sql +38 -0
  359. sqlspec/data_dictionary/sql/duckdb/version.sql +3 -0
  360. sqlspec/data_dictionary/sql/mysql/columns.sql +23 -0
  361. sqlspec/data_dictionary/sql/mysql/foreign_keys.sql +28 -0
  362. sqlspec/data_dictionary/sql/mysql/indexes.sql +26 -0
  363. sqlspec/data_dictionary/sql/mysql/tables.sql +33 -0
  364. sqlspec/data_dictionary/sql/mysql/version.sql +3 -0
  365. sqlspec/data_dictionary/sql/oracle/columns.sql +23 -0
  366. sqlspec/data_dictionary/sql/oracle/foreign_keys.sql +48 -0
  367. sqlspec/data_dictionary/sql/oracle/indexes.sql +44 -0
  368. sqlspec/data_dictionary/sql/oracle/tables.sql +25 -0
  369. sqlspec/data_dictionary/sql/oracle/version.sql +20 -0
  370. sqlspec/data_dictionary/sql/postgres/columns.sql +34 -0
  371. sqlspec/data_dictionary/sql/postgres/foreign_keys.sql +40 -0
  372. sqlspec/data_dictionary/sql/postgres/indexes.sql +56 -0
  373. sqlspec/data_dictionary/sql/postgres/tables.sql +44 -0
  374. sqlspec/data_dictionary/sql/postgres/version.sql +3 -0
  375. sqlspec/data_dictionary/sql/spanner/columns.sql +23 -0
  376. sqlspec/data_dictionary/sql/spanner/foreign_keys.sql +70 -0
  377. sqlspec/data_dictionary/sql/spanner/indexes.sql +30 -0
  378. sqlspec/data_dictionary/sql/spanner/tables.sql +9 -0
  379. sqlspec/data_dictionary/sql/spanner/version.sql +3 -0
  380. sqlspec/data_dictionary/sql/sqlite/columns.sql +23 -0
  381. sqlspec/data_dictionary/sql/sqlite/foreign_keys.sql +22 -0
  382. sqlspec/data_dictionary/sql/sqlite/indexes.sql +7 -0
  383. sqlspec/data_dictionary/sql/sqlite/tables.sql +28 -0
  384. sqlspec/data_dictionary/sql/sqlite/version.sql +3 -0
  385. sqlspec/driver/__init__.py +32 -0
  386. sqlspec/driver/_async.cpython-310-aarch64-linux-gnu.so +0 -0
  387. sqlspec/driver/_async.py +1737 -0
  388. sqlspec/driver/_common.cpython-310-aarch64-linux-gnu.so +0 -0
  389. sqlspec/driver/_common.py +1478 -0
  390. sqlspec/driver/_sql_helpers.cpython-310-aarch64-linux-gnu.so +0 -0
  391. sqlspec/driver/_sql_helpers.py +148 -0
  392. sqlspec/driver/_storage_helpers.cpython-310-aarch64-linux-gnu.so +0 -0
  393. sqlspec/driver/_storage_helpers.py +144 -0
  394. sqlspec/driver/_sync.cpython-310-aarch64-linux-gnu.so +0 -0
  395. sqlspec/driver/_sync.py +1710 -0
  396. sqlspec/exceptions.py +338 -0
  397. sqlspec/extensions/__init__.py +0 -0
  398. sqlspec/extensions/adk/__init__.py +70 -0
  399. sqlspec/extensions/adk/_types.py +51 -0
  400. sqlspec/extensions/adk/converters.py +172 -0
  401. sqlspec/extensions/adk/memory/__init__.py +69 -0
  402. sqlspec/extensions/adk/memory/_types.py +30 -0
  403. sqlspec/extensions/adk/memory/converters.py +149 -0
  404. sqlspec/extensions/adk/memory/service.py +217 -0
  405. sqlspec/extensions/adk/memory/store.py +569 -0
  406. sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +246 -0
  407. sqlspec/extensions/adk/migrations/__init__.py +0 -0
  408. sqlspec/extensions/adk/service.py +225 -0
  409. sqlspec/extensions/adk/store.py +567 -0
  410. sqlspec/extensions/events/__init__.py +51 -0
  411. sqlspec/extensions/events/_channel.py +703 -0
  412. sqlspec/extensions/events/_hints.py +45 -0
  413. sqlspec/extensions/events/_models.py +23 -0
  414. sqlspec/extensions/events/_payload.py +69 -0
  415. sqlspec/extensions/events/_protocols.py +134 -0
  416. sqlspec/extensions/events/_queue.py +461 -0
  417. sqlspec/extensions/events/_store.py +209 -0
  418. sqlspec/extensions/events/migrations/0001_create_event_queue.py +59 -0
  419. sqlspec/extensions/events/migrations/__init__.py +3 -0
  420. sqlspec/extensions/fastapi/__init__.py +19 -0
  421. sqlspec/extensions/fastapi/extension.py +351 -0
  422. sqlspec/extensions/fastapi/providers.py +607 -0
  423. sqlspec/extensions/flask/__init__.py +37 -0
  424. sqlspec/extensions/flask/_state.py +76 -0
  425. sqlspec/extensions/flask/_utils.py +71 -0
  426. sqlspec/extensions/flask/extension.py +519 -0
  427. sqlspec/extensions/litestar/__init__.py +28 -0
  428. sqlspec/extensions/litestar/_utils.py +52 -0
  429. sqlspec/extensions/litestar/channels.py +165 -0
  430. sqlspec/extensions/litestar/cli.py +102 -0
  431. sqlspec/extensions/litestar/config.py +90 -0
  432. sqlspec/extensions/litestar/handlers.py +316 -0
  433. sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
  434. sqlspec/extensions/litestar/migrations/__init__.py +3 -0
  435. sqlspec/extensions/litestar/plugin.py +671 -0
  436. sqlspec/extensions/litestar/providers.py +526 -0
  437. sqlspec/extensions/litestar/store.py +296 -0
  438. sqlspec/extensions/otel/__init__.py +58 -0
  439. sqlspec/extensions/prometheus/__init__.py +113 -0
  440. sqlspec/extensions/starlette/__init__.py +19 -0
  441. sqlspec/extensions/starlette/_state.py +30 -0
  442. sqlspec/extensions/starlette/_utils.py +96 -0
  443. sqlspec/extensions/starlette/extension.py +346 -0
  444. sqlspec/extensions/starlette/middleware.py +235 -0
  445. sqlspec/loader.cpython-310-aarch64-linux-gnu.so +0 -0
  446. sqlspec/loader.py +702 -0
  447. sqlspec/migrations/__init__.py +36 -0
  448. sqlspec/migrations/base.py +731 -0
  449. sqlspec/migrations/commands.py +1232 -0
  450. sqlspec/migrations/context.py +157 -0
  451. sqlspec/migrations/fix.py +204 -0
  452. sqlspec/migrations/loaders.py +443 -0
  453. sqlspec/migrations/runner.py +1172 -0
  454. sqlspec/migrations/templates.py +234 -0
  455. sqlspec/migrations/tracker.py +611 -0
  456. sqlspec/migrations/utils.py +256 -0
  457. sqlspec/migrations/validation.py +207 -0
  458. sqlspec/migrations/version.py +446 -0
  459. sqlspec/observability/__init__.py +55 -0
  460. sqlspec/observability/_common.cpython-310-aarch64-linux-gnu.so +0 -0
  461. sqlspec/observability/_common.py +77 -0
  462. sqlspec/observability/_config.cpython-310-aarch64-linux-gnu.so +0 -0
  463. sqlspec/observability/_config.py +348 -0
  464. sqlspec/observability/_diagnostics.cpython-310-aarch64-linux-gnu.so +0 -0
  465. sqlspec/observability/_diagnostics.py +74 -0
  466. sqlspec/observability/_dispatcher.cpython-310-aarch64-linux-gnu.so +0 -0
  467. sqlspec/observability/_dispatcher.py +152 -0
  468. sqlspec/observability/_formatters/__init__.py +13 -0
  469. sqlspec/observability/_formatters/_aws.cpython-310-aarch64-linux-gnu.so +0 -0
  470. sqlspec/observability/_formatters/_aws.py +102 -0
  471. sqlspec/observability/_formatters/_azure.cpython-310-aarch64-linux-gnu.so +0 -0
  472. sqlspec/observability/_formatters/_azure.py +96 -0
  473. sqlspec/observability/_formatters/_base.cpython-310-aarch64-linux-gnu.so +0 -0
  474. sqlspec/observability/_formatters/_base.py +57 -0
  475. sqlspec/observability/_formatters/_gcp.cpython-310-aarch64-linux-gnu.so +0 -0
  476. sqlspec/observability/_formatters/_gcp.py +131 -0
  477. sqlspec/observability/_formatting.py +58 -0
  478. sqlspec/observability/_observer.cpython-310-aarch64-linux-gnu.so +0 -0
  479. sqlspec/observability/_observer.py +357 -0
  480. sqlspec/observability/_runtime.cpython-310-aarch64-linux-gnu.so +0 -0
  481. sqlspec/observability/_runtime.py +420 -0
  482. sqlspec/observability/_sampling.cpython-310-aarch64-linux-gnu.so +0 -0
  483. sqlspec/observability/_sampling.py +188 -0
  484. sqlspec/observability/_spans.cpython-310-aarch64-linux-gnu.so +0 -0
  485. sqlspec/observability/_spans.py +161 -0
  486. sqlspec/protocols.py +916 -0
  487. sqlspec/py.typed +0 -0
  488. sqlspec/storage/__init__.py +48 -0
  489. sqlspec/storage/_utils.py +104 -0
  490. sqlspec/storage/backends/__init__.py +1 -0
  491. sqlspec/storage/backends/base.py +253 -0
  492. sqlspec/storage/backends/fsspec.py +529 -0
  493. sqlspec/storage/backends/local.py +441 -0
  494. sqlspec/storage/backends/obstore.py +916 -0
  495. sqlspec/storage/errors.py +104 -0
  496. sqlspec/storage/pipeline.py +582 -0
  497. sqlspec/storage/registry.py +301 -0
  498. sqlspec/typing.py +395 -0
  499. sqlspec/utils/__init__.py +7 -0
  500. sqlspec/utils/arrow_helpers.py +318 -0
  501. sqlspec/utils/config_tools.py +332 -0
  502. sqlspec/utils/correlation.cpython-310-aarch64-linux-gnu.so +0 -0
  503. sqlspec/utils/correlation.py +134 -0
  504. sqlspec/utils/deprecation.py +190 -0
  505. sqlspec/utils/fixtures.cpython-310-aarch64-linux-gnu.so +0 -0
  506. sqlspec/utils/fixtures.py +258 -0
  507. sqlspec/utils/logging.py +222 -0
  508. sqlspec/utils/module_loader.py +306 -0
  509. sqlspec/utils/portal.cpython-310-aarch64-linux-gnu.so +0 -0
  510. sqlspec/utils/portal.py +375 -0
  511. sqlspec/utils/schema.cpython-310-aarch64-linux-gnu.so +0 -0
  512. sqlspec/utils/schema.py +485 -0
  513. sqlspec/utils/serializers.cpython-310-aarch64-linux-gnu.so +0 -0
  514. sqlspec/utils/serializers.py +408 -0
  515. sqlspec/utils/singleton.cpython-310-aarch64-linux-gnu.so +0 -0
  516. sqlspec/utils/singleton.py +41 -0
  517. sqlspec/utils/sync_tools.cpython-310-aarch64-linux-gnu.so +0 -0
  518. sqlspec/utils/sync_tools.py +311 -0
  519. sqlspec/utils/text.cpython-310-aarch64-linux-gnu.so +0 -0
  520. sqlspec/utils/text.py +108 -0
  521. sqlspec/utils/type_converters.cpython-310-aarch64-linux-gnu.so +0 -0
  522. sqlspec/utils/type_converters.py +128 -0
  523. sqlspec/utils/type_guards.cpython-310-aarch64-linux-gnu.so +0 -0
  524. sqlspec/utils/type_guards.py +1360 -0
  525. sqlspec/utils/uuids.cpython-310-aarch64-linux-gnu.so +0 -0
  526. sqlspec/utils/uuids.py +225 -0
  527. sqlspec-0.36.0.dist-info/METADATA +205 -0
  528. sqlspec-0.36.0.dist-info/RECORD +531 -0
  529. sqlspec-0.36.0.dist-info/WHEEL +7 -0
  530. sqlspec-0.36.0.dist-info/entry_points.txt +2 -0
  531. sqlspec-0.36.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,703 @@
1
+ """Event channel API with separate sync and async implementations."""
2
+
3
+ import asyncio
4
+ import importlib
5
+ import inspect
6
+ import logging
7
+ import threading
8
+ from collections.abc import AsyncIterator, Iterator
9
+ from dataclasses import dataclass
10
+ from typing import TYPE_CHECKING, Any, cast
11
+
12
+ from sqlspec.exceptions import ImproperConfigurationError, MissingDependencyError
13
+ from sqlspec.extensions.events._hints import get_runtime_hints, resolve_adapter_name
14
+ from sqlspec.extensions.events._models import EventMessage
15
+ from sqlspec.extensions.events._protocols import AsyncEventBackendProtocol, SyncEventBackendProtocol
16
+ from sqlspec.extensions.events._queue import build_queue_backend
17
+ from sqlspec.extensions.events._store import normalize_event_channel_name
18
+ from sqlspec.utils.logging import get_logger, log_with_context
19
+ from sqlspec.utils.type_guards import has_span_attribute
20
+ from sqlspec.utils.uuids import uuid4
21
+
22
+ if TYPE_CHECKING:
23
+ from sqlspec.config import AsyncDatabaseConfig, SyncDatabaseConfig
24
+ from sqlspec.extensions.events._protocols import AsyncEventHandler, SyncEventHandler
25
+ from sqlspec.observability import ObservabilityRuntime
26
+
27
+ logger = get_logger("sqlspec.events.channel")
28
+
29
+ __all__ = (
30
+ "AsyncEventChannel",
31
+ "AsyncEventListener",
32
+ "EventMessage",
33
+ "SyncEventChannel",
34
+ "SyncEventListener",
35
+ "load_native_backend",
36
+ "resolve_poll_interval",
37
+ )
38
+
39
+ _ADAPTER_MODULE_PARTS = 3
40
+
41
+
42
+ @dataclass(slots=True)
43
+ class AsyncEventListener:
44
+ """Represents a running async listener task."""
45
+
46
+ id: str
47
+ channel: str
48
+ task: "asyncio.Task[Any]"
49
+ stop_event: "asyncio.Event"
50
+ poll_interval: float
51
+
52
+ async def stop(self) -> None:
53
+ """Signal the listener to stop and await task completion."""
54
+ self.stop_event.set()
55
+ if not self.task.done():
56
+ await self.task
57
+
58
+
59
+ @dataclass(slots=True)
60
+ class SyncEventListener:
61
+ """Represents a running sync listener thread."""
62
+
63
+ id: str
64
+ channel: str
65
+ thread: threading.Thread
66
+ stop_event: threading.Event
67
+ poll_interval: float
68
+
69
+ def stop(self) -> None:
70
+ """Signal the listener to stop and join the thread."""
71
+ self.stop_event.set()
72
+ self.thread.join()
73
+
74
+
75
+ def resolve_poll_interval(poll_interval: "float | None", default: float) -> float:
76
+ """Resolve poll interval with validation."""
77
+ if poll_interval is None:
78
+ return default
79
+ if poll_interval <= 0:
80
+ msg = "poll_interval must be greater than zero"
81
+ raise ImproperConfigurationError(msg)
82
+ return poll_interval
83
+
84
+
85
+ def _resolve_event_type(payload: "dict[str, Any]", metadata: "dict[str, Any] | None") -> "str | None":
86
+ """Resolve event type from payload or metadata."""
87
+ if metadata and metadata.get("event_type"):
88
+ return str(metadata["event_type"])
89
+ if payload.get("event_type") is not None:
90
+ return str(payload["event_type"])
91
+ if payload.get("type") is not None:
92
+ return str(payload["type"])
93
+ return None
94
+
95
+
96
+ _POSTGRES_ADAPTERS = frozenset({"asyncpg", "psycopg", "psqlpy"})
97
+
98
+
99
+ def _get_default_backend(adapter_name: "str | None") -> str:
100
+ """Return the default events backend for an adapter."""
101
+ if adapter_name in _POSTGRES_ADAPTERS:
102
+ return "listen_notify"
103
+ return "table_queue"
104
+
105
+
106
+ def load_native_backend(config: Any, backend_name: str | None, extension_settings: "dict[str, Any]") -> Any | None:
107
+ """Load adapter-specific native backend if available."""
108
+ if backend_name in {None, "table_queue"}:
109
+ return None
110
+ module_name = type(config).__module__
111
+ parts = module_name.split(".")
112
+ if len(parts) < _ADAPTER_MODULE_PARTS or parts[0] != "sqlspec" or parts[1] != "adapters":
113
+ return None
114
+ adapter_name = parts[2]
115
+ backend_module_name = f"sqlspec.adapters.{adapter_name}.events.backend"
116
+ try:
117
+ backend_module = importlib.import_module(backend_module_name)
118
+ except ModuleNotFoundError:
119
+ log_with_context(
120
+ logger,
121
+ logging.DEBUG,
122
+ "event.listen",
123
+ adapter_name=adapter_name,
124
+ backend_module=backend_module_name,
125
+ status="backend_missing",
126
+ )
127
+ return None
128
+ except ImportError as error:
129
+ log_with_context(
130
+ logger,
131
+ logging.WARNING,
132
+ "event.listen",
133
+ adapter_name=adapter_name,
134
+ backend_module=backend_module_name,
135
+ error_type=type(error).__name__,
136
+ status="backend_import_failed",
137
+ )
138
+ return None
139
+
140
+ try:
141
+ factory = backend_module.create_event_backend
142
+ except AttributeError:
143
+ log_with_context(
144
+ logger,
145
+ logging.DEBUG,
146
+ "event.listen",
147
+ adapter_name=adapter_name,
148
+ backend_module=backend_module_name,
149
+ status="backend_factory_missing",
150
+ )
151
+ return None
152
+ try:
153
+ backend = factory(config, backend_name, extension_settings)
154
+ except MissingDependencyError as error:
155
+ log_with_context(
156
+ logger,
157
+ logging.WARNING,
158
+ "event.listen",
159
+ adapter_name=adapter_name,
160
+ backend_name=backend_name,
161
+ error_type=type(error).__name__,
162
+ status="backend_dependency_missing",
163
+ )
164
+ return None
165
+ except ImproperConfigurationError as error:
166
+ log_with_context(
167
+ logger,
168
+ logging.WARNING,
169
+ "event.listen",
170
+ adapter_name=adapter_name,
171
+ backend_name=backend_name,
172
+ error_type=type(error).__name__,
173
+ status="backend_config_rejected",
174
+ )
175
+ return None
176
+ return backend
177
+
178
+
179
+ def _start_event_span(
180
+ runtime: "ObservabilityRuntime",
181
+ operation: str,
182
+ backend_name: str,
183
+ adapter_name: "str | None",
184
+ channel: "str | None" = None,
185
+ mode: str = "sync",
186
+ ) -> Any:
187
+ """Start an observability span for event operations."""
188
+ if not runtime.span_manager.is_enabled:
189
+ return None
190
+ attributes: dict[str, Any] = {
191
+ "sqlspec.events.operation": operation,
192
+ "sqlspec.events.backend": backend_name,
193
+ "sqlspec.events.mode": mode,
194
+ }
195
+ if adapter_name:
196
+ attributes["sqlspec.events.adapter"] = adapter_name
197
+ if channel:
198
+ attributes["sqlspec.events.channel"] = channel
199
+ return runtime.start_span(f"sqlspec.events.{operation}", attributes=attributes)
200
+
201
+
202
+ def _end_event_span(
203
+ runtime: "ObservabilityRuntime", span: Any, *, error: "Exception | None" = None, result: "str | None" = None
204
+ ) -> None:
205
+ """End an observability span."""
206
+ if span is None:
207
+ return
208
+ if result is not None and has_span_attribute(span):
209
+ span.set_attribute("sqlspec.events.result", result)
210
+ runtime.end_span(span, error=error)
211
+
212
+
213
+ class SyncEventChannel:
214
+ """Event channel for synchronous database configurations."""
215
+
216
+ __slots__ = (
217
+ "_adapter_name",
218
+ "_backend",
219
+ "_backend_name",
220
+ "_config",
221
+ "_listeners",
222
+ "_poll_interval_default",
223
+ "_runtime",
224
+ )
225
+
226
+ _backend: "SyncEventBackendProtocol"
227
+
228
+ def __init__(self, config: "SyncDatabaseConfig[Any, Any, Any]") -> None:
229
+ if config.is_async:
230
+ msg = "SyncEventChannel requires a sync configuration"
231
+ raise ImproperConfigurationError(msg)
232
+ extension_settings: dict[str, Any] = dict(config.extension_config.get("events", {}))
233
+ self._adapter_name = resolve_adapter_name(config)
234
+ hints = get_runtime_hints(self._adapter_name, config)
235
+ self._poll_interval_default = float(extension_settings.get("poll_interval") or hints.poll_interval)
236
+ queue_backend = build_queue_backend(config, extension_settings, adapter_name=self._adapter_name, hints=hints)
237
+ backend_name = extension_settings.get("backend") or _get_default_backend(self._adapter_name)
238
+ native_backend = load_native_backend(config, backend_name, extension_settings)
239
+ if native_backend is None:
240
+ if backend_name not in {None, "table_queue"}:
241
+ log_with_context(
242
+ logger,
243
+ logging.WARNING,
244
+ "event.listen",
245
+ adapter_name=self._adapter_name,
246
+ backend_name=backend_name,
247
+ fallback_backend="table_queue",
248
+ status="backend_unavailable",
249
+ )
250
+ self._backend = cast("SyncEventBackendProtocol", queue_backend)
251
+ backend_label = "table_queue"
252
+ else:
253
+ self._backend = cast("SyncEventBackendProtocol", native_backend)
254
+ if isinstance(native_backend, SyncEventBackendProtocol):
255
+ backend_label = native_backend.backend_name
256
+ else:
257
+ backend_label = backend_name or "table_queue"
258
+ self._config = config
259
+ self._backend_name = backend_label
260
+ self._runtime = config.get_observability_runtime()
261
+ self._listeners: dict[str, SyncEventListener] = {}
262
+
263
+ def publish(self, channel: str, payload: "dict[str, Any]", metadata: "dict[str, Any] | None" = None) -> str:
264
+ """Publish an event to a channel."""
265
+ channel = normalize_event_channel_name(channel)
266
+ if not self._backend.supports_sync:
267
+ msg = "Current events backend does not support sync publishing"
268
+ raise ImproperConfigurationError(msg)
269
+ span = _start_event_span(self._runtime, "publish", self._backend_name, self._adapter_name, channel, mode="sync")
270
+ try:
271
+ event_id = self._backend.publish(channel, payload, metadata)
272
+ except Exception as error:
273
+ _end_event_span(self._runtime, span, error=error)
274
+ raise
275
+ _end_event_span(self._runtime, span, result="published")
276
+ log_with_context(
277
+ logger,
278
+ logging.DEBUG,
279
+ "event.publish",
280
+ adapter_name=self._adapter_name,
281
+ backend_name=self._backend_name,
282
+ channel=channel,
283
+ event_id=event_id,
284
+ event_type=_resolve_event_type(payload, metadata),
285
+ mode="sync",
286
+ )
287
+ return event_id
288
+
289
+ def iter_events(self, channel: str, *, poll_interval: float | None = None) -> Iterator[EventMessage]:
290
+ """Yield events as they become available."""
291
+ channel = normalize_event_channel_name(channel)
292
+ if not self._backend.supports_sync:
293
+ msg = "Current events backend does not support sync consumption"
294
+ raise ImproperConfigurationError(msg)
295
+ interval = resolve_poll_interval(poll_interval, self._poll_interval_default)
296
+ while True:
297
+ span = _start_event_span(
298
+ self._runtime, "dequeue", self._backend_name, self._adapter_name, channel, mode="sync"
299
+ )
300
+ try:
301
+ event = self._backend.dequeue(channel, interval)
302
+ except Exception as error:
303
+ _end_event_span(self._runtime, span, error=error)
304
+ raise
305
+ if event is None:
306
+ _end_event_span(self._runtime, span, result="empty")
307
+ continue
308
+ _end_event_span(self._runtime, span, result="delivered")
309
+ self._runtime.increment_metric("events.deliver")
310
+ log_with_context(
311
+ logger,
312
+ logging.DEBUG,
313
+ "event.receive",
314
+ adapter_name=self._adapter_name,
315
+ backend_name=self._backend_name,
316
+ channel=channel,
317
+ event_id=event.event_id,
318
+ event_type=_resolve_event_type(event.payload, event.metadata),
319
+ mode="sync",
320
+ )
321
+ yield event
322
+
323
+ def listen(
324
+ self, channel: str, handler: "SyncEventHandler", *, poll_interval: float | None = None, auto_ack: bool = True
325
+ ) -> SyncEventListener:
326
+ """Start a background thread that invokes handler for each event."""
327
+ channel = normalize_event_channel_name(channel)
328
+ if not self._backend.supports_sync:
329
+ msg = "Current events backend does not support sync listeners"
330
+ raise ImproperConfigurationError(msg)
331
+ interval = resolve_poll_interval(poll_interval, self._poll_interval_default)
332
+ listener_id = uuid4().hex
333
+ stop_event = threading.Event()
334
+ thread = threading.Thread(
335
+ target=self._run_listener, args=(listener_id, channel, handler, stop_event, interval, auto_ack), daemon=True
336
+ )
337
+ listener = SyncEventListener(listener_id, channel, thread, stop_event, interval)
338
+ self._listeners[listener_id] = listener
339
+ self._runtime.increment_metric("events.listener.start")
340
+ log_with_context(
341
+ logger,
342
+ logging.DEBUG,
343
+ "event.listen",
344
+ adapter_name=self._adapter_name,
345
+ backend_name=self._backend_name,
346
+ channel=channel,
347
+ listener_id=listener_id,
348
+ mode="sync",
349
+ status="start",
350
+ )
351
+ thread.start()
352
+ return listener
353
+
354
+ def stop_listener(self, listener_id: str) -> None:
355
+ """Stop a running listener."""
356
+ listener = self._listeners.pop(listener_id, None)
357
+ if listener is None:
358
+ return
359
+ listener.stop()
360
+ self._runtime.increment_metric("events.listener.stop")
361
+ log_with_context(
362
+ logger,
363
+ logging.DEBUG,
364
+ "event.listen",
365
+ adapter_name=self._adapter_name,
366
+ backend_name=self._backend_name,
367
+ channel=listener.channel,
368
+ listener_id=listener_id,
369
+ mode="sync",
370
+ status="stop",
371
+ )
372
+
373
+ def ack(self, event_id: str) -> None:
374
+ """Acknowledge an event."""
375
+ if not self._backend.supports_sync:
376
+ msg = "Current events backend does not support sync ack"
377
+ raise ImproperConfigurationError(msg)
378
+ span = _start_event_span(self._runtime, "ack", self._backend_name, self._adapter_name, mode="sync")
379
+ try:
380
+ self._backend.ack(event_id)
381
+ except Exception as error:
382
+ _end_event_span(self._runtime, span, error=error)
383
+ raise
384
+ _end_event_span(self._runtime, span, result="acked")
385
+
386
+ def nack(self, event_id: str) -> None:
387
+ """Return an event to the queue for redelivery."""
388
+ span = _start_event_span(self._runtime, "nack", self._backend_name, self._adapter_name, mode="sync")
389
+ try:
390
+ self._backend.nack(event_id)
391
+ except Exception as error:
392
+ _end_event_span(self._runtime, span, error=error)
393
+ raise
394
+ _end_event_span(self._runtime, span, result="nacked")
395
+
396
+ def shutdown(self) -> None:
397
+ """Shutdown the event channel and release backend resources."""
398
+ span = _start_event_span(self._runtime, "shutdown", self._backend_name, self._adapter_name, mode="sync")
399
+ try:
400
+ for listener_id in list(self._listeners):
401
+ self.stop_listener(listener_id)
402
+ self._backend.shutdown()
403
+ except Exception as error:
404
+ _end_event_span(self._runtime, span, error=error)
405
+ raise
406
+ _end_event_span(self._runtime, span, result="shutdown")
407
+ self._runtime.increment_metric("events.shutdown")
408
+
409
+ def _run_listener(
410
+ self,
411
+ listener_id: str,
412
+ channel: str,
413
+ handler: "SyncEventHandler",
414
+ stop_event: threading.Event,
415
+ poll_interval: float,
416
+ auto_ack: bool,
417
+ ) -> None:
418
+ """Internal listener loop."""
419
+ try:
420
+ while not stop_event.is_set():
421
+ span = _start_event_span(
422
+ self._runtime, "dequeue", self._backend_name, self._adapter_name, channel, mode="sync"
423
+ )
424
+ try:
425
+ event = self._backend.dequeue(channel, poll_interval)
426
+ except Exception as error:
427
+ _end_event_span(self._runtime, span, error=error)
428
+ raise
429
+ if event is None:
430
+ _end_event_span(self._runtime, span, result="empty")
431
+ continue
432
+ _end_event_span(self._runtime, span, result="delivered")
433
+ try:
434
+ handler(event)
435
+ if auto_ack:
436
+ self._backend.ack(event.event_id)
437
+ except Exception as error:
438
+ log_with_context(
439
+ logger,
440
+ logging.WARNING,
441
+ "event.listen",
442
+ adapter_name=self._adapter_name,
443
+ backend_name=self._backend_name,
444
+ channel=channel,
445
+ listener_id=listener_id,
446
+ mode="sync",
447
+ error_type=type(error).__name__,
448
+ status="handler_error",
449
+ event_id=event.event_id,
450
+ event_type=_resolve_event_type(event.payload, event.metadata),
451
+ )
452
+ finally:
453
+ self._listeners.pop(listener_id, None)
454
+
455
+
456
+ class AsyncEventChannel:
457
+ """Event channel for asynchronous database configurations."""
458
+
459
+ __slots__ = (
460
+ "_adapter_name",
461
+ "_backend",
462
+ "_backend_name",
463
+ "_config",
464
+ "_listeners",
465
+ "_poll_interval_default",
466
+ "_runtime",
467
+ )
468
+
469
+ _backend: "AsyncEventBackendProtocol"
470
+
471
+ def __init__(self, config: "AsyncDatabaseConfig[Any, Any, Any]") -> None:
472
+ if not config.is_async:
473
+ msg = "AsyncEventChannel requires an async configuration"
474
+ raise ImproperConfigurationError(msg)
475
+ extension_settings: dict[str, Any] = dict(config.extension_config.get("events", {}))
476
+ self._adapter_name = resolve_adapter_name(config)
477
+ hints = get_runtime_hints(self._adapter_name, config)
478
+ self._poll_interval_default = float(extension_settings.get("poll_interval") or hints.poll_interval)
479
+ queue_backend = build_queue_backend(config, extension_settings, adapter_name=self._adapter_name, hints=hints)
480
+ backend_name = extension_settings.get("backend") or _get_default_backend(self._adapter_name)
481
+ native_backend = load_native_backend(config, backend_name, extension_settings)
482
+ if native_backend is None:
483
+ if backend_name not in {None, "table_queue"}:
484
+ log_with_context(
485
+ logger,
486
+ logging.WARNING,
487
+ "event.listen",
488
+ adapter_name=self._adapter_name,
489
+ backend_name=backend_name,
490
+ fallback_backend="table_queue",
491
+ status="backend_unavailable",
492
+ )
493
+ self._backend = cast("AsyncEventBackendProtocol", queue_backend)
494
+ backend_label = "table_queue"
495
+ else:
496
+ self._backend = cast("AsyncEventBackendProtocol", native_backend)
497
+ if isinstance(native_backend, AsyncEventBackendProtocol):
498
+ backend_label = native_backend.backend_name
499
+ else:
500
+ backend_label = backend_name or "table_queue"
501
+ self._config = config
502
+ self._backend_name = backend_label
503
+ self._runtime = config.get_observability_runtime()
504
+ self._listeners: dict[str, AsyncEventListener] = {}
505
+
506
+ async def publish(self, channel: str, payload: "dict[str, Any]", metadata: "dict[str, Any] | None" = None) -> str:
507
+ """Publish an event to a channel."""
508
+ channel = normalize_event_channel_name(channel)
509
+ if not self._backend.supports_async:
510
+ msg = "Current events backend does not support async publishing"
511
+ raise ImproperConfigurationError(msg)
512
+ span = _start_event_span(
513
+ self._runtime, "publish", self._backend_name, self._adapter_name, channel, mode="async"
514
+ )
515
+ try:
516
+ event_id = await self._backend.publish(channel, payload, metadata)
517
+ except Exception as error:
518
+ _end_event_span(self._runtime, span, error=error)
519
+ raise
520
+ _end_event_span(self._runtime, span, result="published")
521
+ log_with_context(
522
+ logger,
523
+ logging.DEBUG,
524
+ "event.publish",
525
+ adapter_name=self._adapter_name,
526
+ backend_name=self._backend_name,
527
+ channel=channel,
528
+ event_id=event_id,
529
+ event_type=_resolve_event_type(payload, metadata),
530
+ mode="async",
531
+ )
532
+ return event_id
533
+
534
+ async def iter_events(self, channel: str, *, poll_interval: float | None = None) -> AsyncIterator[EventMessage]:
535
+ """Yield events as they become available."""
536
+ channel = normalize_event_channel_name(channel)
537
+ if not self._backend.supports_async:
538
+ msg = "Current events backend does not support async consumption"
539
+ raise ImproperConfigurationError(msg)
540
+ interval = resolve_poll_interval(poll_interval, self._poll_interval_default)
541
+ while True:
542
+ span = _start_event_span(
543
+ self._runtime, "dequeue", self._backend_name, self._adapter_name, channel, mode="async"
544
+ )
545
+ try:
546
+ event = await self._backend.dequeue(channel, interval)
547
+ except Exception as error:
548
+ _end_event_span(self._runtime, span, error=error)
549
+ raise
550
+ if event is None:
551
+ _end_event_span(self._runtime, span, result="empty")
552
+ continue
553
+ _end_event_span(self._runtime, span, result="delivered")
554
+ self._runtime.increment_metric("events.deliver")
555
+ log_with_context(
556
+ logger,
557
+ logging.DEBUG,
558
+ "event.receive",
559
+ adapter_name=self._adapter_name,
560
+ backend_name=self._backend_name,
561
+ channel=channel,
562
+ event_id=event.event_id,
563
+ event_type=_resolve_event_type(event.payload, event.metadata),
564
+ mode="async",
565
+ )
566
+ yield event
567
+
568
+ def listen(
569
+ self,
570
+ channel: str,
571
+ handler: "AsyncEventHandler | SyncEventHandler",
572
+ *,
573
+ poll_interval: float | None = None,
574
+ auto_ack: bool = True,
575
+ ) -> AsyncEventListener:
576
+ """Start an async task that delivers events to handler."""
577
+ channel = normalize_event_channel_name(channel)
578
+ if not self._backend.supports_async:
579
+ msg = "Current events backend does not support async listeners"
580
+ raise ImproperConfigurationError(msg)
581
+ loop = asyncio.get_running_loop()
582
+ stop_event = asyncio.Event()
583
+ interval = resolve_poll_interval(poll_interval, self._poll_interval_default)
584
+ listener_id = uuid4().hex
585
+ task = loop.create_task(self._run_listener(listener_id, channel, handler, stop_event, interval, auto_ack))
586
+ listener = AsyncEventListener(listener_id, channel, task, stop_event, interval)
587
+ self._listeners[listener_id] = listener
588
+ self._runtime.increment_metric("events.listener.start")
589
+ log_with_context(
590
+ logger,
591
+ logging.DEBUG,
592
+ "event.listen",
593
+ adapter_name=self._adapter_name,
594
+ backend_name=self._backend_name,
595
+ channel=channel,
596
+ listener_id=listener_id,
597
+ mode="async",
598
+ status="start",
599
+ )
600
+ return listener
601
+
602
+ async def stop_listener(self, listener_id: str) -> None:
603
+ """Stop a running listener."""
604
+ listener = self._listeners.pop(listener_id, None)
605
+ if listener is None:
606
+ return
607
+ await listener.stop()
608
+ self._runtime.increment_metric("events.listener.stop")
609
+ log_with_context(
610
+ logger,
611
+ logging.DEBUG,
612
+ "event.listen",
613
+ adapter_name=self._adapter_name,
614
+ backend_name=self._backend_name,
615
+ channel=listener.channel,
616
+ listener_id=listener_id,
617
+ mode="async",
618
+ status="stop",
619
+ )
620
+
621
+ async def ack(self, event_id: str) -> None:
622
+ """Acknowledge an event."""
623
+ if not self._backend.supports_async:
624
+ msg = "Current events backend does not support async ack"
625
+ raise ImproperConfigurationError(msg)
626
+ span = _start_event_span(self._runtime, "ack", self._backend_name, self._adapter_name, mode="async")
627
+ try:
628
+ await self._backend.ack(event_id)
629
+ except Exception as error:
630
+ _end_event_span(self._runtime, span, error=error)
631
+ raise
632
+ _end_event_span(self._runtime, span, result="acked")
633
+
634
+ async def nack(self, event_id: str) -> None:
635
+ """Return an event to the queue for redelivery."""
636
+ span = _start_event_span(self._runtime, "nack", self._backend_name, self._adapter_name, mode="async")
637
+ try:
638
+ await self._backend.nack(event_id)
639
+ except Exception as error:
640
+ _end_event_span(self._runtime, span, error=error)
641
+ raise
642
+ _end_event_span(self._runtime, span, result="nacked")
643
+
644
+ async def shutdown(self) -> None:
645
+ """Shutdown the event channel and release backend resources."""
646
+ span = _start_event_span(self._runtime, "shutdown", self._backend_name, self._adapter_name, mode="async")
647
+ try:
648
+ for listener_id in list(self._listeners):
649
+ await self.stop_listener(listener_id)
650
+ await self._backend.shutdown()
651
+ except Exception as error:
652
+ _end_event_span(self._runtime, span, error=error)
653
+ raise
654
+ _end_event_span(self._runtime, span, result="shutdown")
655
+ self._runtime.increment_metric("events.shutdown")
656
+
657
+ async def _run_listener(
658
+ self,
659
+ listener_id: str,
660
+ channel: str,
661
+ handler: "AsyncEventHandler | SyncEventHandler",
662
+ stop_event: "asyncio.Event",
663
+ poll_interval: float,
664
+ auto_ack: bool,
665
+ ) -> None:
666
+ """Internal listener loop."""
667
+ try:
668
+ while not stop_event.is_set():
669
+ span = _start_event_span(
670
+ self._runtime, "dequeue", self._backend_name, self._adapter_name, channel, mode="async"
671
+ )
672
+ try:
673
+ event = await self._backend.dequeue(channel, poll_interval)
674
+ except Exception as error:
675
+ _end_event_span(self._runtime, span, error=error)
676
+ raise
677
+ if event is None:
678
+ _end_event_span(self._runtime, span, result="empty")
679
+ continue
680
+ _end_event_span(self._runtime, span, result="delivered")
681
+ try:
682
+ result = handler(event)
683
+ if inspect.isawaitable(result):
684
+ await result
685
+ if auto_ack:
686
+ await self._backend.ack(event.event_id)
687
+ except Exception as error:
688
+ log_with_context(
689
+ logger,
690
+ logging.WARNING,
691
+ "event.listen",
692
+ adapter_name=self._adapter_name,
693
+ backend_name=self._backend_name,
694
+ channel=channel,
695
+ listener_id=listener_id,
696
+ mode="async",
697
+ error_type=type(error).__name__,
698
+ status="handler_error",
699
+ event_id=event.event_id,
700
+ event_type=_resolve_event_type(event.payload, event.metadata),
701
+ )
702
+ finally:
703
+ self._listeners.pop(listener_id, None)