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.
- f68e0789eb443ecb1c2c__mypyc.cp314-win_amd64.pyd +0 -0
- sqlspec/__init__.py +167 -0
- sqlspec/__main__.py +12 -0
- sqlspec/__metadata__.py +14 -0
- sqlspec/_typing.py +714 -0
- sqlspec/adapters/__init__.py +0 -0
- sqlspec/adapters/adbc/__init__.py +13 -0
- sqlspec/adapters/adbc/_typing.py +106 -0
- sqlspec/adapters/adbc/adk/__init__.py +5 -0
- sqlspec/adapters/adbc/adk/store.py +1280 -0
- sqlspec/adapters/adbc/config.py +378 -0
- sqlspec/adapters/adbc/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/adbc/core.py +922 -0
- sqlspec/adapters/adbc/data_dictionary.py +339 -0
- sqlspec/adapters/adbc/driver.py +534 -0
- sqlspec/adapters/adbc/events/__init__.py +5 -0
- sqlspec/adapters/adbc/events/store.py +285 -0
- sqlspec/adapters/adbc/litestar/__init__.py +5 -0
- sqlspec/adapters/adbc/litestar/store.py +534 -0
- sqlspec/adapters/adbc/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/adbc/type_converter.py +142 -0
- sqlspec/adapters/aiomysql/__init__.py +21 -0
- sqlspec/adapters/aiomysql/_typing.py +137 -0
- sqlspec/adapters/aiomysql/adk/__init__.py +5 -0
- sqlspec/adapters/aiomysql/adk/store.py +678 -0
- sqlspec/adapters/aiomysql/config.py +305 -0
- sqlspec/adapters/aiomysql/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/aiomysql/core.py +536 -0
- sqlspec/adapters/aiomysql/data_dictionary.py +121 -0
- sqlspec/adapters/aiomysql/driver.py +386 -0
- sqlspec/adapters/aiomysql/events/__init__.py +5 -0
- sqlspec/adapters/aiomysql/events/store.py +104 -0
- sqlspec/adapters/aiomysql/litestar/__init__.py +5 -0
- sqlspec/adapters/aiomysql/litestar/store.py +314 -0
- sqlspec/adapters/aiosqlite/__init__.py +26 -0
- sqlspec/adapters/aiosqlite/_typing.py +109 -0
- sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/adk/store.py +829 -0
- sqlspec/adapters/aiosqlite/config.py +315 -0
- sqlspec/adapters/aiosqlite/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/aiosqlite/core.py +315 -0
- sqlspec/adapters/aiosqlite/data_dictionary.py +202 -0
- sqlspec/adapters/aiosqlite/driver.py +311 -0
- sqlspec/adapters/aiosqlite/events/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/events/store.py +20 -0
- sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/litestar/store.py +279 -0
- sqlspec/adapters/aiosqlite/pool.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/aiosqlite/pool.py +734 -0
- sqlspec/adapters/asyncmy/__init__.py +21 -0
- sqlspec/adapters/asyncmy/_typing.py +113 -0
- sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
- sqlspec/adapters/asyncmy/adk/store.py +644 -0
- sqlspec/adapters/asyncmy/config.py +307 -0
- sqlspec/adapters/asyncmy/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/asyncmy/core.py +538 -0
- sqlspec/adapters/asyncmy/data_dictionary.py +122 -0
- sqlspec/adapters/asyncmy/driver.py +391 -0
- sqlspec/adapters/asyncmy/events/__init__.py +5 -0
- sqlspec/adapters/asyncmy/events/store.py +104 -0
- sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
- sqlspec/adapters/asyncmy/litestar/store.py +296 -0
- sqlspec/adapters/asyncpg/__init__.py +26 -0
- sqlspec/adapters/asyncpg/_typing.py +103 -0
- sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
- sqlspec/adapters/asyncpg/adk/store.py +483 -0
- sqlspec/adapters/asyncpg/config.py +575 -0
- sqlspec/adapters/asyncpg/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/asyncpg/core.py +480 -0
- sqlspec/adapters/asyncpg/data_dictionary.py +157 -0
- sqlspec/adapters/asyncpg/driver.py +487 -0
- sqlspec/adapters/asyncpg/events/__init__.py +6 -0
- sqlspec/adapters/asyncpg/events/_hub.py +181 -0
- sqlspec/adapters/asyncpg/events/backend.py +210 -0
- sqlspec/adapters/asyncpg/events/store.py +40 -0
- sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
- sqlspec/adapters/asyncpg/litestar/store.py +251 -0
- sqlspec/adapters/bigquery/__init__.py +15 -0
- sqlspec/adapters/bigquery/_typing.py +108 -0
- sqlspec/adapters/bigquery/config.py +362 -0
- sqlspec/adapters/bigquery/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/bigquery/core.py +768 -0
- sqlspec/adapters/bigquery/data_dictionary.py +120 -0
- sqlspec/adapters/bigquery/driver.py +542 -0
- sqlspec/adapters/bigquery/events/__init__.py +5 -0
- sqlspec/adapters/bigquery/events/store.py +139 -0
- sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
- sqlspec/adapters/bigquery/litestar/store.py +325 -0
- sqlspec/adapters/bigquery/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/bigquery/type_converter.py +107 -0
- sqlspec/adapters/cockroach_asyncpg/__init__.py +26 -0
- sqlspec/adapters/cockroach_asyncpg/_typing.py +73 -0
- sqlspec/adapters/cockroach_asyncpg/adk/__init__.py +3 -0
- sqlspec/adapters/cockroach_asyncpg/adk/store.py +465 -0
- sqlspec/adapters/cockroach_asyncpg/config.py +248 -0
- sqlspec/adapters/cockroach_asyncpg/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/cockroach_asyncpg/core.py +55 -0
- sqlspec/adapters/cockroach_asyncpg/data_dictionary.py +110 -0
- sqlspec/adapters/cockroach_asyncpg/driver.py +142 -0
- sqlspec/adapters/cockroach_asyncpg/events/__init__.py +3 -0
- sqlspec/adapters/cockroach_asyncpg/events/store.py +20 -0
- sqlspec/adapters/cockroach_asyncpg/litestar/__init__.py +3 -0
- sqlspec/adapters/cockroach_asyncpg/litestar/store.py +142 -0
- sqlspec/adapters/cockroach_psycopg/__init__.py +39 -0
- sqlspec/adapters/cockroach_psycopg/_typing.py +137 -0
- sqlspec/adapters/cockroach_psycopg/adk/__init__.py +13 -0
- sqlspec/adapters/cockroach_psycopg/adk/store.py +1039 -0
- sqlspec/adapters/cockroach_psycopg/config.py +511 -0
- sqlspec/adapters/cockroach_psycopg/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/cockroach_psycopg/core.py +63 -0
- sqlspec/adapters/cockroach_psycopg/data_dictionary.py +220 -0
- sqlspec/adapters/cockroach_psycopg/driver.py +273 -0
- sqlspec/adapters/cockroach_psycopg/events/__init__.py +6 -0
- sqlspec/adapters/cockroach_psycopg/events/store.py +34 -0
- sqlspec/adapters/cockroach_psycopg/litestar/__init__.py +3 -0
- sqlspec/adapters/cockroach_psycopg/litestar/store.py +327 -0
- sqlspec/adapters/duckdb/__init__.py +29 -0
- sqlspec/adapters/duckdb/_typing.py +104 -0
- sqlspec/adapters/duckdb/adk/__init__.py +14 -0
- sqlspec/adapters/duckdb/adk/store.py +935 -0
- sqlspec/adapters/duckdb/config.py +386 -0
- sqlspec/adapters/duckdb/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/duckdb/core.py +332 -0
- sqlspec/adapters/duckdb/data_dictionary.py +140 -0
- sqlspec/adapters/duckdb/driver.py +426 -0
- sqlspec/adapters/duckdb/events/__init__.py +5 -0
- sqlspec/adapters/duckdb/events/store.py +57 -0
- sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
- sqlspec/adapters/duckdb/litestar/store.py +330 -0
- sqlspec/adapters/duckdb/pool.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/duckdb/pool.py +350 -0
- sqlspec/adapters/duckdb/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/duckdb/type_converter.py +118 -0
- sqlspec/adapters/mysqlconnector/__init__.py +39 -0
- sqlspec/adapters/mysqlconnector/_typing.py +186 -0
- sqlspec/adapters/mysqlconnector/adk/__init__.py +15 -0
- sqlspec/adapters/mysqlconnector/adk/store.py +1183 -0
- sqlspec/adapters/mysqlconnector/config.py +421 -0
- sqlspec/adapters/mysqlconnector/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/mysqlconnector/core.py +472 -0
- sqlspec/adapters/mysqlconnector/data_dictionary.py +230 -0
- sqlspec/adapters/mysqlconnector/driver.py +516 -0
- sqlspec/adapters/mysqlconnector/events/__init__.py +8 -0
- sqlspec/adapters/mysqlconnector/events/store.py +98 -0
- sqlspec/adapters/mysqlconnector/litestar/__init__.py +5 -0
- sqlspec/adapters/mysqlconnector/litestar/store.py +426 -0
- sqlspec/adapters/oracledb/__init__.py +39 -0
- sqlspec/adapters/oracledb/_json_handlers.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/oracledb/_json_handlers.py +196 -0
- sqlspec/adapters/oracledb/_param_types.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/oracledb/_param_types.py +46 -0
- sqlspec/adapters/oracledb/_typing.py +258 -0
- sqlspec/adapters/oracledb/_uuid_handlers.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/oracledb/_uuid_handlers.py +163 -0
- sqlspec/adapters/oracledb/_vector_handlers.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/oracledb/_vector_handlers.py +228 -0
- sqlspec/adapters/oracledb/adk/__init__.py +21 -0
- sqlspec/adapters/oracledb/adk/store.py +2453 -0
- sqlspec/adapters/oracledb/config.py +575 -0
- sqlspec/adapters/oracledb/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/oracledb/core.py +820 -0
- sqlspec/adapters/oracledb/data_dictionary.py +404 -0
- sqlspec/adapters/oracledb/driver.py +1277 -0
- sqlspec/adapters/oracledb/events/__init__.py +16 -0
- sqlspec/adapters/oracledb/events/_hub.py +345 -0
- sqlspec/adapters/oracledb/events/backend.py +300 -0
- sqlspec/adapters/oracledb/events/store.py +420 -0
- sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
- sqlspec/adapters/oracledb/litestar/store.py +781 -0
- sqlspec/adapters/oracledb/migrations.py +539 -0
- sqlspec/adapters/oracledb/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/oracledb/type_converter.py +211 -0
- sqlspec/adapters/psqlpy/__init__.py +18 -0
- sqlspec/adapters/psqlpy/_typing.py +121 -0
- sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
- sqlspec/adapters/psqlpy/adk/store.py +591 -0
- sqlspec/adapters/psqlpy/config.py +376 -0
- sqlspec/adapters/psqlpy/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/psqlpy/core.py +694 -0
- sqlspec/adapters/psqlpy/data_dictionary.py +121 -0
- sqlspec/adapters/psqlpy/driver.py +411 -0
- sqlspec/adapters/psqlpy/events/__init__.py +6 -0
- sqlspec/adapters/psqlpy/events/_hub.py +204 -0
- sqlspec/adapters/psqlpy/events/backend.py +210 -0
- sqlspec/adapters/psqlpy/events/store.py +20 -0
- sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
- sqlspec/adapters/psqlpy/litestar/store.py +270 -0
- sqlspec/adapters/psqlpy/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/psqlpy/type_converter.py +113 -0
- sqlspec/adapters/psycopg/__init__.py +38 -0
- sqlspec/adapters/psycopg/_typing.py +218 -0
- sqlspec/adapters/psycopg/adk/__init__.py +10 -0
- sqlspec/adapters/psycopg/adk/store.py +1106 -0
- sqlspec/adapters/psycopg/config.py +695 -0
- sqlspec/adapters/psycopg/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/psycopg/core.py +520 -0
- sqlspec/adapters/psycopg/data_dictionary.py +278 -0
- sqlspec/adapters/psycopg/driver.py +1033 -0
- sqlspec/adapters/psycopg/events/__init__.py +20 -0
- sqlspec/adapters/psycopg/events/_hub.py +388 -0
- sqlspec/adapters/psycopg/events/backend.py +398 -0
- sqlspec/adapters/psycopg/events/store.py +42 -0
- sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
- sqlspec/adapters/psycopg/litestar/store.py +554 -0
- sqlspec/adapters/psycopg/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/psycopg/type_converter.py +93 -0
- sqlspec/adapters/pymysql/__init__.py +21 -0
- sqlspec/adapters/pymysql/_typing.py +92 -0
- sqlspec/adapters/pymysql/adk/__init__.py +5 -0
- sqlspec/adapters/pymysql/adk/store.py +657 -0
- sqlspec/adapters/pymysql/config.py +176 -0
- sqlspec/adapters/pymysql/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/pymysql/core.py +469 -0
- sqlspec/adapters/pymysql/data_dictionary.py +120 -0
- sqlspec/adapters/pymysql/driver.py +271 -0
- sqlspec/adapters/pymysql/events/__init__.py +5 -0
- sqlspec/adapters/pymysql/events/store.py +50 -0
- sqlspec/adapters/pymysql/litestar/__init__.py +5 -0
- sqlspec/adapters/pymysql/litestar/store.py +232 -0
- sqlspec/adapters/pymysql/pool.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/pymysql/pool.py +184 -0
- sqlspec/adapters/spanner/__init__.py +33 -0
- sqlspec/adapters/spanner/_typing.py +102 -0
- sqlspec/adapters/spanner/adk/__init__.py +5 -0
- sqlspec/adapters/spanner/adk/store.py +758 -0
- sqlspec/adapters/spanner/config.py +355 -0
- sqlspec/adapters/spanner/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/spanner/core.py +263 -0
- sqlspec/adapters/spanner/data_dictionary.py +120 -0
- sqlspec/adapters/spanner/driver.py +407 -0
- sqlspec/adapters/spanner/events/__init__.py +5 -0
- sqlspec/adapters/spanner/events/store.py +187 -0
- sqlspec/adapters/spanner/litestar/__init__.py +5 -0
- sqlspec/adapters/spanner/litestar/store.py +291 -0
- sqlspec/adapters/spanner/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/spanner/type_converter.py +342 -0
- sqlspec/adapters/sqlite/__init__.py +19 -0
- sqlspec/adapters/sqlite/_typing.py +123 -0
- sqlspec/adapters/sqlite/adk/__init__.py +5 -0
- sqlspec/adapters/sqlite/adk/store.py +992 -0
- sqlspec/adapters/sqlite/config.py +240 -0
- sqlspec/adapters/sqlite/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/sqlite/core.py +357 -0
- sqlspec/adapters/sqlite/data_dictionary.py +198 -0
- sqlspec/adapters/sqlite/driver.py +527 -0
- sqlspec/adapters/sqlite/events/__init__.py +5 -0
- sqlspec/adapters/sqlite/events/store.py +20 -0
- sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
- sqlspec/adapters/sqlite/litestar/store.py +316 -0
- sqlspec/adapters/sqlite/pool.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/sqlite/pool.py +237 -0
- sqlspec/adapters/sqlite/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/sqlite/type_converter.py +114 -0
- sqlspec/base.py +832 -0
- sqlspec/builder/__init__.py +181 -0
- sqlspec/builder/_base.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_base.py +1071 -0
- sqlspec/builder/_column.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_column.py +521 -0
- sqlspec/builder/_ddl.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_ddl.py +1691 -0
- sqlspec/builder/_delete.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_delete.py +95 -0
- sqlspec/builder/_dml.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_dml.py +386 -0
- sqlspec/builder/_explain.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_explain.py +579 -0
- sqlspec/builder/_expression_wrappers.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_expression_wrappers.py +46 -0
- sqlspec/builder/_factory.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_factory.py +1884 -0
- sqlspec/builder/_insert.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_insert.py +405 -0
- sqlspec/builder/_join.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_join.py +489 -0
- sqlspec/builder/_merge.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_merge.py +823 -0
- sqlspec/builder/_parsing_utils.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_parsing_utils.py +295 -0
- sqlspec/builder/_select.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_select.py +1666 -0
- sqlspec/builder/_temporal.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_temporal.py +167 -0
- sqlspec/builder/_update.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_update.py +173 -0
- sqlspec/builder/_vector_distance.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_vector_distance.py +330 -0
- sqlspec/cli.py +1095 -0
- sqlspec/config.py +2383 -0
- sqlspec/core/__init__.py +372 -0
- sqlspec/core/_correlation.cp314-win_amd64.pyd +0 -0
- sqlspec/core/_correlation.py +176 -0
- sqlspec/core/_pagination.py +42 -0
- sqlspec/core/_pool.cp314-win_amd64.pyd +0 -0
- sqlspec/core/_pool.py +76 -0
- sqlspec/core/cache.cp314-win_amd64.pyd +0 -0
- sqlspec/core/cache.py +1085 -0
- sqlspec/core/compiler.cp314-win_amd64.pyd +0 -0
- sqlspec/core/compiler.py +1090 -0
- sqlspec/core/config_runtime.cp314-win_amd64.pyd +0 -0
- sqlspec/core/config_runtime.py +174 -0
- sqlspec/core/explain.cp314-win_amd64.pyd +0 -0
- sqlspec/core/explain.py +275 -0
- sqlspec/core/filters.cp314-win_amd64.pyd +0 -0
- sqlspec/core/filters.py +969 -0
- sqlspec/core/hashing.cp314-win_amd64.pyd +0 -0
- sqlspec/core/hashing.py +266 -0
- sqlspec/core/metrics.cp314-win_amd64.pyd +0 -0
- sqlspec/core/metrics.py +83 -0
- sqlspec/core/parameters/__init__.py +72 -0
- sqlspec/core/parameters/_alignment.cp314-win_amd64.pyd +0 -0
- sqlspec/core/parameters/_alignment.py +283 -0
- sqlspec/core/parameters/_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/core/parameters/_converter.py +554 -0
- sqlspec/core/parameters/_processor.cp314-win_amd64.pyd +0 -0
- sqlspec/core/parameters/_processor.py +1182 -0
- sqlspec/core/parameters/_registry.cp314-win_amd64.pyd +0 -0
- sqlspec/core/parameters/_registry.py +206 -0
- sqlspec/core/parameters/_transformers.cp314-win_amd64.pyd +0 -0
- sqlspec/core/parameters/_transformers.py +324 -0
- sqlspec/core/parameters/_types.cp314-win_amd64.pyd +0 -0
- sqlspec/core/parameters/_types.py +536 -0
- sqlspec/core/parameters/_validator.cp314-win_amd64.pyd +0 -0
- sqlspec/core/parameters/_validator.py +171 -0
- sqlspec/core/pipeline.cp314-win_amd64.pyd +0 -0
- sqlspec/core/pipeline.py +333 -0
- sqlspec/core/query_modifiers.cp314-win_amd64.pyd +0 -0
- sqlspec/core/query_modifiers.py +508 -0
- sqlspec/core/result/__init__.py +25 -0
- sqlspec/core/result/_base.cp314-win_amd64.pyd +0 -0
- sqlspec/core/result/_base.py +1232 -0
- sqlspec/core/result/_io.cp314-win_amd64.pyd +0 -0
- sqlspec/core/result/_io.py +28 -0
- sqlspec/core/splitter.cp314-win_amd64.pyd +0 -0
- sqlspec/core/splitter.py +1021 -0
- sqlspec/core/sqlcommenter.cp314-win_amd64.pyd +0 -0
- sqlspec/core/sqlcommenter.py +249 -0
- sqlspec/core/stack.cp314-win_amd64.pyd +0 -0
- sqlspec/core/stack.py +163 -0
- sqlspec/core/statement.cp314-win_amd64.pyd +0 -0
- sqlspec/core/statement.py +1865 -0
- sqlspec/core/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/core/type_converter.py +340 -0
- sqlspec/data_dictionary/__init__.py +22 -0
- sqlspec/data_dictionary/_loader.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/_loader.py +138 -0
- sqlspec/data_dictionary/_registry.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/_registry.py +74 -0
- sqlspec/data_dictionary/_types.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/_types.py +121 -0
- sqlspec/data_dictionary/dialects/__init__.py +21 -0
- sqlspec/data_dictionary/dialects/bigquery.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/bigquery.py +81 -0
- sqlspec/data_dictionary/dialects/cockroachdb.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/cockroachdb.py +54 -0
- sqlspec/data_dictionary/dialects/duckdb.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/duckdb.py +47 -0
- sqlspec/data_dictionary/dialects/mysql.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/mysql.py +53 -0
- sqlspec/data_dictionary/dialects/oracle.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/oracle.py +197 -0
- sqlspec/data_dictionary/dialects/postgres.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/postgres.py +69 -0
- sqlspec/data_dictionary/dialects/spanner.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/spanner.py +37 -0
- sqlspec/data_dictionary/dialects/sqlite.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/sqlite.py +59 -0
- sqlspec/data_dictionary/sql/.gitkeep +0 -0
- sqlspec/data_dictionary/sql/bigquery/columns.sql +23 -0
- sqlspec/data_dictionary/sql/bigquery/foreign_keys.sql +34 -0
- sqlspec/data_dictionary/sql/bigquery/indexes.sql +19 -0
- sqlspec/data_dictionary/sql/bigquery/tables.sql +33 -0
- sqlspec/data_dictionary/sql/bigquery/version.sql +3 -0
- sqlspec/data_dictionary/sql/cockroachdb/columns.sql +34 -0
- sqlspec/data_dictionary/sql/cockroachdb/foreign_keys.sql +40 -0
- sqlspec/data_dictionary/sql/cockroachdb/indexes.sql +32 -0
- sqlspec/data_dictionary/sql/cockroachdb/tables.sql +44 -0
- sqlspec/data_dictionary/sql/cockroachdb/version.sql +3 -0
- sqlspec/data_dictionary/sql/duckdb/columns.sql +23 -0
- sqlspec/data_dictionary/sql/duckdb/foreign_keys.sql +36 -0
- sqlspec/data_dictionary/sql/duckdb/indexes.sql +19 -0
- sqlspec/data_dictionary/sql/duckdb/tables.sql +38 -0
- sqlspec/data_dictionary/sql/duckdb/version.sql +3 -0
- sqlspec/data_dictionary/sql/mysql/columns.sql +23 -0
- sqlspec/data_dictionary/sql/mysql/foreign_keys.sql +28 -0
- sqlspec/data_dictionary/sql/mysql/indexes.sql +26 -0
- sqlspec/data_dictionary/sql/mysql/tables.sql +33 -0
- sqlspec/data_dictionary/sql/mysql/version.sql +3 -0
- sqlspec/data_dictionary/sql/oracle/columns.sql +23 -0
- sqlspec/data_dictionary/sql/oracle/foreign_keys.sql +48 -0
- sqlspec/data_dictionary/sql/oracle/indexes.sql +44 -0
- sqlspec/data_dictionary/sql/oracle/tables.sql +25 -0
- sqlspec/data_dictionary/sql/oracle/version.sql +20 -0
- sqlspec/data_dictionary/sql/postgres/columns.sql +34 -0
- sqlspec/data_dictionary/sql/postgres/foreign_keys.sql +40 -0
- sqlspec/data_dictionary/sql/postgres/indexes.sql +56 -0
- sqlspec/data_dictionary/sql/postgres/tables.sql +44 -0
- sqlspec/data_dictionary/sql/postgres/version.sql +3 -0
- sqlspec/data_dictionary/sql/spanner/columns.sql +23 -0
- sqlspec/data_dictionary/sql/spanner/foreign_keys.sql +70 -0
- sqlspec/data_dictionary/sql/spanner/indexes.sql +30 -0
- sqlspec/data_dictionary/sql/spanner/tables.sql +9 -0
- sqlspec/data_dictionary/sql/spanner/version.sql +3 -0
- sqlspec/data_dictionary/sql/sqlite/columns.sql +23 -0
- sqlspec/data_dictionary/sql/sqlite/foreign_keys.sql +22 -0
- sqlspec/data_dictionary/sql/sqlite/indexes.sql +7 -0
- sqlspec/data_dictionary/sql/sqlite/tables.sql +28 -0
- sqlspec/data_dictionary/sql/sqlite/version.sql +3 -0
- sqlspec/dialects/__init__.py +22 -0
- sqlspec/dialects/_compat.cp314-win_amd64.pyd +0 -0
- sqlspec/dialects/_compat.py +14 -0
- sqlspec/dialects/postgres/__init__.py +9 -0
- sqlspec/dialects/postgres/_generators.cp314-win_amd64.pyd +0 -0
- sqlspec/dialects/postgres/_generators.py +57 -0
- sqlspec/dialects/postgres/_operators.cp314-win_amd64.pyd +0 -0
- sqlspec/dialects/postgres/_operators.py +81 -0
- sqlspec/dialects/postgres/_paradedb.py +50 -0
- sqlspec/dialects/postgres/_pgvector.py +36 -0
- sqlspec/dialects/spanner/__init__.py +6 -0
- sqlspec/dialects/spanner/_generators.cp314-win_amd64.pyd +0 -0
- sqlspec/dialects/spanner/_generators.py +206 -0
- sqlspec/dialects/spanner/_spangres.py +77 -0
- sqlspec/dialects/spanner/_spanner.py +179 -0
- sqlspec/driver/__init__.py +49 -0
- sqlspec/driver/_async.cp314-win_amd64.pyd +0 -0
- sqlspec/driver/_async.py +1830 -0
- sqlspec/driver/_common.cp314-win_amd64.pyd +0 -0
- sqlspec/driver/_common.py +2292 -0
- sqlspec/driver/_exception_handler.cp314-win_amd64.pyd +0 -0
- sqlspec/driver/_exception_handler.py +108 -0
- sqlspec/driver/_query_cache.cp314-win_amd64.pyd +0 -0
- sqlspec/driver/_query_cache.py +96 -0
- sqlspec/driver/_sql_helpers.cp314-win_amd64.pyd +0 -0
- sqlspec/driver/_sql_helpers.py +139 -0
- sqlspec/driver/_storage_helpers.cp314-win_amd64.pyd +0 -0
- sqlspec/driver/_storage_helpers.py +153 -0
- sqlspec/driver/_sync.cp314-win_amd64.pyd +0 -0
- sqlspec/driver/_sync.py +1817 -0
- sqlspec/exceptions.cp314-win_amd64.pyd +0 -0
- sqlspec/exceptions.py +480 -0
- sqlspec/extensions/__init__.py +0 -0
- sqlspec/extensions/adk/__init__.py +84 -0
- sqlspec/extensions/adk/_config_utils.py +199 -0
- sqlspec/extensions/adk/_types.cp314-win_amd64.pyd +0 -0
- sqlspec/extensions/adk/_types.py +41 -0
- sqlspec/extensions/adk/artifact/__init__.py +57 -0
- sqlspec/extensions/adk/artifact/_types.cp314-win_amd64.pyd +0 -0
- sqlspec/extensions/adk/artifact/_types.py +32 -0
- sqlspec/extensions/adk/artifact/service.py +508 -0
- sqlspec/extensions/adk/artifact/store.py +361 -0
- sqlspec/extensions/adk/converters.py +212 -0
- sqlspec/extensions/adk/memory/__init__.py +69 -0
- sqlspec/extensions/adk/memory/_types.cp314-win_amd64.pyd +0 -0
- sqlspec/extensions/adk/memory/_types.py +30 -0
- sqlspec/extensions/adk/memory/converters.py +225 -0
- sqlspec/extensions/adk/memory/service.py +316 -0
- sqlspec/extensions/adk/memory/store.py +525 -0
- sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +184 -0
- sqlspec/extensions/adk/migrations/__init__.py +0 -0
- sqlspec/extensions/adk/service.py +279 -0
- sqlspec/extensions/adk/store.py +590 -0
- sqlspec/extensions/events/__init__.py +51 -0
- sqlspec/extensions/events/_channel.py +703 -0
- sqlspec/extensions/events/_hints.cp314-win_amd64.pyd +0 -0
- sqlspec/extensions/events/_hints.py +45 -0
- sqlspec/extensions/events/_models.py +23 -0
- sqlspec/extensions/events/_payload.cp314-win_amd64.pyd +0 -0
- sqlspec/extensions/events/_payload.py +69 -0
- sqlspec/extensions/events/_protocols.py +134 -0
- sqlspec/extensions/events/_queue.py +462 -0
- sqlspec/extensions/events/_store.py +209 -0
- sqlspec/extensions/events/migrations/0001_create_event_queue.py +59 -0
- sqlspec/extensions/events/migrations/__init__.py +3 -0
- sqlspec/extensions/fastapi/__init__.py +22 -0
- sqlspec/extensions/fastapi/extension.py +391 -0
- sqlspec/extensions/fastapi/providers.cp314-win_amd64.pyd +0 -0
- sqlspec/extensions/fastapi/providers.py +712 -0
- sqlspec/extensions/flask/__init__.py +38 -0
- sqlspec/extensions/flask/_state.py +87 -0
- sqlspec/extensions/flask/_utils.py +71 -0
- sqlspec/extensions/flask/extension.py +539 -0
- sqlspec/extensions/litestar/__init__.py +31 -0
- sqlspec/extensions/litestar/_utils.py +52 -0
- sqlspec/extensions/litestar/channels.py +165 -0
- sqlspec/extensions/litestar/cli.py +102 -0
- sqlspec/extensions/litestar/config.py +90 -0
- sqlspec/extensions/litestar/handlers.py +316 -0
- sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
- sqlspec/extensions/litestar/migrations/__init__.py +3 -0
- sqlspec/extensions/litestar/plugin.py +1066 -0
- sqlspec/extensions/litestar/providers.cp314-win_amd64.pyd +0 -0
- sqlspec/extensions/litestar/providers.py +784 -0
- sqlspec/extensions/litestar/store.py +298 -0
- sqlspec/extensions/otel/__init__.py +58 -0
- sqlspec/extensions/prometheus/__init__.py +113 -0
- sqlspec/extensions/sanic/__init__.py +19 -0
- sqlspec/extensions/sanic/_state.py +43 -0
- sqlspec/extensions/sanic/_utils.py +127 -0
- sqlspec/extensions/sanic/extension.py +647 -0
- sqlspec/extensions/starlette/__init__.py +22 -0
- sqlspec/extensions/starlette/_state.py +42 -0
- sqlspec/extensions/starlette/_utils.py +96 -0
- sqlspec/extensions/starlette/extension.py +374 -0
- sqlspec/extensions/starlette/middleware.py +281 -0
- sqlspec/loader.cp314-win_amd64.pyd +0 -0
- sqlspec/loader.py +727 -0
- sqlspec/migrations/__init__.py +39 -0
- sqlspec/migrations/base.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/base.py +862 -0
- sqlspec/migrations/commands.py +2151 -0
- sqlspec/migrations/context.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/context.py +157 -0
- sqlspec/migrations/fix.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/fix.py +204 -0
- sqlspec/migrations/loaders.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/loaders.py +443 -0
- sqlspec/migrations/runner.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/runner.py +1195 -0
- sqlspec/migrations/squash.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/squash.py +490 -0
- sqlspec/migrations/templates.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/templates.py +234 -0
- sqlspec/migrations/tracker.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/tracker.py +792 -0
- sqlspec/migrations/utils.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/utils.py +256 -0
- sqlspec/migrations/validation.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/validation.py +359 -0
- sqlspec/migrations/version.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/version.py +446 -0
- sqlspec/observability/__init__.py +57 -0
- sqlspec/observability/_common.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_common.py +77 -0
- sqlspec/observability/_config.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_config.py +364 -0
- sqlspec/observability/_diagnostics.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_diagnostics.py +74 -0
- sqlspec/observability/_dispatcher.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_dispatcher.py +200 -0
- sqlspec/observability/_formatters/__init__.py +13 -0
- sqlspec/observability/_formatters/_aws.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_formatters/_aws.py +102 -0
- sqlspec/observability/_formatters/_azure.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_formatters/_azure.py +96 -0
- sqlspec/observability/_formatters/_base.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_formatters/_base.py +57 -0
- sqlspec/observability/_formatters/_gcp.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_formatters/_gcp.py +131 -0
- sqlspec/observability/_formatting.py +58 -0
- sqlspec/observability/_observer.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_observer.py +361 -0
- sqlspec/observability/_runtime.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_runtime.py +461 -0
- sqlspec/observability/_sampling.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_sampling.py +188 -0
- sqlspec/observability/_spans.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_spans.py +161 -0
- sqlspec/protocols.py +955 -0
- sqlspec/py.typed +0 -0
- sqlspec/service.py +433 -0
- sqlspec/storage/__init__.py +48 -0
- sqlspec/storage/_arrow_payload.py +68 -0
- sqlspec/storage/_paths.cp314-win_amd64.pyd +0 -0
- sqlspec/storage/_paths.py +58 -0
- sqlspec/storage/_utils.py +46 -0
- sqlspec/storage/backends/__init__.py +1 -0
- sqlspec/storage/backends/base.cp314-win_amd64.pyd +0 -0
- sqlspec/storage/backends/base.py +374 -0
- sqlspec/storage/backends/fsspec.py +574 -0
- sqlspec/storage/backends/local.py +468 -0
- sqlspec/storage/backends/obstore.py +956 -0
- sqlspec/storage/errors.cp314-win_amd64.pyd +0 -0
- sqlspec/storage/errors.py +102 -0
- sqlspec/storage/pipeline.cp314-win_amd64.pyd +0 -0
- sqlspec/storage/pipeline.py +628 -0
- sqlspec/storage/registry.cp314-win_amd64.pyd +0 -0
- sqlspec/storage/registry.py +329 -0
- sqlspec/typing.py +405 -0
- sqlspec/utils/__init__.py +7 -0
- sqlspec/utils/arrow_helpers.py +384 -0
- sqlspec/utils/config_tools.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/config_tools.py +314 -0
- sqlspec/utils/correlation.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/correlation.py +134 -0
- sqlspec/utils/deprecation.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/deprecation.py +157 -0
- sqlspec/utils/dispatch.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/dispatch.py +101 -0
- sqlspec/utils/fixtures.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/fixtures.py +260 -0
- sqlspec/utils/logging.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/logging.py +251 -0
- sqlspec/utils/module_loader.py +306 -0
- sqlspec/utils/portal.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/portal.py +377 -0
- sqlspec/utils/schema.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/schema.py +1040 -0
- sqlspec/utils/serializers/__init__.py +30 -0
- sqlspec/utils/serializers/_json.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/serializers/_json.py +415 -0
- sqlspec/utils/serializers/_numpy.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/serializers/_numpy.py +65 -0
- sqlspec/utils/serializers/_schema.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/serializers/_schema.py +285 -0
- sqlspec/utils/singleton.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/singleton.py +41 -0
- sqlspec/utils/sync_tools.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/sync_tools.py +316 -0
- sqlspec/utils/text.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/text.py +109 -0
- sqlspec/utils/type_converters.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/type_converters.py +216 -0
- sqlspec/utils/type_guards.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/type_guards.py +1508 -0
- sqlspec/utils/uuids.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/uuids.py +241 -0
- sqlspec-0.47.0.dist-info/METADATA +202 -0
- sqlspec-0.47.0.dist-info/RECORD +621 -0
- sqlspec-0.47.0.dist-info/WHEEL +4 -0
- sqlspec-0.47.0.dist-info/entry_points.txt +6 -0
- sqlspec-0.47.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,1066 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from collections.abc import Iterable
|
|
3
|
+
from contextlib import suppress
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Literal, NoReturn, cast, overload
|
|
6
|
+
|
|
7
|
+
from litestar.di import Provide
|
|
8
|
+
from litestar.exceptions import NotFoundException
|
|
9
|
+
from litestar.middleware import DefineMiddleware
|
|
10
|
+
from litestar.plugins import CLIPlugin, InitPluginProtocol, OpenAPISchemaPlugin
|
|
11
|
+
|
|
12
|
+
from sqlspec.base import SQLSpec
|
|
13
|
+
from sqlspec.config import (
|
|
14
|
+
AsyncConfigT,
|
|
15
|
+
AsyncDatabaseConfig,
|
|
16
|
+
DatabaseConfigProtocol,
|
|
17
|
+
DriverT,
|
|
18
|
+
NoPoolAsyncConfig,
|
|
19
|
+
NoPoolSyncConfig,
|
|
20
|
+
SyncConfigT,
|
|
21
|
+
SyncDatabaseConfig,
|
|
22
|
+
)
|
|
23
|
+
from sqlspec.core._pagination import OffsetPagination
|
|
24
|
+
from sqlspec.core.sqlcommenter import SQLCommenterContext
|
|
25
|
+
from sqlspec.exceptions import ImproperConfigurationError, NotFoundError
|
|
26
|
+
from sqlspec.extensions.litestar._utils import (
|
|
27
|
+
delete_sqlspec_scope_state,
|
|
28
|
+
get_sqlspec_scope_state,
|
|
29
|
+
set_sqlspec_scope_state,
|
|
30
|
+
)
|
|
31
|
+
from sqlspec.extensions.litestar.handlers import (
|
|
32
|
+
autocommit_handler_maker,
|
|
33
|
+
connection_provider_maker,
|
|
34
|
+
lifespan_handler_maker,
|
|
35
|
+
manual_handler_maker,
|
|
36
|
+
pool_provider_maker,
|
|
37
|
+
session_provider_maker,
|
|
38
|
+
)
|
|
39
|
+
from sqlspec.typing import NUMPY_INSTALLED, ConnectionT, PoolT, SchemaT
|
|
40
|
+
from sqlspec.utils.correlation import CorrelationContext
|
|
41
|
+
from sqlspec.utils.logging import get_logger, log_with_context
|
|
42
|
+
from sqlspec.utils.serializers import DEFAULT_TYPE_ENCODERS, numpy_array_dec_hook
|
|
43
|
+
|
|
44
|
+
if TYPE_CHECKING:
|
|
45
|
+
from collections.abc import AsyncGenerator, Callable
|
|
46
|
+
from contextlib import AbstractAsyncContextManager
|
|
47
|
+
|
|
48
|
+
from litestar import Litestar, Request
|
|
49
|
+
from litestar._openapi.schema_generation.schema import SchemaCreator
|
|
50
|
+
from litestar.config.app import AppConfig
|
|
51
|
+
from litestar.datastructures.state import State
|
|
52
|
+
from litestar.openapi.spec import Schema
|
|
53
|
+
from litestar.types import ASGIApp, BeforeMessageSendHookHandler, Receive, Scope, Send
|
|
54
|
+
from litestar.typing import FieldDefinition
|
|
55
|
+
from rich_click import Group
|
|
56
|
+
|
|
57
|
+
from sqlspec.driver import AsyncDriverAdapterBase, SyncDriverAdapterBase
|
|
58
|
+
from sqlspec.loader import SQLFileLoader
|
|
59
|
+
|
|
60
|
+
logger = get_logger("sqlspec.extensions.litestar")
|
|
61
|
+
|
|
62
|
+
CommitMode = Literal["manual", "autocommit", "autocommit_include_redirect"]
|
|
63
|
+
DEFAULT_COMMIT_MODE: CommitMode = "manual"
|
|
64
|
+
DEFAULT_CONNECTION_KEY = "db_connection"
|
|
65
|
+
DEFAULT_POOL_KEY = "db_pool"
|
|
66
|
+
DEFAULT_SESSION_KEY = "db_session"
|
|
67
|
+
DEFAULT_CORRELATION_HEADER = "x-request-id"
|
|
68
|
+
TRACE_CONTEXT_FALLBACK_HEADERS: tuple[str, ...] = (
|
|
69
|
+
DEFAULT_CORRELATION_HEADER,
|
|
70
|
+
"x-correlation-id",
|
|
71
|
+
"traceparent",
|
|
72
|
+
"x-cloud-trace-context",
|
|
73
|
+
"grpc-trace-bin",
|
|
74
|
+
"x-amzn-trace-id",
|
|
75
|
+
"x-b3-traceid",
|
|
76
|
+
"x-client-trace-id",
|
|
77
|
+
)
|
|
78
|
+
CORRELATION_STATE_KEY = "sqlspec_correlation_id"
|
|
79
|
+
_LITESTAR_NUMPY_ARRAY_TYPE: type[Any] | None = None
|
|
80
|
+
|
|
81
|
+
__all__ = (
|
|
82
|
+
"CORRELATION_STATE_KEY",
|
|
83
|
+
"DEFAULT_COMMIT_MODE",
|
|
84
|
+
"DEFAULT_CONNECTION_KEY",
|
|
85
|
+
"DEFAULT_CORRELATION_HEADER",
|
|
86
|
+
"DEFAULT_POOL_KEY",
|
|
87
|
+
"DEFAULT_SESSION_KEY",
|
|
88
|
+
"TRACE_CONTEXT_FALLBACK_HEADERS",
|
|
89
|
+
"CommitMode",
|
|
90
|
+
"CorrelationMiddleware",
|
|
91
|
+
"PluginConfigState",
|
|
92
|
+
"SQLSpecPlugin",
|
|
93
|
+
"_OffsetPaginationSchemaPlugin",
|
|
94
|
+
"not_found_error_handler",
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def not_found_error_handler(_request: "Request[Any, Any, Any]", exc: NotFoundError) -> NoReturn:
|
|
99
|
+
"""Translate :class:`sqlspec.exceptions.NotFoundError` into Litestar's HTTP 404.
|
|
100
|
+
|
|
101
|
+
Re-raised as :class:`litestar.exceptions.NotFoundException` so the standard
|
|
102
|
+
Litestar exception-handler chain renders it (including any RFC 7807 handler
|
|
103
|
+
the user has registered) and the OpenAPI 404 schema stays consistent.
|
|
104
|
+
"""
|
|
105
|
+
detail = str(exc) or "Not Found"
|
|
106
|
+
raise NotFoundException(detail=detail) from exc
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class CorrelationMiddleware:
|
|
110
|
+
__slots__ = ("_app", "_headers")
|
|
111
|
+
|
|
112
|
+
def __init__(self, app: "ASGIApp", *, headers: tuple[str, ...]) -> None:
|
|
113
|
+
self._app = app
|
|
114
|
+
self._headers = headers
|
|
115
|
+
|
|
116
|
+
async def __call__(self, scope: "Scope", receive: "Receive", send: "Send") -> None:
|
|
117
|
+
scope_type = scope.get("type")
|
|
118
|
+
if str(scope_type) != "http" or not self._headers:
|
|
119
|
+
await self._app(scope, receive, send)
|
|
120
|
+
return
|
|
121
|
+
|
|
122
|
+
header_value: str | None = None
|
|
123
|
+
raw_headers = scope.get("headers") or []
|
|
124
|
+
for header in self._headers:
|
|
125
|
+
for name, value in raw_headers:
|
|
126
|
+
if name.decode().lower() == header:
|
|
127
|
+
header_value = value.decode()
|
|
128
|
+
break
|
|
129
|
+
if header_value:
|
|
130
|
+
break
|
|
131
|
+
if not header_value:
|
|
132
|
+
header_value = CorrelationContext.generate()
|
|
133
|
+
|
|
134
|
+
previous_correlation_id = CorrelationContext.get()
|
|
135
|
+
CorrelationContext.set(header_value)
|
|
136
|
+
set_sqlspec_scope_state(scope, CORRELATION_STATE_KEY, header_value)
|
|
137
|
+
try:
|
|
138
|
+
await self._app(scope, receive, send)
|
|
139
|
+
finally:
|
|
140
|
+
with suppress(KeyError):
|
|
141
|
+
delete_sqlspec_scope_state(scope, CORRELATION_STATE_KEY)
|
|
142
|
+
CorrelationContext.set(previous_correlation_id)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@dataclass
|
|
146
|
+
class PluginConfigState:
|
|
147
|
+
"""Internal state for each database configuration."""
|
|
148
|
+
|
|
149
|
+
config: "DatabaseConfigProtocol[Any, Any, Any]"
|
|
150
|
+
connection_key: str
|
|
151
|
+
pool_key: str
|
|
152
|
+
session_key: str
|
|
153
|
+
commit_mode: CommitMode
|
|
154
|
+
extra_commit_statuses: "set[int] | None"
|
|
155
|
+
extra_rollback_statuses: "set[int] | None"
|
|
156
|
+
enable_correlation_middleware: bool
|
|
157
|
+
correlation_header: str
|
|
158
|
+
enable_sqlcommenter_middleware: bool
|
|
159
|
+
correlation_headers: tuple[str, ...] = field(init=False)
|
|
160
|
+
disable_di: bool
|
|
161
|
+
connection_provider: "Callable[[State, Scope], AsyncGenerator[Any, None]]" = field(init=False)
|
|
162
|
+
pool_provider: "Callable[[State, Scope], Any]" = field(init=False)
|
|
163
|
+
session_provider: "Callable[..., AsyncGenerator[Any, None]]" = field(init=False)
|
|
164
|
+
before_send_handler: "BeforeMessageSendHookHandler" = field(init=False)
|
|
165
|
+
lifespan_handler: "Callable[[Litestar], AbstractAsyncContextManager[None]]" = field(init=False)
|
|
166
|
+
annotation: "type[DatabaseConfigProtocol[Any, Any, Any]]" = field(init=False)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class SQLSpecPlugin(InitPluginProtocol, CLIPlugin):
|
|
170
|
+
"""Litestar plugin for SQLSpec database integration.
|
|
171
|
+
|
|
172
|
+
Automatically configures NumPy array serialization when NumPy is installed,
|
|
173
|
+
enabling seamless bidirectional conversion between NumPy arrays and JSON
|
|
174
|
+
for vector embedding workflows.
|
|
175
|
+
|
|
176
|
+
Session Table Migrations:
|
|
177
|
+
The Litestar extension includes migrations for creating session storage tables.
|
|
178
|
+
To include these migrations in your database migration workflow, add 'litestar'
|
|
179
|
+
to the include_extensions list in your migration configuration.
|
|
180
|
+
|
|
181
|
+
Example:
|
|
182
|
+
config = AsyncpgConfig(
|
|
183
|
+
connection_config={"dsn": "postgresql://localhost/db"},
|
|
184
|
+
extension_config={
|
|
185
|
+
"litestar": {
|
|
186
|
+
"session_table": "custom_sessions" # Optional custom table name
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
migration_config={
|
|
190
|
+
"script_location": "migrations",
|
|
191
|
+
"include_extensions": ["litestar"], # Simple string list only
|
|
192
|
+
}
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
The session table migration will automatically use the appropriate column types
|
|
196
|
+
for your database dialect (JSONB for PostgreSQL, JSON for MySQL, TEXT for SQLite).
|
|
197
|
+
|
|
198
|
+
Extension migrations use the ext_litestar_ prefix (e.g., ext_litestar_0001) to
|
|
199
|
+
prevent version conflicts with application migrations.
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
__slots__ = ("_correlation_headers", "_enable_sqlcommenter_middleware", "_plugin_configs", "_sqlspec")
|
|
203
|
+
|
|
204
|
+
def __init__(self, sqlspec: SQLSpec, *, loader: "SQLFileLoader | None" = None) -> None:
|
|
205
|
+
"""Initialize SQLSpec plugin.
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
sqlspec: Pre-configured SQLSpec instance with registered database configs.
|
|
209
|
+
loader: Optional SQL file loader instance (SQLSpec may already have one).
|
|
210
|
+
"""
|
|
211
|
+
self._sqlspec = sqlspec
|
|
212
|
+
|
|
213
|
+
self._plugin_configs: list[PluginConfigState] = []
|
|
214
|
+
for cfg in self._sqlspec.configs.values():
|
|
215
|
+
config_union = cast(
|
|
216
|
+
"SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]",
|
|
217
|
+
cfg,
|
|
218
|
+
)
|
|
219
|
+
settings = self._extract_litestar_settings(config_union)
|
|
220
|
+
state = self._create_config_state(config_union, settings)
|
|
221
|
+
self._plugin_configs.append(state)
|
|
222
|
+
|
|
223
|
+
correlation_headers: list[str] = []
|
|
224
|
+
enable_sqlcommenter = False
|
|
225
|
+
for state in self._plugin_configs:
|
|
226
|
+
if state.enable_sqlcommenter_middleware and state.config.statement_config.enable_sqlcommenter:
|
|
227
|
+
enable_sqlcommenter = True
|
|
228
|
+
if not state.enable_correlation_middleware:
|
|
229
|
+
continue
|
|
230
|
+
for header in state.correlation_headers:
|
|
231
|
+
if header not in correlation_headers:
|
|
232
|
+
correlation_headers.append(header)
|
|
233
|
+
self._correlation_headers = tuple(correlation_headers)
|
|
234
|
+
self._enable_sqlcommenter_middleware = enable_sqlcommenter
|
|
235
|
+
log_with_context(
|
|
236
|
+
logger,
|
|
237
|
+
logging.DEBUG,
|
|
238
|
+
"extension.init",
|
|
239
|
+
framework="litestar",
|
|
240
|
+
stage="init",
|
|
241
|
+
config_count=len(self._plugin_configs),
|
|
242
|
+
correlation_headers=len(self._correlation_headers),
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
def _extract_litestar_settings(
|
|
246
|
+
self,
|
|
247
|
+
config: "SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]",
|
|
248
|
+
) -> "dict[str, Any]":
|
|
249
|
+
"""Extract Litestar settings from config.extension_config."""
|
|
250
|
+
litestar_config = config.extension_config.get("litestar", {})
|
|
251
|
+
|
|
252
|
+
connection_key = litestar_config.get("connection_key", DEFAULT_CONNECTION_KEY)
|
|
253
|
+
pool_key = litestar_config.get("pool_key", DEFAULT_POOL_KEY)
|
|
254
|
+
session_key = litestar_config.get("session_key", DEFAULT_SESSION_KEY)
|
|
255
|
+
commit_mode = litestar_config.get("commit_mode", DEFAULT_COMMIT_MODE)
|
|
256
|
+
|
|
257
|
+
if not config.supports_connection_pooling and pool_key == DEFAULT_POOL_KEY:
|
|
258
|
+
pool_key = f"_{DEFAULT_POOL_KEY}_{id(config)}"
|
|
259
|
+
|
|
260
|
+
correlation_header = str(litestar_config.get("correlation_header", DEFAULT_CORRELATION_HEADER)).lower()
|
|
261
|
+
configured_headers = _normalize_header_list(litestar_config.get("correlation_headers"))
|
|
262
|
+
auto_trace_headers = bool(litestar_config.get("auto_trace_headers", True))
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
"connection_key": connection_key,
|
|
266
|
+
"pool_key": pool_key,
|
|
267
|
+
"session_key": session_key,
|
|
268
|
+
"commit_mode": commit_mode,
|
|
269
|
+
"extra_commit_statuses": litestar_config.get("extra_commit_statuses"),
|
|
270
|
+
"extra_rollback_statuses": litestar_config.get("extra_rollback_statuses"),
|
|
271
|
+
"enable_correlation_middleware": litestar_config.get("enable_correlation_middleware", True),
|
|
272
|
+
"correlation_header": correlation_header,
|
|
273
|
+
"correlation_headers": _build_correlation_headers(
|
|
274
|
+
primary=correlation_header, configured=configured_headers, auto_trace_headers=auto_trace_headers
|
|
275
|
+
),
|
|
276
|
+
"disable_di": litestar_config.get("disable_di", False),
|
|
277
|
+
"enable_sqlcommenter_middleware": litestar_config.get("enable_sqlcommenter_middleware", True),
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
def _create_config_state(
|
|
281
|
+
self,
|
|
282
|
+
config: "SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]",
|
|
283
|
+
settings: "dict[str, Any]",
|
|
284
|
+
) -> PluginConfigState:
|
|
285
|
+
"""Create plugin state with handlers for the given configuration."""
|
|
286
|
+
state = PluginConfigState(
|
|
287
|
+
config=config,
|
|
288
|
+
connection_key=settings["connection_key"],
|
|
289
|
+
pool_key=settings["pool_key"],
|
|
290
|
+
session_key=settings["session_key"],
|
|
291
|
+
commit_mode=settings["commit_mode"],
|
|
292
|
+
extra_commit_statuses=settings.get("extra_commit_statuses"),
|
|
293
|
+
extra_rollback_statuses=settings.get("extra_rollback_statuses"),
|
|
294
|
+
enable_correlation_middleware=settings["enable_correlation_middleware"],
|
|
295
|
+
correlation_header=settings["correlation_header"],
|
|
296
|
+
enable_sqlcommenter_middleware=settings["enable_sqlcommenter_middleware"],
|
|
297
|
+
disable_di=settings["disable_di"],
|
|
298
|
+
)
|
|
299
|
+
state.correlation_headers = tuple(settings["correlation_headers"])
|
|
300
|
+
|
|
301
|
+
if not state.disable_di:
|
|
302
|
+
self._setup_handlers(state)
|
|
303
|
+
return state
|
|
304
|
+
|
|
305
|
+
def _setup_handlers(self, state: PluginConfigState) -> None:
|
|
306
|
+
"""Setup handlers for the plugin state."""
|
|
307
|
+
connection_key = state.connection_key
|
|
308
|
+
pool_key = state.pool_key
|
|
309
|
+
commit_mode = state.commit_mode
|
|
310
|
+
config = state.config
|
|
311
|
+
is_async = config.is_async
|
|
312
|
+
|
|
313
|
+
state.connection_provider = connection_provider_maker(config, pool_key, connection_key)
|
|
314
|
+
state.pool_provider = pool_provider_maker(config, pool_key)
|
|
315
|
+
state.session_provider = session_provider_maker(config, connection_key)
|
|
316
|
+
state.lifespan_handler = lifespan_handler_maker(config, pool_key)
|
|
317
|
+
|
|
318
|
+
if commit_mode == "manual":
|
|
319
|
+
state.before_send_handler = manual_handler_maker(connection_key, is_async)
|
|
320
|
+
else:
|
|
321
|
+
commit_on_redirect = commit_mode == "autocommit_include_redirect"
|
|
322
|
+
state.before_send_handler = autocommit_handler_maker(
|
|
323
|
+
connection_key, is_async, commit_on_redirect, state.extra_commit_statuses, state.extra_rollback_statuses
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
@property
|
|
327
|
+
def config(
|
|
328
|
+
self,
|
|
329
|
+
) -> "list[SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]]":
|
|
330
|
+
"""Return the plugin configurations.
|
|
331
|
+
|
|
332
|
+
Returns:
|
|
333
|
+
List of database configurations.
|
|
334
|
+
"""
|
|
335
|
+
return [
|
|
336
|
+
cast(
|
|
337
|
+
"SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]",
|
|
338
|
+
state.config,
|
|
339
|
+
)
|
|
340
|
+
for state in self._plugin_configs
|
|
341
|
+
]
|
|
342
|
+
|
|
343
|
+
def on_cli_init(self, cli: "Group") -> None:
|
|
344
|
+
"""Configure CLI commands for SQLSpec database operations.
|
|
345
|
+
|
|
346
|
+
Args:
|
|
347
|
+
cli: The Click command group to add commands to.
|
|
348
|
+
"""
|
|
349
|
+
from sqlspec.extensions.litestar.cli import database_group
|
|
350
|
+
|
|
351
|
+
cli.add_command(database_group)
|
|
352
|
+
|
|
353
|
+
def on_app_init(self, app_config: "AppConfig") -> "AppConfig":
|
|
354
|
+
"""Configure Litestar application with SQLSpec database integration.
|
|
355
|
+
|
|
356
|
+
Automatically registers NumPy array serialization when NumPy is installed.
|
|
357
|
+
|
|
358
|
+
Args:
|
|
359
|
+
app_config: The Litestar application configuration instance.
|
|
360
|
+
|
|
361
|
+
Returns:
|
|
362
|
+
The updated application configuration instance.
|
|
363
|
+
"""
|
|
364
|
+
self._validate_dependency_keys()
|
|
365
|
+
|
|
366
|
+
def store_sqlspec_in_state() -> None:
|
|
367
|
+
app_config.state.sqlspec = self
|
|
368
|
+
|
|
369
|
+
app_config.on_startup.append(store_sqlspec_in_state)
|
|
370
|
+
app_config.signature_types.extend([SQLSpec, DatabaseConfigProtocol, SyncConfigT, AsyncConfigT])
|
|
371
|
+
|
|
372
|
+
signature_namespace = {"ConnectionT": ConnectionT, "PoolT": PoolT, "DriverT": DriverT, "SchemaT": SchemaT}
|
|
373
|
+
|
|
374
|
+
for state in self._plugin_configs:
|
|
375
|
+
state.annotation = type(state.config)
|
|
376
|
+
app_config.signature_types.append(state.annotation)
|
|
377
|
+
app_config.signature_types.append(state.config.connection_type)
|
|
378
|
+
app_config.signature_types.append(state.config.driver_type)
|
|
379
|
+
|
|
380
|
+
signature_namespace.update(state.config.get_signature_namespace())
|
|
381
|
+
|
|
382
|
+
if not state.disable_di:
|
|
383
|
+
app_config.before_send.append(state.before_send_handler)
|
|
384
|
+
app_config.lifespan.append(state.lifespan_handler)
|
|
385
|
+
app_config.dependencies.update({
|
|
386
|
+
state.connection_key: Provide(state.connection_provider),
|
|
387
|
+
state.pool_key: Provide(state.pool_provider),
|
|
388
|
+
state.session_key: Provide(state.session_provider),
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
if signature_namespace:
|
|
392
|
+
app_config.signature_namespace.update(signature_namespace)
|
|
393
|
+
|
|
394
|
+
if NUMPY_INSTALLED and (ndarray_type := _get_litestar_numpy_array_type()) is not None:
|
|
395
|
+
import numpy as np
|
|
396
|
+
|
|
397
|
+
numpy_namespace = _NumpySignatureNamespace(np, ndarray_type)
|
|
398
|
+
app_config.signature_namespace.update({
|
|
399
|
+
"np": numpy_namespace,
|
|
400
|
+
"numpy": numpy_namespace,
|
|
401
|
+
"ndarray": ndarray_type,
|
|
402
|
+
})
|
|
403
|
+
|
|
404
|
+
if not any(isinstance(p, _OffsetPaginationSchemaPlugin) for p in app_config.plugins):
|
|
405
|
+
app_config.plugins.append(_OffsetPaginationSchemaPlugin())
|
|
406
|
+
|
|
407
|
+
if app_config.exception_handlers is None:
|
|
408
|
+
app_config.exception_handlers = {}
|
|
409
|
+
app_config.exception_handlers.setdefault(NotFoundError, not_found_error_handler)
|
|
410
|
+
|
|
411
|
+
# Inject sqlspec's DEFAULT_TYPE_ENCODERS into Litestar's response serializer
|
|
412
|
+
# (user-supplied encoders win on conflict). Litestar's per-handler
|
|
413
|
+
# resolve_type_encoders() merges these with route/controller/router-level
|
|
414
|
+
# overrides automatically — no bidirectional thread needed.
|
|
415
|
+
app_config.type_encoders = {**DEFAULT_TYPE_ENCODERS, **(app_config.type_encoders or {})}
|
|
416
|
+
sqlspec_decoders = _build_litestar_type_decoders()
|
|
417
|
+
if sqlspec_decoders:
|
|
418
|
+
app_config.type_decoders = [*(app_config.type_decoders or []), *sqlspec_decoders]
|
|
419
|
+
|
|
420
|
+
if self._correlation_headers:
|
|
421
|
+
middleware = DefineMiddleware(CorrelationMiddleware, headers=self._correlation_headers)
|
|
422
|
+
existing_middleware = list(app_config.middleware or [])
|
|
423
|
+
existing_middleware.append(middleware)
|
|
424
|
+
app_config.middleware = existing_middleware
|
|
425
|
+
|
|
426
|
+
if self._enable_sqlcommenter_middleware:
|
|
427
|
+
sc_middleware = DefineMiddleware(SQLCommenterMiddleware)
|
|
428
|
+
existing_middleware = list(app_config.middleware or [])
|
|
429
|
+
existing_middleware.append(sc_middleware)
|
|
430
|
+
app_config.middleware = existing_middleware
|
|
431
|
+
|
|
432
|
+
log_with_context(
|
|
433
|
+
logger,
|
|
434
|
+
logging.DEBUG,
|
|
435
|
+
"extension.init",
|
|
436
|
+
framework="litestar",
|
|
437
|
+
stage="configured",
|
|
438
|
+
config_count=len(self._plugin_configs),
|
|
439
|
+
correlation_headers=len(self._correlation_headers),
|
|
440
|
+
numpy_enabled=bool(NUMPY_INSTALLED),
|
|
441
|
+
)
|
|
442
|
+
return app_config
|
|
443
|
+
|
|
444
|
+
def get_annotations(
|
|
445
|
+
self,
|
|
446
|
+
) -> "list[type[SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]]]":
|
|
447
|
+
"""Return the list of annotations.
|
|
448
|
+
|
|
449
|
+
Returns:
|
|
450
|
+
List of annotations.
|
|
451
|
+
"""
|
|
452
|
+
return [
|
|
453
|
+
cast(
|
|
454
|
+
"type[SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]]",
|
|
455
|
+
state.annotation,
|
|
456
|
+
)
|
|
457
|
+
for state in self._plugin_configs
|
|
458
|
+
]
|
|
459
|
+
|
|
460
|
+
def get_annotation(
|
|
461
|
+
self,
|
|
462
|
+
key: "str | SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any] | type[SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]]",
|
|
463
|
+
) -> "type[SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]]":
|
|
464
|
+
"""Return the annotation for the given configuration.
|
|
465
|
+
|
|
466
|
+
Args:
|
|
467
|
+
key: The configuration instance or key to lookup.
|
|
468
|
+
|
|
469
|
+
Raises:
|
|
470
|
+
KeyError: If no configuration is found for the given key.
|
|
471
|
+
|
|
472
|
+
Returns:
|
|
473
|
+
The annotation for the configuration.
|
|
474
|
+
"""
|
|
475
|
+
for state in self._plugin_configs:
|
|
476
|
+
if key in {state.config, state.annotation} or key in {state.connection_key, state.pool_key}:
|
|
477
|
+
return cast(
|
|
478
|
+
"type[SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]]",
|
|
479
|
+
state.annotation,
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
msg = f"No configuration found for {key}"
|
|
483
|
+
raise KeyError(msg)
|
|
484
|
+
|
|
485
|
+
@overload
|
|
486
|
+
def get_config(
|
|
487
|
+
self, name: "type[SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any]]"
|
|
488
|
+
) -> "SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any]": ...
|
|
489
|
+
|
|
490
|
+
@overload
|
|
491
|
+
def get_config(
|
|
492
|
+
self, name: "type[AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]]"
|
|
493
|
+
) -> "AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]": ...
|
|
494
|
+
|
|
495
|
+
@overload
|
|
496
|
+
def get_config(
|
|
497
|
+
self, name: str
|
|
498
|
+
) -> "SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]": ...
|
|
499
|
+
|
|
500
|
+
def get_config(
|
|
501
|
+
self, name: "type[DatabaseConfigProtocol[Any, Any, Any]] | str | Any"
|
|
502
|
+
) -> "DatabaseConfigProtocol[Any, Any, Any]":
|
|
503
|
+
"""Get a configuration instance by name.
|
|
504
|
+
|
|
505
|
+
Args:
|
|
506
|
+
name: The configuration identifier.
|
|
507
|
+
|
|
508
|
+
Raises:
|
|
509
|
+
KeyError: If no configuration is found for the given name.
|
|
510
|
+
|
|
511
|
+
Returns:
|
|
512
|
+
The configuration instance for the specified name.
|
|
513
|
+
"""
|
|
514
|
+
if isinstance(name, str):
|
|
515
|
+
for state in self._plugin_configs:
|
|
516
|
+
if name in {state.connection_key, state.pool_key, state.session_key}:
|
|
517
|
+
return cast("DatabaseConfigProtocol[Any, Any, Any]", state.config) # type: ignore[redundant-cast]
|
|
518
|
+
|
|
519
|
+
for state in self._plugin_configs:
|
|
520
|
+
if name in {state.config, state.annotation}:
|
|
521
|
+
return cast("DatabaseConfigProtocol[Any, Any, Any]", state.config) # type: ignore[redundant-cast]
|
|
522
|
+
|
|
523
|
+
msg = f"No database configuration found for name '{name}'. Available keys: {self._get_available_keys()}"
|
|
524
|
+
raise KeyError(msg)
|
|
525
|
+
|
|
526
|
+
def _ensure_connection_sync(self, plugin_state: PluginConfigState, state: "State", scope: "Scope") -> Any:
|
|
527
|
+
"""Ensure a connection exists in scope, creating one from the pool if needed (sync)."""
|
|
528
|
+
connection = get_sqlspec_scope_state(scope, plugin_state.connection_key)
|
|
529
|
+
if connection is not None:
|
|
530
|
+
return connection
|
|
531
|
+
|
|
532
|
+
pool = state.get(plugin_state.pool_key)
|
|
533
|
+
if pool is None:
|
|
534
|
+
self._raise_missing_connection(plugin_state.connection_key)
|
|
535
|
+
|
|
536
|
+
cm = plugin_state.config.provide_connection(pool)
|
|
537
|
+
connection = cm.__enter__() # type: ignore[union-attr]
|
|
538
|
+
set_sqlspec_scope_state(scope, plugin_state.connection_key, connection)
|
|
539
|
+
return connection
|
|
540
|
+
|
|
541
|
+
async def _ensure_connection_async(self, plugin_state: PluginConfigState, state: "State", scope: "Scope") -> Any:
|
|
542
|
+
"""Ensure a connection exists in scope, creating one from the pool if needed (async)."""
|
|
543
|
+
connection = get_sqlspec_scope_state(scope, plugin_state.connection_key)
|
|
544
|
+
if connection is not None:
|
|
545
|
+
return connection
|
|
546
|
+
|
|
547
|
+
pool = state.get(plugin_state.pool_key)
|
|
548
|
+
if pool is None:
|
|
549
|
+
self._raise_missing_connection(plugin_state.connection_key)
|
|
550
|
+
|
|
551
|
+
cm = plugin_state.config.provide_connection(pool)
|
|
552
|
+
connection = await cm.__aenter__() # type: ignore[union-attr]
|
|
553
|
+
set_sqlspec_scope_state(scope, plugin_state.connection_key, connection)
|
|
554
|
+
return connection
|
|
555
|
+
|
|
556
|
+
def _create_session(
|
|
557
|
+
self, plugin_state: PluginConfigState, connection: Any, scope: "Scope"
|
|
558
|
+
) -> "SyncDriverAdapterBase | AsyncDriverAdapterBase":
|
|
559
|
+
"""Create a session from a connection and store it in scope."""
|
|
560
|
+
session_scope_key = f"{plugin_state.session_key}_instance"
|
|
561
|
+
|
|
562
|
+
session = get_sqlspec_scope_state(scope, session_scope_key)
|
|
563
|
+
if session is not None:
|
|
564
|
+
return cast("SyncDriverAdapterBase | AsyncDriverAdapterBase", session)
|
|
565
|
+
|
|
566
|
+
session = plugin_state.config.driver_type(
|
|
567
|
+
connection=connection,
|
|
568
|
+
statement_config=plugin_state.config.statement_config,
|
|
569
|
+
driver_features=plugin_state.config.driver_features,
|
|
570
|
+
)
|
|
571
|
+
set_sqlspec_scope_state(scope, session_scope_key, session)
|
|
572
|
+
return cast("SyncDriverAdapterBase | AsyncDriverAdapterBase", session)
|
|
573
|
+
|
|
574
|
+
@overload
|
|
575
|
+
def provide_request_session(
|
|
576
|
+
self,
|
|
577
|
+
key: "SyncDatabaseConfig[Any, Any, DriverT] | NoPoolSyncConfig[Any, DriverT] | type[SyncDatabaseConfig[Any, Any, DriverT] | NoPoolSyncConfig[Any, DriverT]]",
|
|
578
|
+
state: "State",
|
|
579
|
+
scope: "Scope",
|
|
580
|
+
) -> "DriverT": ...
|
|
581
|
+
|
|
582
|
+
@overload
|
|
583
|
+
def provide_request_session(
|
|
584
|
+
self,
|
|
585
|
+
key: "AsyncDatabaseConfig[Any, Any, DriverT] | NoPoolAsyncConfig[Any, DriverT] | type[AsyncDatabaseConfig[Any, Any, DriverT] | NoPoolAsyncConfig[Any, DriverT]]",
|
|
586
|
+
state: "State",
|
|
587
|
+
scope: "Scope",
|
|
588
|
+
) -> "DriverT": ...
|
|
589
|
+
|
|
590
|
+
@overload
|
|
591
|
+
def provide_request_session(
|
|
592
|
+
self, key: str, state: "State", scope: "Scope"
|
|
593
|
+
) -> "SyncDriverAdapterBase | AsyncDriverAdapterBase": ...
|
|
594
|
+
|
|
595
|
+
def provide_request_session(
|
|
596
|
+
self,
|
|
597
|
+
key: "str | SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any] | type[SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]]",
|
|
598
|
+
state: "State",
|
|
599
|
+
scope: "Scope",
|
|
600
|
+
) -> "SyncDriverAdapterBase | AsyncDriverAdapterBase":
|
|
601
|
+
"""Provide a database session for the specified configuration key from request scope.
|
|
602
|
+
|
|
603
|
+
This method requires the connection to already exist in scope (e.g., from DI injection).
|
|
604
|
+
For on-demand connection creation, use ``provide_request_session_sync`` or
|
|
605
|
+
``provide_request_session_async`` instead.
|
|
606
|
+
|
|
607
|
+
Args:
|
|
608
|
+
key: The configuration identifier (same as get_config).
|
|
609
|
+
state: The Litestar application State object.
|
|
610
|
+
scope: The ASGI scope containing the request context.
|
|
611
|
+
|
|
612
|
+
Returns:
|
|
613
|
+
A driver session instance for the specified database configuration.
|
|
614
|
+
"""
|
|
615
|
+
plugin_state = self._get_plugin_state(key)
|
|
616
|
+
connection = get_sqlspec_scope_state(scope, plugin_state.connection_key)
|
|
617
|
+
if connection is None:
|
|
618
|
+
self._raise_missing_connection(plugin_state.connection_key)
|
|
619
|
+
return self._create_session(plugin_state, connection, scope)
|
|
620
|
+
|
|
621
|
+
@overload
|
|
622
|
+
def provide_request_session_sync(
|
|
623
|
+
self,
|
|
624
|
+
key: "SyncDatabaseConfig[Any, Any, DriverT] | NoPoolSyncConfig[Any, DriverT]",
|
|
625
|
+
state: "State",
|
|
626
|
+
scope: "Scope",
|
|
627
|
+
) -> "DriverT": ...
|
|
628
|
+
|
|
629
|
+
@overload
|
|
630
|
+
def provide_request_session_sync(
|
|
631
|
+
self,
|
|
632
|
+
key: "type[SyncDatabaseConfig[Any, Any, DriverT] | NoPoolSyncConfig[Any, DriverT]]",
|
|
633
|
+
state: "State",
|
|
634
|
+
scope: "Scope",
|
|
635
|
+
) -> "DriverT": ...
|
|
636
|
+
|
|
637
|
+
@overload
|
|
638
|
+
def provide_request_session_sync(self, key: str, state: "State", scope: "Scope") -> "SyncDriverAdapterBase": ...
|
|
639
|
+
|
|
640
|
+
def provide_request_session_sync(
|
|
641
|
+
self,
|
|
642
|
+
key: "str | SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | type[SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any]]",
|
|
643
|
+
state: "State",
|
|
644
|
+
scope: "Scope",
|
|
645
|
+
) -> "SyncDriverAdapterBase | Any":
|
|
646
|
+
"""Provide a sync database session for the specified configuration key from request scope.
|
|
647
|
+
|
|
648
|
+
If no connection exists in scope, one will be created from the pool and stored
|
|
649
|
+
in scope for reuse. The connection will be cleaned up by the before_send handler.
|
|
650
|
+
|
|
651
|
+
For async configurations, use ``provide_request_session_async`` instead.
|
|
652
|
+
|
|
653
|
+
Args:
|
|
654
|
+
key: The configuration identifier (same as get_config).
|
|
655
|
+
state: The Litestar application State object.
|
|
656
|
+
scope: The ASGI scope containing the request context.
|
|
657
|
+
|
|
658
|
+
Returns:
|
|
659
|
+
A sync driver session instance for the specified database configuration.
|
|
660
|
+
"""
|
|
661
|
+
plugin_state = self._get_plugin_state(key)
|
|
662
|
+
connection = self._ensure_connection_sync(plugin_state, state, scope)
|
|
663
|
+
return cast("SyncDriverAdapterBase", self._create_session(plugin_state, connection, scope))
|
|
664
|
+
|
|
665
|
+
@overload
|
|
666
|
+
async def provide_request_session_async(
|
|
667
|
+
self,
|
|
668
|
+
key: "AsyncDatabaseConfig[Any, Any, DriverT] | NoPoolAsyncConfig[Any, DriverT]",
|
|
669
|
+
state: "State",
|
|
670
|
+
scope: "Scope",
|
|
671
|
+
) -> "DriverT": ...
|
|
672
|
+
|
|
673
|
+
@overload
|
|
674
|
+
async def provide_request_session_async(
|
|
675
|
+
self,
|
|
676
|
+
key: "type[AsyncDatabaseConfig[Any, Any, DriverT] | NoPoolAsyncConfig[Any, DriverT]]",
|
|
677
|
+
state: "State",
|
|
678
|
+
scope: "Scope",
|
|
679
|
+
) -> "DriverT": ...
|
|
680
|
+
|
|
681
|
+
@overload
|
|
682
|
+
async def provide_request_session_async(
|
|
683
|
+
self, key: str, state: "State", scope: "Scope"
|
|
684
|
+
) -> "AsyncDriverAdapterBase": ...
|
|
685
|
+
|
|
686
|
+
async def provide_request_session_async(
|
|
687
|
+
self,
|
|
688
|
+
key: "str | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any] | type[AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]]",
|
|
689
|
+
state: "State",
|
|
690
|
+
scope: "Scope",
|
|
691
|
+
) -> "AsyncDriverAdapterBase | Any":
|
|
692
|
+
"""Provide an async database session for the specified configuration key from request scope.
|
|
693
|
+
|
|
694
|
+
If no connection exists in scope, one will be created from the pool and stored
|
|
695
|
+
in scope for reuse. The connection will be cleaned up by the before_send handler.
|
|
696
|
+
|
|
697
|
+
For sync configurations, use ``provide_request_session`` instead.
|
|
698
|
+
|
|
699
|
+
Args:
|
|
700
|
+
key: The configuration identifier (same as get_config).
|
|
701
|
+
state: The Litestar application State object.
|
|
702
|
+
scope: The ASGI scope containing the request context.
|
|
703
|
+
|
|
704
|
+
Returns:
|
|
705
|
+
An async driver session instance for the specified database configuration.
|
|
706
|
+
"""
|
|
707
|
+
plugin_state = self._get_plugin_state(key)
|
|
708
|
+
connection = await self._ensure_connection_async(plugin_state, state, scope)
|
|
709
|
+
return cast("AsyncDriverAdapterBase", self._create_session(plugin_state, connection, scope))
|
|
710
|
+
|
|
711
|
+
@overload
|
|
712
|
+
def provide_request_connection(
|
|
713
|
+
self,
|
|
714
|
+
key: "SyncDatabaseConfig[ConnectionT, Any, Any] | NoPoolSyncConfig[ConnectionT, Any] | AsyncDatabaseConfig[ConnectionT, Any, Any] | NoPoolAsyncConfig[ConnectionT, Any]",
|
|
715
|
+
state: "State",
|
|
716
|
+
scope: "Scope",
|
|
717
|
+
) -> "ConnectionT": ...
|
|
718
|
+
|
|
719
|
+
@overload
|
|
720
|
+
def provide_request_connection(
|
|
721
|
+
self,
|
|
722
|
+
key: "type[SyncDatabaseConfig[ConnectionT, Any, Any] | NoPoolSyncConfig[ConnectionT, Any] | AsyncDatabaseConfig[ConnectionT, Any, Any] | NoPoolAsyncConfig[ConnectionT, Any]]",
|
|
723
|
+
state: "State",
|
|
724
|
+
scope: "Scope",
|
|
725
|
+
) -> "ConnectionT": ...
|
|
726
|
+
|
|
727
|
+
@overload
|
|
728
|
+
def provide_request_connection(self, key: str, state: "State", scope: "Scope") -> Any: ...
|
|
729
|
+
|
|
730
|
+
def provide_request_connection(
|
|
731
|
+
self,
|
|
732
|
+
key: "str | SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any] | type[SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]]",
|
|
733
|
+
state: "State",
|
|
734
|
+
scope: "Scope",
|
|
735
|
+
) -> Any:
|
|
736
|
+
"""Provide a database connection for the specified configuration key from request scope.
|
|
737
|
+
|
|
738
|
+
This method requires the connection to already exist in scope (e.g., from DI injection).
|
|
739
|
+
For on-demand connection creation, use ``provide_request_connection_sync`` or
|
|
740
|
+
``provide_request_connection_async`` instead.
|
|
741
|
+
|
|
742
|
+
Args:
|
|
743
|
+
key: The configuration identifier (same as get_config).
|
|
744
|
+
state: The Litestar application State object.
|
|
745
|
+
scope: The ASGI scope containing the request context.
|
|
746
|
+
|
|
747
|
+
Returns:
|
|
748
|
+
A database connection instance for the specified database configuration.
|
|
749
|
+
"""
|
|
750
|
+
plugin_state = self._get_plugin_state(key)
|
|
751
|
+
connection = get_sqlspec_scope_state(scope, plugin_state.connection_key)
|
|
752
|
+
if connection is None:
|
|
753
|
+
self._raise_missing_connection(plugin_state.connection_key)
|
|
754
|
+
return connection
|
|
755
|
+
|
|
756
|
+
@overload
|
|
757
|
+
def provide_request_connection_sync(
|
|
758
|
+
self,
|
|
759
|
+
key: "SyncDatabaseConfig[ConnectionT, Any, Any] | NoPoolSyncConfig[ConnectionT, Any]",
|
|
760
|
+
state: "State",
|
|
761
|
+
scope: "Scope",
|
|
762
|
+
) -> "ConnectionT": ...
|
|
763
|
+
|
|
764
|
+
@overload
|
|
765
|
+
def provide_request_connection_sync(
|
|
766
|
+
self,
|
|
767
|
+
key: "type[SyncDatabaseConfig[ConnectionT, Any, Any] | NoPoolSyncConfig[ConnectionT, Any]]",
|
|
768
|
+
state: "State",
|
|
769
|
+
scope: "Scope",
|
|
770
|
+
) -> "ConnectionT": ...
|
|
771
|
+
|
|
772
|
+
@overload
|
|
773
|
+
def provide_request_connection_sync(self, key: str, state: "State", scope: "Scope") -> Any: ...
|
|
774
|
+
|
|
775
|
+
def provide_request_connection_sync(
|
|
776
|
+
self,
|
|
777
|
+
key: "str | SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any] | type[SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any]]",
|
|
778
|
+
state: "State",
|
|
779
|
+
scope: "Scope",
|
|
780
|
+
) -> Any:
|
|
781
|
+
"""Provide a sync database connection for the specified configuration key from request scope.
|
|
782
|
+
|
|
783
|
+
If no connection exists in scope, one will be created from the pool and stored
|
|
784
|
+
in scope for reuse. The connection will be cleaned up by the before_send handler.
|
|
785
|
+
|
|
786
|
+
For async configurations, use ``provide_request_connection_async`` instead.
|
|
787
|
+
|
|
788
|
+
Args:
|
|
789
|
+
key: The configuration identifier (same as get_config).
|
|
790
|
+
state: The Litestar application State object.
|
|
791
|
+
scope: The ASGI scope containing the request context.
|
|
792
|
+
|
|
793
|
+
Returns:
|
|
794
|
+
A database connection instance for the specified database configuration.
|
|
795
|
+
"""
|
|
796
|
+
plugin_state = self._get_plugin_state(key)
|
|
797
|
+
return self._ensure_connection_sync(plugin_state, state, scope)
|
|
798
|
+
|
|
799
|
+
@overload
|
|
800
|
+
async def provide_request_connection_async(
|
|
801
|
+
self,
|
|
802
|
+
key: "AsyncDatabaseConfig[ConnectionT, Any, Any] | NoPoolAsyncConfig[ConnectionT, Any]",
|
|
803
|
+
state: "State",
|
|
804
|
+
scope: "Scope",
|
|
805
|
+
) -> "ConnectionT": ...
|
|
806
|
+
|
|
807
|
+
@overload
|
|
808
|
+
async def provide_request_connection_async(
|
|
809
|
+
self,
|
|
810
|
+
key: "type[AsyncDatabaseConfig[ConnectionT, Any, Any] | NoPoolAsyncConfig[ConnectionT, Any]]",
|
|
811
|
+
state: "State",
|
|
812
|
+
scope: "Scope",
|
|
813
|
+
) -> "ConnectionT": ...
|
|
814
|
+
|
|
815
|
+
@overload
|
|
816
|
+
async def provide_request_connection_async(self, key: str, state: "State", scope: "Scope") -> Any: ...
|
|
817
|
+
|
|
818
|
+
async def provide_request_connection_async(
|
|
819
|
+
self,
|
|
820
|
+
key: "str | AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any] | type[AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]]",
|
|
821
|
+
state: "State",
|
|
822
|
+
scope: "Scope",
|
|
823
|
+
) -> Any:
|
|
824
|
+
"""Provide an async database connection for the specified configuration key from request scope.
|
|
825
|
+
|
|
826
|
+
If no connection exists in scope, one will be created from the pool and stored
|
|
827
|
+
in scope for reuse. The connection will be cleaned up by the before_send handler.
|
|
828
|
+
|
|
829
|
+
For sync configurations, use ``provide_request_connection`` instead.
|
|
830
|
+
|
|
831
|
+
Args:
|
|
832
|
+
key: The configuration identifier (same as get_config).
|
|
833
|
+
state: The Litestar application State object.
|
|
834
|
+
scope: The ASGI scope containing the request context.
|
|
835
|
+
|
|
836
|
+
Returns:
|
|
837
|
+
A database connection instance for the specified database configuration.
|
|
838
|
+
"""
|
|
839
|
+
plugin_state = self._get_plugin_state(key)
|
|
840
|
+
return await self._ensure_connection_async(plugin_state, state, scope)
|
|
841
|
+
|
|
842
|
+
def _get_plugin_state(
|
|
843
|
+
self, key: "str | DatabaseConfigProtocol[Any, Any, Any] | type[DatabaseConfigProtocol[Any, Any, Any]]"
|
|
844
|
+
) -> PluginConfigState:
|
|
845
|
+
"""Get plugin state for a configuration by key."""
|
|
846
|
+
if isinstance(key, str):
|
|
847
|
+
for state in self._plugin_configs:
|
|
848
|
+
if key in {state.connection_key, state.pool_key, state.session_key}:
|
|
849
|
+
return state
|
|
850
|
+
|
|
851
|
+
for state in self._plugin_configs:
|
|
852
|
+
if key in {state.config, state.annotation}:
|
|
853
|
+
return state
|
|
854
|
+
|
|
855
|
+
self._raise_config_not_found(key)
|
|
856
|
+
return None
|
|
857
|
+
|
|
858
|
+
def _get_available_keys(self) -> "list[str]":
|
|
859
|
+
"""Get a list of all available configuration keys for error messages."""
|
|
860
|
+
keys = []
|
|
861
|
+
for state in self._plugin_configs:
|
|
862
|
+
keys.extend([state.connection_key, state.pool_key, state.session_key])
|
|
863
|
+
return keys
|
|
864
|
+
|
|
865
|
+
def _validate_dependency_keys(self) -> None:
|
|
866
|
+
"""Validate that connection and pool keys are unique across configurations."""
|
|
867
|
+
connection_keys = [state.connection_key for state in self._plugin_configs]
|
|
868
|
+
pool_keys = [state.pool_key for state in self._plugin_configs]
|
|
869
|
+
|
|
870
|
+
if len(set(connection_keys)) != len(connection_keys):
|
|
871
|
+
self._raise_duplicate_connection_keys()
|
|
872
|
+
|
|
873
|
+
if len(set(pool_keys)) != len(pool_keys):
|
|
874
|
+
self._raise_duplicate_pool_keys()
|
|
875
|
+
|
|
876
|
+
def _raise_missing_connection(self, connection_key: str) -> None:
|
|
877
|
+
"""Raise error when connection is not found in scope."""
|
|
878
|
+
msg = f"No database connection found in scope for key '{connection_key}'. "
|
|
879
|
+
msg += "Ensure the connection dependency is properly configured and available."
|
|
880
|
+
raise ImproperConfigurationError(detail=msg)
|
|
881
|
+
|
|
882
|
+
def _raise_config_not_found(self, key: Any) -> NoReturn:
|
|
883
|
+
"""Raise error when configuration is not found."""
|
|
884
|
+
msg = f"No database configuration found for name '{key}'. Available keys: {self._get_available_keys()}"
|
|
885
|
+
raise KeyError(msg)
|
|
886
|
+
|
|
887
|
+
def _raise_duplicate_connection_keys(self) -> None:
|
|
888
|
+
"""Raise error when connection keys are not unique."""
|
|
889
|
+
msg = "When using multiple database configuration, each configuration must have a unique `connection_key`."
|
|
890
|
+
raise ImproperConfigurationError(detail=msg)
|
|
891
|
+
|
|
892
|
+
def _raise_duplicate_pool_keys(self) -> None:
|
|
893
|
+
"""Raise error when pool keys are not unique."""
|
|
894
|
+
msg = "When using multiple database configuration, each configuration must have a unique `pool_key`."
|
|
895
|
+
raise ImproperConfigurationError(detail=msg)
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
class SQLCommenterMiddleware:
|
|
899
|
+
"""ASGI middleware that populates SQLCommenterContext with Litestar request attributes.
|
|
900
|
+
|
|
901
|
+
Extracts route, controller, and action from the Litestar scope and sets them
|
|
902
|
+
in :class:`~sqlspec.extensions.sqlcommenter.SQLCommenterContext` for the
|
|
903
|
+
duration of the request.
|
|
904
|
+
"""
|
|
905
|
+
|
|
906
|
+
__slots__ = ("app",)
|
|
907
|
+
|
|
908
|
+
def __init__(self, app: "ASGIApp") -> None:
|
|
909
|
+
self.app = app
|
|
910
|
+
|
|
911
|
+
async def __call__(self, scope: "Scope", receive: "Receive", send: "Send") -> None:
|
|
912
|
+
if str(scope.get("type")) != "http":
|
|
913
|
+
await self.app(scope, receive, send)
|
|
914
|
+
return
|
|
915
|
+
|
|
916
|
+
attrs: dict[str, str] = {"route": scope.get("path", ""), "framework": "litestar"}
|
|
917
|
+
handler = scope.get("route_handler")
|
|
918
|
+
if handler is not None:
|
|
919
|
+
fn = getattr(handler, "fn", None)
|
|
920
|
+
if fn is not None:
|
|
921
|
+
attrs["action"] = getattr(fn, "__name__", "")
|
|
922
|
+
owner = getattr(handler, "owner", None)
|
|
923
|
+
if owner is not None:
|
|
924
|
+
attrs["controller"] = getattr(owner, "__name__", "")
|
|
925
|
+
|
|
926
|
+
previous = SQLCommenterContext.get()
|
|
927
|
+
SQLCommenterContext.set(attrs)
|
|
928
|
+
try:
|
|
929
|
+
await self.app(scope, receive, send)
|
|
930
|
+
finally:
|
|
931
|
+
SQLCommenterContext.set(previous)
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
class _OffsetPaginationSchemaPlugin(OpenAPISchemaPlugin):
|
|
935
|
+
"""OpenAPI schema plugin expanding OffsetPagination[T] into a concrete schema.
|
|
936
|
+
|
|
937
|
+
Defense-in-depth for sqlspec.core.filters.OffsetPagination. The msgspec.Struct
|
|
938
|
+
conversion already lets Litestar's default generator produce a correct schema;
|
|
939
|
+
this plugin guarantees the shape even if future Litestar or msgspec changes
|
|
940
|
+
break auto-detection.
|
|
941
|
+
"""
|
|
942
|
+
|
|
943
|
+
@staticmethod
|
|
944
|
+
def is_plugin_supported_type(value: Any) -> bool:
|
|
945
|
+
origin = getattr(value, "__origin__", value)
|
|
946
|
+
return isinstance(origin, type) and issubclass(origin, OffsetPagination)
|
|
947
|
+
|
|
948
|
+
def to_openapi_schema(self, field_definition: "FieldDefinition", schema_creator: "SchemaCreator") -> "Schema":
|
|
949
|
+
from litestar.openapi.spec import OpenAPIType, Schema
|
|
950
|
+
from litestar.typing import FieldDefinition
|
|
951
|
+
|
|
952
|
+
inner_type: Any = Any
|
|
953
|
+
inner_args = getattr(field_definition, "inner_types", ())
|
|
954
|
+
if inner_args:
|
|
955
|
+
inner_type = inner_args[0].annotation
|
|
956
|
+
|
|
957
|
+
item_schema = schema_creator.for_field_definition(FieldDefinition.from_annotation(inner_type))
|
|
958
|
+
|
|
959
|
+
return Schema(
|
|
960
|
+
type=OpenAPIType.OBJECT,
|
|
961
|
+
properties={
|
|
962
|
+
"items": Schema(type=OpenAPIType.ARRAY, items=item_schema),
|
|
963
|
+
"limit": Schema(type=OpenAPIType.INTEGER),
|
|
964
|
+
"offset": Schema(type=OpenAPIType.INTEGER),
|
|
965
|
+
"total": Schema(type=OpenAPIType.INTEGER),
|
|
966
|
+
},
|
|
967
|
+
required=["items", "limit", "offset", "total"],
|
|
968
|
+
)
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
class _NumpySignatureNamespace:
|
|
972
|
+
"""Proxy ``numpy`` module namespace that maps ``ndarray`` to SQLSpec's decoder-safe subclass."""
|
|
973
|
+
|
|
974
|
+
__slots__ = ("_numpy", "ndarray")
|
|
975
|
+
|
|
976
|
+
def __init__(self, numpy_module: Any, ndarray_type: type[Any]) -> None:
|
|
977
|
+
self._numpy = numpy_module
|
|
978
|
+
self.ndarray = ndarray_type
|
|
979
|
+
|
|
980
|
+
def __getattr__(self, name: str) -> Any:
|
|
981
|
+
return getattr(self._numpy, name)
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
def _normalize_header_list(headers: Any) -> list[str]:
|
|
985
|
+
if headers is None:
|
|
986
|
+
return []
|
|
987
|
+
if isinstance(headers, str):
|
|
988
|
+
return [headers.lower()]
|
|
989
|
+
if isinstance(headers, Iterable):
|
|
990
|
+
normalized: list[str] = []
|
|
991
|
+
for header in headers:
|
|
992
|
+
if not isinstance(header, str):
|
|
993
|
+
msg = "litestar correlation headers must be strings"
|
|
994
|
+
raise ImproperConfigurationError(msg)
|
|
995
|
+
normalized.append(header.lower())
|
|
996
|
+
return normalized
|
|
997
|
+
msg = "litestar correlation_headers must be a string or iterable of strings"
|
|
998
|
+
raise ImproperConfigurationError(msg)
|
|
999
|
+
|
|
1000
|
+
|
|
1001
|
+
def _dedupe_headers(headers: Iterable[str]) -> list[str]:
|
|
1002
|
+
seen: set[str] = set()
|
|
1003
|
+
ordered: list[str] = []
|
|
1004
|
+
for header in headers:
|
|
1005
|
+
lowered = header.lower()
|
|
1006
|
+
if lowered in seen or not lowered:
|
|
1007
|
+
continue
|
|
1008
|
+
seen.add(lowered)
|
|
1009
|
+
ordered.append(lowered)
|
|
1010
|
+
return ordered
|
|
1011
|
+
|
|
1012
|
+
|
|
1013
|
+
def _build_correlation_headers(*, primary: str, configured: list[str], auto_trace_headers: bool) -> tuple[str, ...]:
|
|
1014
|
+
header_order: list[str] = [primary.lower()]
|
|
1015
|
+
header_order.extend(configured)
|
|
1016
|
+
if auto_trace_headers:
|
|
1017
|
+
header_order.extend(TRACE_CONTEXT_FALLBACK_HEADERS)
|
|
1018
|
+
return tuple(_dedupe_headers(header_order))
|
|
1019
|
+
|
|
1020
|
+
|
|
1021
|
+
def _get_litestar_numpy_array_type() -> type[Any] | None:
|
|
1022
|
+
"""Return a mutable ndarray subclass Litestar can attach a decoder to."""
|
|
1023
|
+
if not NUMPY_INSTALLED:
|
|
1024
|
+
return None
|
|
1025
|
+
|
|
1026
|
+
global _LITESTAR_NUMPY_ARRAY_TYPE
|
|
1027
|
+
if _LITESTAR_NUMPY_ARRAY_TYPE is None:
|
|
1028
|
+
import numpy as np
|
|
1029
|
+
|
|
1030
|
+
class SQLSpecNumpyArray(np.ndarray):
|
|
1031
|
+
pass
|
|
1032
|
+
|
|
1033
|
+
_LITESTAR_NUMPY_ARRAY_TYPE = SQLSpecNumpyArray
|
|
1034
|
+
return _LITESTAR_NUMPY_ARRAY_TYPE
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
def _litestar_numpy_array_predicate(target_type: Any) -> bool:
|
|
1038
|
+
ndarray_type = _get_litestar_numpy_array_type()
|
|
1039
|
+
return ndarray_type is not None and target_type is ndarray_type
|
|
1040
|
+
|
|
1041
|
+
|
|
1042
|
+
def _litestar_numpy_array_dec_hook(target_type: type[Any], value: Any) -> Any:
|
|
1043
|
+
decoded = numpy_array_dec_hook(target_type, value)
|
|
1044
|
+
if NUMPY_INSTALLED:
|
|
1045
|
+
import numpy as np
|
|
1046
|
+
|
|
1047
|
+
if isinstance(decoded, np.ndarray) and isinstance(target_type, type) and not isinstance(decoded, target_type):
|
|
1048
|
+
return decoded.view(target_type)
|
|
1049
|
+
return decoded
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
def _build_litestar_type_decoders() -> "list[tuple[Callable[[Any], bool], Callable[[type, Any], Any]]]":
|
|
1053
|
+
"""Build the Litestar-specific ``type_decoders`` list.
|
|
1054
|
+
|
|
1055
|
+
Decoders are predicate-tuples consumed by Litestar's request-body parsing,
|
|
1056
|
+
not part of sqlspec's serializer registry — so they live here rather than
|
|
1057
|
+
in :data:`sqlspec.utils.serializers.DEFAULT_TYPE_ENCODERS`.
|
|
1058
|
+
"""
|
|
1059
|
+
decoders: list[tuple[Callable[[Any], bool], Callable[[type, Any], Any]]] = []
|
|
1060
|
+
if NUMPY_INSTALLED:
|
|
1061
|
+
decoders.append((_litestar_numpy_array_predicate, _litestar_numpy_array_dec_hook))
|
|
1062
|
+
with suppress(ImportError):
|
|
1063
|
+
import uuid_utils # pyright: ignore[reportMissingImports]
|
|
1064
|
+
|
|
1065
|
+
decoders.append((lambda t: t is uuid_utils.UUID, lambda t, v: t(str(v))))
|
|
1066
|
+
return decoders
|