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,298 @@
|
|
|
1
|
+
"""Base session store classes for Litestar integration."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from abc import ABC, abstractmethod
|
|
5
|
+
from datetime import datetime, timedelta, timezone
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Final, Generic, TypeVar, cast
|
|
7
|
+
|
|
8
|
+
from sqlspec.observability import resolve_db_system
|
|
9
|
+
from sqlspec.utils.logging import get_logger
|
|
10
|
+
from sqlspec.utils.type_guards import has_extension_config
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from types import TracebackType
|
|
14
|
+
|
|
15
|
+
from typing_extensions import Self
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
ConfigT = TypeVar("ConfigT")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
logger = get_logger("sqlspec.extensions.litestar.store")
|
|
22
|
+
|
|
23
|
+
__all__ = ("BaseSQLSpecStore",)
|
|
24
|
+
|
|
25
|
+
VALID_TABLE_NAME_PATTERN: Final = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$")
|
|
26
|
+
MAX_TABLE_NAME_LENGTH: Final = 63
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class BaseSQLSpecStore(ABC, Generic[ConfigT]):
|
|
30
|
+
"""Base class for SQLSpec-backed Litestar session stores.
|
|
31
|
+
|
|
32
|
+
Implements the litestar.stores.base.Store protocol for server-side session
|
|
33
|
+
storage using SQLSpec database adapters.
|
|
34
|
+
|
|
35
|
+
This abstract base class provides common functionality for all database-specific
|
|
36
|
+
store implementations including:
|
|
37
|
+
- Connection management via SQLSpec configs
|
|
38
|
+
- Session expiration calculation
|
|
39
|
+
- Table creation utilities
|
|
40
|
+
|
|
41
|
+
Subclasses must implement dialect-specific SQL queries.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
config: SQLSpec database configuration with extension_config["litestar"] settings.
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
from sqlspec.adapters.asyncpg import AsyncpgConfig
|
|
48
|
+
from sqlspec.adapters.asyncpg.litestar.store import AsyncpgStore
|
|
49
|
+
|
|
50
|
+
config = AsyncpgConfig(
|
|
51
|
+
connection_config={"dsn": "postgresql://..."},
|
|
52
|
+
extension_config={"litestar": {"session_table": "my_sessions"}}
|
|
53
|
+
)
|
|
54
|
+
store = AsyncpgStore(config)
|
|
55
|
+
await store.create_table()
|
|
56
|
+
|
|
57
|
+
Notes:
|
|
58
|
+
Configuration is read from config.extension_config["litestar"]:
|
|
59
|
+
- session_table: Table name (default: "litestar_session")
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
__slots__ = ("_config", "_table_name")
|
|
63
|
+
|
|
64
|
+
def __init__(self, config: ConfigT) -> None:
|
|
65
|
+
"""Initialize the session store.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
config: SQLSpec database configuration.
|
|
69
|
+
|
|
70
|
+
Notes:
|
|
71
|
+
Reads table_name from config.extension_config["litestar"]["session_table"].
|
|
72
|
+
Defaults to "litestar_session" if not specified.
|
|
73
|
+
"""
|
|
74
|
+
self._config = config
|
|
75
|
+
self._table_name = self._get_table_name_from_config()
|
|
76
|
+
self._validate_table_name(self._table_name)
|
|
77
|
+
|
|
78
|
+
def _get_table_name_from_config(self) -> str:
|
|
79
|
+
"""Extract table name from config.extension_config.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
Table name for the session store.
|
|
83
|
+
|
|
84
|
+
Notes:
|
|
85
|
+
Accepts ``session_table: True`` for default name or a string for custom name.
|
|
86
|
+
"""
|
|
87
|
+
default_name = "litestar_session"
|
|
88
|
+
if has_extension_config(self._config):
|
|
89
|
+
extension_config = cast("dict[str, dict[str, Any]]", self._config.extension_config)
|
|
90
|
+
litestar_config: dict[str, Any] = extension_config.get("litestar", {})
|
|
91
|
+
session_table = litestar_config.get("session_table", default_name)
|
|
92
|
+
if session_table is True:
|
|
93
|
+
return default_name
|
|
94
|
+
return str(session_table)
|
|
95
|
+
return default_name
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def config(self) -> ConfigT:
|
|
99
|
+
"""Return the database configuration."""
|
|
100
|
+
return self._config
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def table_name(self) -> str:
|
|
104
|
+
"""Return the session table name."""
|
|
105
|
+
return self._table_name
|
|
106
|
+
|
|
107
|
+
@abstractmethod
|
|
108
|
+
async def get(self, key: str, renew_for: "int | timedelta | None" = None) -> "bytes | None":
|
|
109
|
+
"""Get a session value by key.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
key: Session ID to retrieve.
|
|
113
|
+
renew_for: If given and the value had an initial expiry time set, renew the
|
|
114
|
+
expiry time for ``renew_for`` seconds. If the value has not been set
|
|
115
|
+
with an expiry time this is a no-op.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
Session data as bytes if found and not expired, None otherwise.
|
|
119
|
+
"""
|
|
120
|
+
raise NotImplementedError
|
|
121
|
+
|
|
122
|
+
@abstractmethod
|
|
123
|
+
async def set(self, key: str, value: "str | bytes", expires_in: "int | timedelta | None" = None) -> None:
|
|
124
|
+
"""Store a session value.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
key: Session ID.
|
|
128
|
+
value: Session data (will be converted to bytes if string).
|
|
129
|
+
expires_in: Time in seconds or timedelta before expiration.
|
|
130
|
+
"""
|
|
131
|
+
raise NotImplementedError
|
|
132
|
+
|
|
133
|
+
@abstractmethod
|
|
134
|
+
async def delete(self, key: str) -> None:
|
|
135
|
+
"""Delete a session by key.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
key: Session ID to delete.
|
|
139
|
+
"""
|
|
140
|
+
raise NotImplementedError
|
|
141
|
+
|
|
142
|
+
@abstractmethod
|
|
143
|
+
async def delete_all(self) -> None:
|
|
144
|
+
"""Delete all sessions from the store."""
|
|
145
|
+
raise NotImplementedError
|
|
146
|
+
|
|
147
|
+
@abstractmethod
|
|
148
|
+
async def exists(self, key: str) -> bool:
|
|
149
|
+
"""Check if a session key exists and is not expired.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
key: Session ID to check.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
True if the session exists and is not expired.
|
|
156
|
+
"""
|
|
157
|
+
raise NotImplementedError
|
|
158
|
+
|
|
159
|
+
@abstractmethod
|
|
160
|
+
async def expires_in(self, key: str) -> "int | None":
|
|
161
|
+
"""Get the time in seconds until the session expires.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
key: Session ID to check.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Seconds until expiration, or None if no expiry or key doesn't exist.
|
|
168
|
+
"""
|
|
169
|
+
raise NotImplementedError
|
|
170
|
+
|
|
171
|
+
@abstractmethod
|
|
172
|
+
async def delete_expired(self) -> int:
|
|
173
|
+
"""Delete all expired sessions.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
Number of sessions deleted.
|
|
177
|
+
"""
|
|
178
|
+
raise NotImplementedError
|
|
179
|
+
|
|
180
|
+
@abstractmethod
|
|
181
|
+
async def create_table(self) -> None:
|
|
182
|
+
"""Create the session table if it doesn't exist."""
|
|
183
|
+
raise NotImplementedError
|
|
184
|
+
|
|
185
|
+
@abstractmethod
|
|
186
|
+
def _get_create_table_sql(self) -> str:
|
|
187
|
+
"""Get the CREATE TABLE SQL for this database dialect.
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
SQL statement to create the sessions table.
|
|
191
|
+
"""
|
|
192
|
+
raise NotImplementedError
|
|
193
|
+
|
|
194
|
+
@abstractmethod
|
|
195
|
+
def _get_drop_table_sql(self) -> "list[str]":
|
|
196
|
+
"""Get the DROP TABLE SQL statements for this database dialect.
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
List of SQL statements to drop the table and all indexes.
|
|
200
|
+
Order matters: drop indexes before table.
|
|
201
|
+
|
|
202
|
+
Notes:
|
|
203
|
+
Should use IF EXISTS or dialect-specific error handling
|
|
204
|
+
to allow idempotent migrations.
|
|
205
|
+
"""
|
|
206
|
+
raise NotImplementedError
|
|
207
|
+
|
|
208
|
+
async def __aenter__(self) -> "Self":
|
|
209
|
+
"""Enter context manager."""
|
|
210
|
+
return self
|
|
211
|
+
|
|
212
|
+
async def __aexit__(
|
|
213
|
+
self, exc_type: "type[BaseException] | None", exc_val: "BaseException | None", exc_tb: "TracebackType | None"
|
|
214
|
+
) -> None:
|
|
215
|
+
"""Exit context manager."""
|
|
216
|
+
return
|
|
217
|
+
|
|
218
|
+
def _log_table_created(self) -> None:
|
|
219
|
+
logger.debug(
|
|
220
|
+
"Litestar session table ready",
|
|
221
|
+
extra={"db.system": resolve_db_system(type(self).__name__), "session_table": self._table_name},
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
def _log_delete_all(self) -> None:
|
|
225
|
+
logger.debug(
|
|
226
|
+
"Litestar sessions cleared",
|
|
227
|
+
extra={"db.system": resolve_db_system(type(self).__name__), "session_table": self._table_name},
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
def _log_delete_expired(self, count: int) -> None:
|
|
231
|
+
logger.debug(
|
|
232
|
+
"Litestar sessions expired cleanup",
|
|
233
|
+
extra={
|
|
234
|
+
"db.system": resolve_db_system(type(self).__name__),
|
|
235
|
+
"session_table": self._table_name,
|
|
236
|
+
"deleted_sessions": count,
|
|
237
|
+
},
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
def _calculate_expires_at(self, expires_in: "int | timedelta | None") -> "datetime | None":
|
|
241
|
+
"""Calculate expiration timestamp from expires_in.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
expires_in: Seconds or timedelta until expiration.
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
UTC datetime of expiration, or None if no expiration.
|
|
248
|
+
"""
|
|
249
|
+
if expires_in is None:
|
|
250
|
+
return None
|
|
251
|
+
|
|
252
|
+
expires_in_seconds = int(expires_in.total_seconds()) if isinstance(expires_in, timedelta) else expires_in
|
|
253
|
+
|
|
254
|
+
if expires_in_seconds <= 0:
|
|
255
|
+
return None
|
|
256
|
+
|
|
257
|
+
return datetime.now(timezone.utc) + timedelta(seconds=expires_in_seconds)
|
|
258
|
+
|
|
259
|
+
def _value_to_bytes(self, value: "str | bytes") -> bytes:
|
|
260
|
+
"""Convert value to bytes if needed.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
value: String or bytes value.
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
Value as bytes.
|
|
267
|
+
"""
|
|
268
|
+
if isinstance(value, str):
|
|
269
|
+
return value.encode("utf-8")
|
|
270
|
+
return value
|
|
271
|
+
|
|
272
|
+
@staticmethod
|
|
273
|
+
def _validate_table_name(table_name: str) -> None:
|
|
274
|
+
"""Validate table name for SQL safety.
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
table_name: Table name to validate.
|
|
278
|
+
|
|
279
|
+
Raises:
|
|
280
|
+
ValueError: If table name is invalid.
|
|
281
|
+
|
|
282
|
+
Notes:
|
|
283
|
+
- Must start with letter or underscore
|
|
284
|
+
- Can only contain letters, numbers, and underscores
|
|
285
|
+
- Maximum length is 63 characters (PostgreSQL limit)
|
|
286
|
+
- Prevents SQL injection in table names
|
|
287
|
+
"""
|
|
288
|
+
if not table_name:
|
|
289
|
+
msg = "Table name cannot be empty"
|
|
290
|
+
raise ValueError(msg)
|
|
291
|
+
|
|
292
|
+
if len(table_name) > MAX_TABLE_NAME_LENGTH:
|
|
293
|
+
msg = f"Table name too long: {len(table_name)} chars (max {MAX_TABLE_NAME_LENGTH})"
|
|
294
|
+
raise ValueError(msg)
|
|
295
|
+
|
|
296
|
+
if not VALID_TABLE_NAME_PATTERN.match(table_name):
|
|
297
|
+
msg = f"Invalid table name: {table_name!r}. Must start with letter/underscore and contain only alphanumeric characters and underscores"
|
|
298
|
+
raise ValueError(msg)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Optional helpers for enabling OpenTelemetry spans via ObservabilityConfig."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from sqlspec.observability import ObservabilityConfig, TelemetryConfig
|
|
7
|
+
from sqlspec.typing import trace
|
|
8
|
+
from sqlspec.utils.module_loader import ensure_opentelemetry
|
|
9
|
+
|
|
10
|
+
__all__ = ("enable_tracing",)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _wrap_provider(provider: Any | None) -> Callable[[], Any] | None:
|
|
14
|
+
if provider is None:
|
|
15
|
+
return None
|
|
16
|
+
|
|
17
|
+
def _factory() -> Any:
|
|
18
|
+
return provider
|
|
19
|
+
|
|
20
|
+
return _factory
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def enable_tracing(
|
|
24
|
+
*,
|
|
25
|
+
base_config: ObservabilityConfig | None = None,
|
|
26
|
+
tracer_provider: Any | None = None,
|
|
27
|
+
tracer_provider_factory: Callable[[], Any] | None = None,
|
|
28
|
+
resource_attributes: dict[str, Any] | None = None,
|
|
29
|
+
enable_spans: bool = True,
|
|
30
|
+
) -> ObservabilityConfig:
|
|
31
|
+
"""Return an ObservabilityConfig with OpenTelemetry spans enabled.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
base_config: Existing observability config to extend. When omitted a new instance is created.
|
|
35
|
+
tracer_provider: Optional provider instance to reuse. Mutually exclusive with tracer_provider_factory.
|
|
36
|
+
tracer_provider_factory: Callable that returns a tracer provider when spans are first used.
|
|
37
|
+
resource_attributes: Additional attributes to attach to every span.
|
|
38
|
+
enable_spans: Allow disabling spans while keeping the rest of the config.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
ObservabilityConfig with telemetry options configured for OpenTelemetry.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
ensure_opentelemetry()
|
|
45
|
+
|
|
46
|
+
if tracer_provider is not None and tracer_provider_factory is not None:
|
|
47
|
+
msg = "Provide either tracer_provider or tracer_provider_factory, not both"
|
|
48
|
+
raise ValueError(msg)
|
|
49
|
+
|
|
50
|
+
telemetry = TelemetryConfig(
|
|
51
|
+
enable_spans=enable_spans,
|
|
52
|
+
provider_factory=tracer_provider_factory or _wrap_provider(tracer_provider) or trace.get_tracer_provider,
|
|
53
|
+
resource_attributes=resource_attributes,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
config = base_config.copy() if base_config else ObservabilityConfig()
|
|
57
|
+
config.telemetry = telemetry
|
|
58
|
+
return config
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""Prometheus metrics helpers that integrate with the observability statement observers."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from sqlspec.observability import ObservabilityConfig, StatementEvent, StatementObserver, resolve_db_system
|
|
7
|
+
from sqlspec.typing import Counter, Histogram
|
|
8
|
+
from sqlspec.utils.module_loader import ensure_prometheus
|
|
9
|
+
|
|
10
|
+
__all__ = ("PrometheusStatementObserver", "enable_metrics")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PrometheusStatementObserver:
|
|
14
|
+
"""Statement observer that records Prometheus metrics."""
|
|
15
|
+
|
|
16
|
+
__slots__ = ("_counters", "_duration", "_label_names", "_rows")
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
*,
|
|
21
|
+
namespace: str = "sqlspec",
|
|
22
|
+
subsystem: str = "driver",
|
|
23
|
+
registry: Any | None = None,
|
|
24
|
+
label_names: Iterable[str] = ("db_system", "operation"),
|
|
25
|
+
duration_buckets: tuple[float, ...] | None = None,
|
|
26
|
+
) -> None:
|
|
27
|
+
self._label_names = tuple(label_names)
|
|
28
|
+
self._counters = Counter(
|
|
29
|
+
"query_total",
|
|
30
|
+
"Total SQL statements executed",
|
|
31
|
+
labelnames=self._label_names,
|
|
32
|
+
namespace=namespace,
|
|
33
|
+
subsystem=subsystem,
|
|
34
|
+
registry=registry,
|
|
35
|
+
)
|
|
36
|
+
histogram_kwargs: dict[str, Any] = {}
|
|
37
|
+
if duration_buckets is not None:
|
|
38
|
+
histogram_kwargs["buckets"] = duration_buckets
|
|
39
|
+
|
|
40
|
+
self._duration = Histogram(
|
|
41
|
+
"query_duration_seconds",
|
|
42
|
+
"SQL execution time in seconds",
|
|
43
|
+
labelnames=self._label_names,
|
|
44
|
+
namespace=namespace,
|
|
45
|
+
subsystem=subsystem,
|
|
46
|
+
registry=registry,
|
|
47
|
+
**histogram_kwargs,
|
|
48
|
+
)
|
|
49
|
+
self._rows = Histogram(
|
|
50
|
+
"query_rows",
|
|
51
|
+
"Rows affected per statement",
|
|
52
|
+
labelnames=self._label_names,
|
|
53
|
+
namespace=namespace,
|
|
54
|
+
subsystem=subsystem,
|
|
55
|
+
registry=registry,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def __call__(self, event: StatementEvent) -> None:
|
|
59
|
+
label_values = self._label_values(event)
|
|
60
|
+
self._counters.labels(*label_values).inc()
|
|
61
|
+
self._duration.labels(*label_values).observe(max(event.duration_s, 0.0))
|
|
62
|
+
if event.rows_affected is not None:
|
|
63
|
+
self._rows.labels(*label_values).observe(float(event.rows_affected))
|
|
64
|
+
|
|
65
|
+
def _label_values(self, event: StatementEvent) -> tuple[str, ...]:
|
|
66
|
+
values: list[str] = []
|
|
67
|
+
payload = event.as_dict()
|
|
68
|
+
for name in self._label_names:
|
|
69
|
+
if name == "db_system":
|
|
70
|
+
db_system = event.db_system
|
|
71
|
+
if db_system is None:
|
|
72
|
+
db_system = resolve_db_system(event.adapter)
|
|
73
|
+
values.append(db_system)
|
|
74
|
+
elif name == "driver":
|
|
75
|
+
values.append(event.driver)
|
|
76
|
+
elif name == "operation":
|
|
77
|
+
values.append(event.operation or "EXECUTE")
|
|
78
|
+
elif name == "adapter":
|
|
79
|
+
values.append(event.adapter)
|
|
80
|
+
elif name == "bind_key":
|
|
81
|
+
values.append(event.bind_key or "default")
|
|
82
|
+
else:
|
|
83
|
+
value = payload.get(name)
|
|
84
|
+
values.append("" if value is None else str(value))
|
|
85
|
+
return tuple(values)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def enable_metrics(
|
|
89
|
+
*,
|
|
90
|
+
base_config: ObservabilityConfig | None = None,
|
|
91
|
+
namespace: str = "sqlspec",
|
|
92
|
+
subsystem: str = "driver",
|
|
93
|
+
registry: Any | None = None,
|
|
94
|
+
label_names: Iterable[str] = ("db_system", "operation"),
|
|
95
|
+
duration_buckets: tuple[float, ...] | None = None,
|
|
96
|
+
) -> ObservabilityConfig:
|
|
97
|
+
"""Attach a Prometheus-backed statement observer to the provided config."""
|
|
98
|
+
|
|
99
|
+
ensure_prometheus()
|
|
100
|
+
|
|
101
|
+
observer: StatementObserver = PrometheusStatementObserver(
|
|
102
|
+
namespace=namespace,
|
|
103
|
+
subsystem=subsystem,
|
|
104
|
+
registry=registry,
|
|
105
|
+
label_names=label_names,
|
|
106
|
+
duration_buckets=duration_buckets,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
config = base_config.copy() if base_config else ObservabilityConfig()
|
|
110
|
+
existing: list[StatementObserver] = list(config.statement_observers or ())
|
|
111
|
+
existing.append(observer)
|
|
112
|
+
config.statement_observers = tuple(existing)
|
|
113
|
+
return config
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Sanic extension for SQLSpec.
|
|
2
|
+
|
|
3
|
+
Provides Sanic-native app and request context helpers plus plugin wiring for
|
|
4
|
+
connection lifecycle and request-scoped sessions.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from sqlspec.extensions.sanic._state import SanicConfigState
|
|
8
|
+
from sqlspec.extensions.sanic._utils import get_connection_from_request, get_or_create_session
|
|
9
|
+
from sqlspec.extensions.sanic.extension import SQLSpecPlugin
|
|
10
|
+
from sqlspec.service import SQLSpecAsyncService, SQLSpecSyncService
|
|
11
|
+
|
|
12
|
+
__all__ = (
|
|
13
|
+
"SQLSpecAsyncService",
|
|
14
|
+
"SQLSpecPlugin",
|
|
15
|
+
"SQLSpecSyncService",
|
|
16
|
+
"SanicConfigState",
|
|
17
|
+
"get_connection_from_request",
|
|
18
|
+
"get_or_create_session",
|
|
19
|
+
)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
3
|
+
|
|
4
|
+
from sqlspec.exceptions import ImproperConfigurationError
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from sqlspec.config import DatabaseConfigProtocol
|
|
8
|
+
|
|
9
|
+
__all__ = ("CommitMode", "SanicConfigState")
|
|
10
|
+
|
|
11
|
+
CommitMode = Literal["manual", "autocommit", "autocommit_include_redirect"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class SanicConfigState:
|
|
16
|
+
"""Internal state for a Sanic database configuration.
|
|
17
|
+
|
|
18
|
+
Tracks the keys and behavior needed to bind one SQLSpec config into a
|
|
19
|
+
Sanic app and its request context.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
config: "DatabaseConfigProtocol[Any, Any, Any]"
|
|
23
|
+
connection_key: str
|
|
24
|
+
pool_key: str
|
|
25
|
+
session_key: str
|
|
26
|
+
commit_mode: CommitMode
|
|
27
|
+
extra_commit_statuses: "set[int] | None"
|
|
28
|
+
extra_rollback_statuses: "set[int] | None"
|
|
29
|
+
disable_di: bool
|
|
30
|
+
enable_correlation_middleware: bool = False
|
|
31
|
+
correlation_header: str = "x-request-id"
|
|
32
|
+
correlation_headers: "tuple[str, ...] | None" = None
|
|
33
|
+
auto_trace_headers: bool = True
|
|
34
|
+
enable_sqlcommenter_middleware: bool = True
|
|
35
|
+
sqlcommenter_framework: str = "sanic"
|
|
36
|
+
|
|
37
|
+
def __post_init__(self) -> None:
|
|
38
|
+
"""Validate status configuration."""
|
|
39
|
+
extra_commit_statuses = self.extra_commit_statuses or set()
|
|
40
|
+
extra_rollback_statuses = self.extra_rollback_statuses or set()
|
|
41
|
+
if extra_commit_statuses & extra_rollback_statuses:
|
|
42
|
+
msg = "Extra rollback statuses and commit statuses must not share any status codes"
|
|
43
|
+
raise ImproperConfigurationError(msg)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any
|
|
2
|
+
|
|
3
|
+
from sqlspec.exceptions import ImproperConfigurationError
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from sqlspec.extensions.sanic._state import SanicConfigState
|
|
7
|
+
|
|
8
|
+
__all__ = (
|
|
9
|
+
"get_connection_from_request",
|
|
10
|
+
"get_context_value",
|
|
11
|
+
"get_or_create_session",
|
|
12
|
+
"has_context_value",
|
|
13
|
+
"pop_context_value",
|
|
14
|
+
"set_context_value",
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
_MISSING = object()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_context_value(context: Any, key: str, default: Any = _MISSING) -> Any:
|
|
21
|
+
"""Get a value from a Sanic ``ctx`` object.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
context: Sanic ``app.ctx`` or ``request.ctx`` object.
|
|
25
|
+
key: Attribute name to retrieve.
|
|
26
|
+
default: Optional value returned when the key is missing.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
Stored context value.
|
|
30
|
+
"""
|
|
31
|
+
if default is _MISSING:
|
|
32
|
+
return getattr(context, key)
|
|
33
|
+
return getattr(context, key, default)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def set_context_value(context: Any, key: str, value: Any) -> None:
|
|
37
|
+
"""Set a value on a Sanic ``ctx`` object.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
context: Sanic ``app.ctx`` or ``request.ctx`` object.
|
|
41
|
+
key: Attribute name to set.
|
|
42
|
+
value: Value to store.
|
|
43
|
+
"""
|
|
44
|
+
setattr(context, key, value)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def pop_context_value(context: Any, key: str) -> Any | None:
|
|
48
|
+
"""Remove a value from a Sanic ``ctx`` object.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
context: Sanic ``app.ctx`` or ``request.ctx`` object.
|
|
52
|
+
key: Attribute name to remove.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
Removed value if present, otherwise ``None``.
|
|
56
|
+
"""
|
|
57
|
+
if not hasattr(context, key):
|
|
58
|
+
return None
|
|
59
|
+
value = getattr(context, key)
|
|
60
|
+
delattr(context, key)
|
|
61
|
+
return value
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def has_context_value(context: Any, key: str) -> bool:
|
|
65
|
+
"""Check if a Sanic ``ctx`` object has a stored value.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
context: Sanic ``app.ctx`` or ``request.ctx`` object.
|
|
69
|
+
key: Attribute name to check.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
``True`` when the key is present.
|
|
73
|
+
"""
|
|
74
|
+
return hasattr(context, key)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def get_connection_from_request(request: Any, config_state: "SanicConfigState") -> Any:
|
|
78
|
+
"""Get database connection from request context.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
request: Sanic request instance.
|
|
82
|
+
config_state: Configuration state for the database.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Database connection object.
|
|
86
|
+
|
|
87
|
+
Raises:
|
|
88
|
+
ImproperConfigurationError: If SQLSpec request middleware has not stored a connection.
|
|
89
|
+
"""
|
|
90
|
+
try:
|
|
91
|
+
return get_context_value(request.ctx, config_state.connection_key)
|
|
92
|
+
except AttributeError as exc:
|
|
93
|
+
msg = (
|
|
94
|
+
f"Sanic request context does not contain SQLSpec connection '{config_state.connection_key}'. "
|
|
95
|
+
"Ensure SQLSpecPlugin is initialized and its request middleware runs before accessing sessions."
|
|
96
|
+
)
|
|
97
|
+
raise ImproperConfigurationError(msg) from exc
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_or_create_session(request: Any, config_state: "SanicConfigState") -> Any:
|
|
101
|
+
"""Get or create database session for request.
|
|
102
|
+
|
|
103
|
+
Sessions are cached per request to return the same session instance across
|
|
104
|
+
multiple calls in one request.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
request: Sanic request instance.
|
|
108
|
+
config_state: Configuration state for the database.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Database session driver instance.
|
|
112
|
+
"""
|
|
113
|
+
session_instance_key = f"{config_state.session_key}_instance"
|
|
114
|
+
|
|
115
|
+
existing_session = get_context_value(request.ctx, session_instance_key, None)
|
|
116
|
+
if existing_session is not None:
|
|
117
|
+
return existing_session
|
|
118
|
+
|
|
119
|
+
connection = get_connection_from_request(request, config_state)
|
|
120
|
+
session = config_state.config.driver_type(
|
|
121
|
+
connection=connection,
|
|
122
|
+
statement_config=config_state.config.statement_config,
|
|
123
|
+
driver_features=config_state.config.driver_features,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
set_context_value(request.ctx, session_instance_key, session)
|
|
127
|
+
return session
|