sqlspec 0.36.0__cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ac8f31065839703b4e70__mypyc.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/__init__.py +140 -0
- sqlspec/__main__.py +12 -0
- sqlspec/__metadata__.py +14 -0
- sqlspec/_serialization.py +315 -0
- sqlspec/_typing.py +700 -0
- sqlspec/adapters/__init__.py +0 -0
- sqlspec/adapters/adbc/__init__.py +5 -0
- sqlspec/adapters/adbc/_typing.py +82 -0
- sqlspec/adapters/adbc/adk/__init__.py +5 -0
- sqlspec/adapters/adbc/adk/store.py +1273 -0
- sqlspec/adapters/adbc/config.py +295 -0
- sqlspec/adapters/adbc/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/adbc/core.py +735 -0
- sqlspec/adapters/adbc/data_dictionary.py +334 -0
- sqlspec/adapters/adbc/driver.py +529 -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 +502 -0
- sqlspec/adapters/adbc/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/adbc/type_converter.py +140 -0
- sqlspec/adapters/aiosqlite/__init__.py +25 -0
- sqlspec/adapters/aiosqlite/_typing.py +82 -0
- sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/adk/store.py +818 -0
- sqlspec/adapters/aiosqlite/config.py +334 -0
- sqlspec/adapters/aiosqlite/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/aiosqlite/core.py +315 -0
- sqlspec/adapters/aiosqlite/data_dictionary.py +208 -0
- sqlspec/adapters/aiosqlite/driver.py +313 -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.py +533 -0
- sqlspec/adapters/asyncmy/__init__.py +21 -0
- sqlspec/adapters/asyncmy/_typing.py +87 -0
- sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
- sqlspec/adapters/asyncmy/adk/store.py +703 -0
- sqlspec/adapters/asyncmy/config.py +302 -0
- sqlspec/adapters/asyncmy/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/asyncmy/core.py +360 -0
- sqlspec/adapters/asyncmy/data_dictionary.py +124 -0
- sqlspec/adapters/asyncmy/driver.py +383 -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 +19 -0
- sqlspec/adapters/asyncpg/_typing.py +88 -0
- sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
- sqlspec/adapters/asyncpg/adk/store.py +748 -0
- sqlspec/adapters/asyncpg/config.py +569 -0
- sqlspec/adapters/asyncpg/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/asyncpg/core.py +367 -0
- sqlspec/adapters/asyncpg/data_dictionary.py +162 -0
- sqlspec/adapters/asyncpg/driver.py +487 -0
- sqlspec/adapters/asyncpg/events/__init__.py +6 -0
- sqlspec/adapters/asyncpg/events/backend.py +286 -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 +14 -0
- sqlspec/adapters/bigquery/_typing.py +86 -0
- sqlspec/adapters/bigquery/adk/__init__.py +5 -0
- sqlspec/adapters/bigquery/adk/store.py +827 -0
- sqlspec/adapters/bigquery/config.py +353 -0
- sqlspec/adapters/bigquery/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/bigquery/core.py +715 -0
- sqlspec/adapters/bigquery/data_dictionary.py +128 -0
- sqlspec/adapters/bigquery/driver.py +548 -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.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/bigquery/type_converter.py +107 -0
- sqlspec/adapters/cockroach_asyncpg/__init__.py +24 -0
- sqlspec/adapters/cockroach_asyncpg/_typing.py +72 -0
- sqlspec/adapters/cockroach_asyncpg/adk/__init__.py +3 -0
- sqlspec/adapters/cockroach_asyncpg/adk/store.py +410 -0
- sqlspec/adapters/cockroach_asyncpg/config.py +238 -0
- sqlspec/adapters/cockroach_asyncpg/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/cockroach_asyncpg/core.py +55 -0
- sqlspec/adapters/cockroach_asyncpg/data_dictionary.py +107 -0
- sqlspec/adapters/cockroach_asyncpg/driver.py +144 -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 +38 -0
- sqlspec/adapters/cockroach_psycopg/_typing.py +129 -0
- sqlspec/adapters/cockroach_psycopg/adk/__init__.py +13 -0
- sqlspec/adapters/cockroach_psycopg/adk/store.py +868 -0
- sqlspec/adapters/cockroach_psycopg/config.py +484 -0
- sqlspec/adapters/cockroach_psycopg/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/cockroach_psycopg/core.py +63 -0
- sqlspec/adapters/cockroach_psycopg/data_dictionary.py +215 -0
- sqlspec/adapters/cockroach_psycopg/driver.py +284 -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 +325 -0
- sqlspec/adapters/duckdb/__init__.py +25 -0
- sqlspec/adapters/duckdb/_typing.py +81 -0
- sqlspec/adapters/duckdb/adk/__init__.py +14 -0
- sqlspec/adapters/duckdb/adk/store.py +850 -0
- sqlspec/adapters/duckdb/config.py +463 -0
- sqlspec/adapters/duckdb/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/duckdb/core.py +257 -0
- sqlspec/adapters/duckdb/data_dictionary.py +140 -0
- sqlspec/adapters/duckdb/driver.py +430 -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.py +293 -0
- sqlspec/adapters/duckdb/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/duckdb/type_converter.py +118 -0
- sqlspec/adapters/mock/__init__.py +72 -0
- sqlspec/adapters/mock/_typing.py +147 -0
- sqlspec/adapters/mock/config.py +483 -0
- sqlspec/adapters/mock/core.py +319 -0
- sqlspec/adapters/mock/data_dictionary.py +366 -0
- sqlspec/adapters/mock/driver.py +721 -0
- sqlspec/adapters/mysqlconnector/__init__.py +36 -0
- sqlspec/adapters/mysqlconnector/_typing.py +141 -0
- sqlspec/adapters/mysqlconnector/adk/__init__.py +15 -0
- sqlspec/adapters/mysqlconnector/adk/store.py +1060 -0
- sqlspec/adapters/mysqlconnector/config.py +394 -0
- sqlspec/adapters/mysqlconnector/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/mysqlconnector/core.py +303 -0
- sqlspec/adapters/mysqlconnector/data_dictionary.py +235 -0
- sqlspec/adapters/mysqlconnector/driver.py +483 -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 +60 -0
- sqlspec/adapters/oracledb/_numpy_handlers.py +141 -0
- sqlspec/adapters/oracledb/_typing.py +182 -0
- sqlspec/adapters/oracledb/_uuid_handlers.py +166 -0
- sqlspec/adapters/oracledb/adk/__init__.py +10 -0
- sqlspec/adapters/oracledb/adk/store.py +2369 -0
- sqlspec/adapters/oracledb/config.py +550 -0
- sqlspec/adapters/oracledb/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/oracledb/core.py +543 -0
- sqlspec/adapters/oracledb/data_dictionary.py +536 -0
- sqlspec/adapters/oracledb/driver.py +1229 -0
- sqlspec/adapters/oracledb/events/__init__.py +16 -0
- sqlspec/adapters/oracledb/events/backend.py +347 -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 +535 -0
- sqlspec/adapters/oracledb/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/oracledb/type_converter.py +211 -0
- sqlspec/adapters/psqlpy/__init__.py +17 -0
- sqlspec/adapters/psqlpy/_typing.py +79 -0
- sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
- sqlspec/adapters/psqlpy/adk/store.py +766 -0
- sqlspec/adapters/psqlpy/config.py +304 -0
- sqlspec/adapters/psqlpy/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/psqlpy/core.py +480 -0
- sqlspec/adapters/psqlpy/data_dictionary.py +126 -0
- sqlspec/adapters/psqlpy/driver.py +438 -0
- sqlspec/adapters/psqlpy/events/__init__.py +6 -0
- sqlspec/adapters/psqlpy/events/backend.py +310 -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.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/psqlpy/type_converter.py +113 -0
- sqlspec/adapters/psycopg/__init__.py +32 -0
- sqlspec/adapters/psycopg/_typing.py +164 -0
- sqlspec/adapters/psycopg/adk/__init__.py +10 -0
- sqlspec/adapters/psycopg/adk/store.py +1387 -0
- sqlspec/adapters/psycopg/config.py +576 -0
- sqlspec/adapters/psycopg/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/psycopg/core.py +450 -0
- sqlspec/adapters/psycopg/data_dictionary.py +289 -0
- sqlspec/adapters/psycopg/driver.py +975 -0
- sqlspec/adapters/psycopg/events/__init__.py +20 -0
- sqlspec/adapters/psycopg/events/backend.py +458 -0
- sqlspec/adapters/psycopg/events/store.py +42 -0
- sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
- sqlspec/adapters/psycopg/litestar/store.py +552 -0
- sqlspec/adapters/psycopg/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/psycopg/type_converter.py +93 -0
- sqlspec/adapters/pymysql/__init__.py +21 -0
- sqlspec/adapters/pymysql/_typing.py +71 -0
- sqlspec/adapters/pymysql/adk/__init__.py +5 -0
- sqlspec/adapters/pymysql/adk/store.py +540 -0
- sqlspec/adapters/pymysql/config.py +195 -0
- sqlspec/adapters/pymysql/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/pymysql/core.py +299 -0
- sqlspec/adapters/pymysql/data_dictionary.py +122 -0
- sqlspec/adapters/pymysql/driver.py +259 -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.py +137 -0
- sqlspec/adapters/spanner/__init__.py +40 -0
- sqlspec/adapters/spanner/_typing.py +86 -0
- sqlspec/adapters/spanner/adk/__init__.py +5 -0
- sqlspec/adapters/spanner/adk/store.py +732 -0
- sqlspec/adapters/spanner/config.py +352 -0
- sqlspec/adapters/spanner/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/spanner/core.py +188 -0
- sqlspec/adapters/spanner/data_dictionary.py +120 -0
- sqlspec/adapters/spanner/dialect/__init__.py +6 -0
- sqlspec/adapters/spanner/dialect/_spangres.py +57 -0
- sqlspec/adapters/spanner/dialect/_spanner.py +130 -0
- sqlspec/adapters/spanner/driver.py +373 -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.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/spanner/type_converter.py +331 -0
- sqlspec/adapters/sqlite/__init__.py +19 -0
- sqlspec/adapters/sqlite/_typing.py +80 -0
- sqlspec/adapters/sqlite/adk/__init__.py +5 -0
- sqlspec/adapters/sqlite/adk/store.py +958 -0
- sqlspec/adapters/sqlite/config.py +280 -0
- sqlspec/adapters/sqlite/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/sqlite/core.py +312 -0
- sqlspec/adapters/sqlite/data_dictionary.py +202 -0
- sqlspec/adapters/sqlite/driver.py +359 -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.py +198 -0
- sqlspec/adapters/sqlite/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/sqlite/type_converter.py +114 -0
- sqlspec/base.py +747 -0
- sqlspec/builder/__init__.py +179 -0
- sqlspec/builder/_base.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_base.py +1022 -0
- sqlspec/builder/_column.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_column.py +521 -0
- sqlspec/builder/_ddl.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_ddl.py +1642 -0
- sqlspec/builder/_delete.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_delete.py +95 -0
- sqlspec/builder/_dml.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_dml.py +365 -0
- sqlspec/builder/_explain.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_explain.py +579 -0
- sqlspec/builder/_expression_wrappers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_expression_wrappers.py +46 -0
- sqlspec/builder/_factory.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_factory.py +1697 -0
- sqlspec/builder/_insert.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_insert.py +328 -0
- sqlspec/builder/_join.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_join.py +499 -0
- sqlspec/builder/_merge.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_merge.py +821 -0
- sqlspec/builder/_parsing_utils.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_parsing_utils.py +297 -0
- sqlspec/builder/_select.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_select.py +1660 -0
- sqlspec/builder/_temporal.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_temporal.py +139 -0
- sqlspec/builder/_update.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_update.py +173 -0
- sqlspec/builder/_vector_expressions.py +267 -0
- sqlspec/cli.py +911 -0
- sqlspec/config.py +1755 -0
- sqlspec/core/__init__.py +374 -0
- sqlspec/core/_correlation.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/_correlation.py +176 -0
- sqlspec/core/cache.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/cache.py +1069 -0
- sqlspec/core/compiler.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/compiler.py +954 -0
- sqlspec/core/explain.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/explain.py +275 -0
- sqlspec/core/filters.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/filters.py +952 -0
- sqlspec/core/hashing.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/hashing.py +262 -0
- sqlspec/core/metrics.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/metrics.py +83 -0
- sqlspec/core/parameters/__init__.py +71 -0
- sqlspec/core/parameters/_alignment.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_alignment.py +270 -0
- sqlspec/core/parameters/_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_converter.py +543 -0
- sqlspec/core/parameters/_processor.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_processor.py +505 -0
- sqlspec/core/parameters/_registry.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_registry.py +206 -0
- sqlspec/core/parameters/_transformers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_transformers.py +292 -0
- sqlspec/core/parameters/_types.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_types.py +499 -0
- sqlspec/core/parameters/_validator.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_validator.py +180 -0
- sqlspec/core/pipeline.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/pipeline.py +319 -0
- sqlspec/core/query_modifiers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/query_modifiers.py +437 -0
- sqlspec/core/result/__init__.py +23 -0
- sqlspec/core/result/_base.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/result/_base.py +1121 -0
- sqlspec/core/result/_io.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/result/_io.py +28 -0
- sqlspec/core/splitter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/splitter.py +966 -0
- sqlspec/core/stack.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/stack.py +163 -0
- sqlspec/core/statement.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/statement.py +1503 -0
- sqlspec/core/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/type_converter.py +339 -0
- sqlspec/data_dictionary/__init__.py +22 -0
- sqlspec/data_dictionary/_loader.py +123 -0
- sqlspec/data_dictionary/_registry.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/_registry.py +74 -0
- sqlspec/data_dictionary/_types.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/_types.py +121 -0
- sqlspec/data_dictionary/dialects/__init__.py +21 -0
- sqlspec/data_dictionary/dialects/bigquery.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/bigquery.py +49 -0
- sqlspec/data_dictionary/dialects/cockroachdb.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/cockroachdb.py +43 -0
- sqlspec/data_dictionary/dialects/duckdb.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/duckdb.py +47 -0
- sqlspec/data_dictionary/dialects/mysql.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/mysql.py +42 -0
- sqlspec/data_dictionary/dialects/oracle.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/oracle.py +34 -0
- sqlspec/data_dictionary/dialects/postgres.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/postgres.py +46 -0
- sqlspec/data_dictionary/dialects/spanner.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/spanner.py +37 -0
- sqlspec/data_dictionary/dialects/sqlite.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/sqlite.py +42 -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/driver/__init__.py +32 -0
- sqlspec/driver/_async.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_async.py +1737 -0
- sqlspec/driver/_common.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_common.py +1478 -0
- sqlspec/driver/_sql_helpers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_sql_helpers.py +148 -0
- sqlspec/driver/_storage_helpers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_storage_helpers.py +144 -0
- sqlspec/driver/_sync.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_sync.py +1710 -0
- sqlspec/exceptions.py +338 -0
- sqlspec/extensions/__init__.py +0 -0
- sqlspec/extensions/adk/__init__.py +70 -0
- sqlspec/extensions/adk/_types.py +51 -0
- sqlspec/extensions/adk/converters.py +172 -0
- sqlspec/extensions/adk/memory/__init__.py +69 -0
- sqlspec/extensions/adk/memory/_types.py +30 -0
- sqlspec/extensions/adk/memory/converters.py +149 -0
- sqlspec/extensions/adk/memory/service.py +217 -0
- sqlspec/extensions/adk/memory/store.py +569 -0
- sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +246 -0
- sqlspec/extensions/adk/migrations/__init__.py +0 -0
- sqlspec/extensions/adk/service.py +225 -0
- sqlspec/extensions/adk/store.py +567 -0
- sqlspec/extensions/events/__init__.py +51 -0
- sqlspec/extensions/events/_channel.py +703 -0
- sqlspec/extensions/events/_hints.py +45 -0
- sqlspec/extensions/events/_models.py +23 -0
- sqlspec/extensions/events/_payload.py +69 -0
- sqlspec/extensions/events/_protocols.py +134 -0
- sqlspec/extensions/events/_queue.py +461 -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 +19 -0
- sqlspec/extensions/fastapi/extension.py +351 -0
- sqlspec/extensions/fastapi/providers.py +607 -0
- sqlspec/extensions/flask/__init__.py +37 -0
- sqlspec/extensions/flask/_state.py +76 -0
- sqlspec/extensions/flask/_utils.py +71 -0
- sqlspec/extensions/flask/extension.py +519 -0
- sqlspec/extensions/litestar/__init__.py +28 -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 +671 -0
- sqlspec/extensions/litestar/providers.py +526 -0
- sqlspec/extensions/litestar/store.py +296 -0
- sqlspec/extensions/otel/__init__.py +58 -0
- sqlspec/extensions/prometheus/__init__.py +113 -0
- sqlspec/extensions/starlette/__init__.py +19 -0
- sqlspec/extensions/starlette/_state.py +30 -0
- sqlspec/extensions/starlette/_utils.py +96 -0
- sqlspec/extensions/starlette/extension.py +346 -0
- sqlspec/extensions/starlette/middleware.py +235 -0
- sqlspec/loader.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/loader.py +702 -0
- sqlspec/migrations/__init__.py +36 -0
- sqlspec/migrations/base.py +731 -0
- sqlspec/migrations/commands.py +1232 -0
- sqlspec/migrations/context.py +157 -0
- sqlspec/migrations/fix.py +204 -0
- sqlspec/migrations/loaders.py +443 -0
- sqlspec/migrations/runner.py +1172 -0
- sqlspec/migrations/templates.py +234 -0
- sqlspec/migrations/tracker.py +611 -0
- sqlspec/migrations/utils.py +256 -0
- sqlspec/migrations/validation.py +207 -0
- sqlspec/migrations/version.py +446 -0
- sqlspec/observability/__init__.py +55 -0
- sqlspec/observability/_common.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_common.py +77 -0
- sqlspec/observability/_config.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_config.py +348 -0
- sqlspec/observability/_diagnostics.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_diagnostics.py +74 -0
- sqlspec/observability/_dispatcher.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_dispatcher.py +152 -0
- sqlspec/observability/_formatters/__init__.py +13 -0
- sqlspec/observability/_formatters/_aws.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_formatters/_aws.py +102 -0
- sqlspec/observability/_formatters/_azure.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_formatters/_azure.py +96 -0
- sqlspec/observability/_formatters/_base.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_formatters/_base.py +57 -0
- sqlspec/observability/_formatters/_gcp.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_formatters/_gcp.py +131 -0
- sqlspec/observability/_formatting.py +58 -0
- sqlspec/observability/_observer.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_observer.py +357 -0
- sqlspec/observability/_runtime.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_runtime.py +420 -0
- sqlspec/observability/_sampling.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_sampling.py +188 -0
- sqlspec/observability/_spans.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_spans.py +161 -0
- sqlspec/protocols.py +916 -0
- sqlspec/py.typed +0 -0
- sqlspec/storage/__init__.py +48 -0
- sqlspec/storage/_utils.py +104 -0
- sqlspec/storage/backends/__init__.py +1 -0
- sqlspec/storage/backends/base.py +253 -0
- sqlspec/storage/backends/fsspec.py +529 -0
- sqlspec/storage/backends/local.py +441 -0
- sqlspec/storage/backends/obstore.py +916 -0
- sqlspec/storage/errors.py +104 -0
- sqlspec/storage/pipeline.py +582 -0
- sqlspec/storage/registry.py +301 -0
- sqlspec/typing.py +395 -0
- sqlspec/utils/__init__.py +7 -0
- sqlspec/utils/arrow_helpers.py +318 -0
- sqlspec/utils/config_tools.py +332 -0
- sqlspec/utils/correlation.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/correlation.py +134 -0
- sqlspec/utils/deprecation.py +190 -0
- sqlspec/utils/fixtures.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/fixtures.py +258 -0
- sqlspec/utils/logging.py +222 -0
- sqlspec/utils/module_loader.py +306 -0
- sqlspec/utils/portal.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/portal.py +375 -0
- sqlspec/utils/schema.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/schema.py +485 -0
- sqlspec/utils/serializers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/serializers.py +408 -0
- sqlspec/utils/singleton.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/singleton.py +41 -0
- sqlspec/utils/sync_tools.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/sync_tools.py +311 -0
- sqlspec/utils/text.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/text.py +108 -0
- sqlspec/utils/type_converters.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/type_converters.py +128 -0
- sqlspec/utils/type_guards.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/type_guards.py +1360 -0
- sqlspec/utils/uuids.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/uuids.py +225 -0
- sqlspec-0.36.0.dist-info/METADATA +205 -0
- sqlspec-0.36.0.dist-info/RECORD +531 -0
- sqlspec-0.36.0.dist-info/WHEEL +7 -0
- sqlspec-0.36.0.dist-info/entry_points.txt +2 -0
- sqlspec-0.36.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
"""Application dependency providers for FastAPI filter injection.
|
|
2
|
+
|
|
3
|
+
This module provides filter dependency injection for FastAPI routes, allowing
|
|
4
|
+
automatic parsing of query parameters into SQLSpec filter objects.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import datetime
|
|
8
|
+
import inspect
|
|
9
|
+
from typing import TYPE_CHECKING, Annotated, Any, Literal, NamedTuple
|
|
10
|
+
from uuid import UUID
|
|
11
|
+
|
|
12
|
+
from fastapi import Depends, Query
|
|
13
|
+
from fastapi.exceptions import RequestValidationError
|
|
14
|
+
from typing_extensions import NotRequired, TypedDict
|
|
15
|
+
|
|
16
|
+
from sqlspec.core import (
|
|
17
|
+
BeforeAfterFilter,
|
|
18
|
+
FilterTypes,
|
|
19
|
+
InCollectionFilter,
|
|
20
|
+
LimitOffsetFilter,
|
|
21
|
+
NotInCollectionFilter,
|
|
22
|
+
NotNullFilter,
|
|
23
|
+
NullFilter,
|
|
24
|
+
OrderByFilter,
|
|
25
|
+
SearchFilter,
|
|
26
|
+
)
|
|
27
|
+
from sqlspec.utils.singleton import SingletonMeta
|
|
28
|
+
from sqlspec.utils.text import camelize
|
|
29
|
+
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
from collections.abc import Callable
|
|
32
|
+
|
|
33
|
+
__all__ = (
|
|
34
|
+
"DEPENDENCY_DEFAULTS",
|
|
35
|
+
"BooleanOrNone",
|
|
36
|
+
"DTorNone",
|
|
37
|
+
"DependencyDefaults",
|
|
38
|
+
"FieldNameType",
|
|
39
|
+
"FilterConfig",
|
|
40
|
+
"HashableType",
|
|
41
|
+
"HashableValue",
|
|
42
|
+
"IntOrNone",
|
|
43
|
+
"SortOrder",
|
|
44
|
+
"SortOrderOrNone",
|
|
45
|
+
"StringOrNone",
|
|
46
|
+
"UuidOrNone",
|
|
47
|
+
"dep_cache",
|
|
48
|
+
"provide_filters",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
DTorNone = datetime.datetime | None
|
|
52
|
+
StringOrNone = str | None
|
|
53
|
+
UuidOrNone = UUID | None
|
|
54
|
+
IntOrNone = int | None
|
|
55
|
+
BooleanOrNone = bool | None
|
|
56
|
+
SortOrder = Literal["asc", "desc"]
|
|
57
|
+
SortOrderOrNone = SortOrder | None
|
|
58
|
+
HashableValue = str | int | float | bool | None
|
|
59
|
+
HashableType = HashableValue | tuple[Any, ...] | tuple[tuple[str, Any], ...] | tuple[HashableValue, ...]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class DependencyDefaults:
|
|
63
|
+
"""Default values for dependency generation."""
|
|
64
|
+
|
|
65
|
+
CREATED_FILTER_DEPENDENCY_KEY: str = "created_filter"
|
|
66
|
+
ID_FILTER_DEPENDENCY_KEY: str = "id_filter"
|
|
67
|
+
LIMIT_OFFSET_FILTER_DEPENDENCY_KEY: str = "limit_offset_filter"
|
|
68
|
+
UPDATED_FILTER_DEPENDENCY_KEY: str = "updated_filter"
|
|
69
|
+
ORDER_BY_FILTER_DEPENDENCY_KEY: str = "order_by_filter"
|
|
70
|
+
SEARCH_FILTER_DEPENDENCY_KEY: str = "search_filter"
|
|
71
|
+
DEFAULT_PAGINATION_SIZE: int = 20
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
DEPENDENCY_DEFAULTS = DependencyDefaults()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class FieldNameType(NamedTuple):
|
|
78
|
+
"""Type for field name and associated type information for filter configuration."""
|
|
79
|
+
|
|
80
|
+
name: str
|
|
81
|
+
"""Name of the field to filter on."""
|
|
82
|
+
type_hint: type[Any] = str
|
|
83
|
+
"""Type of the filter value. Defaults to str."""
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class FilterConfig(TypedDict):
|
|
87
|
+
"""Configuration for generating dynamic filters for FastAPI."""
|
|
88
|
+
|
|
89
|
+
id_filter: NotRequired[type[UUID | int | str]]
|
|
90
|
+
"""Type of ID filter to enable (UUID, int, or str). When set, enables collection filtering by IDs."""
|
|
91
|
+
id_field: NotRequired[str]
|
|
92
|
+
"""Field name for ID filtering. Defaults to 'id'."""
|
|
93
|
+
sort_field: NotRequired[str | set[str]]
|
|
94
|
+
"""Default field(s) to use for sorting."""
|
|
95
|
+
sort_order: NotRequired[SortOrder]
|
|
96
|
+
"""Default sort order ('asc' or 'desc'). Defaults to 'desc'."""
|
|
97
|
+
pagination_type: NotRequired[Literal["limit_offset"]]
|
|
98
|
+
"""When set to 'limit_offset', enables pagination with page size and current page parameters."""
|
|
99
|
+
pagination_size: NotRequired[int]
|
|
100
|
+
"""Default pagination page size. Defaults to DEFAULT_PAGINATION_SIZE (20)."""
|
|
101
|
+
search: NotRequired[str | set[str]]
|
|
102
|
+
"""Field(s) to enable search filtering on. Can be comma-separated string or set of field names."""
|
|
103
|
+
search_ignore_case: NotRequired[bool]
|
|
104
|
+
"""When True, search is case-insensitive. Defaults to False."""
|
|
105
|
+
created_at: NotRequired[bool]
|
|
106
|
+
"""When True, enables created_at date range filtering. Uses 'created_at' field by default."""
|
|
107
|
+
updated_at: NotRequired[bool]
|
|
108
|
+
"""When True, enables updated_at date range filtering. Uses 'updated_at' field by default."""
|
|
109
|
+
not_in_fields: NotRequired[FieldNameType | set[FieldNameType]]
|
|
110
|
+
"""Fields that support not-in collection filtering. Can be single field or set of fields with type info."""
|
|
111
|
+
in_fields: NotRequired[FieldNameType | set[FieldNameType]]
|
|
112
|
+
"""Fields that support in-collection filtering. Can be single field or set of fields with type info."""
|
|
113
|
+
null_fields: NotRequired[str | set[str]]
|
|
114
|
+
"""Fields that support IS NULL filtering. Can be single field name or set of field names."""
|
|
115
|
+
not_null_fields: NotRequired[str | set[str]]
|
|
116
|
+
"""Fields that support IS NOT NULL filtering. Can be single field name or set of field names."""
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class DependencyCache(metaclass=SingletonMeta):
|
|
120
|
+
"""Simple dependency cache to memoize dynamically generated dependencies."""
|
|
121
|
+
|
|
122
|
+
def __init__(self) -> None:
|
|
123
|
+
self.dependencies: dict[int, Callable[..., list[FilterTypes]]] = {}
|
|
124
|
+
|
|
125
|
+
def add_dependencies(self, key: int, dependencies: "Callable[..., list[FilterTypes]]") -> None:
|
|
126
|
+
"""Add dependencies to cache.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
key: Cache key (hash of config).
|
|
130
|
+
dependencies: Dependency callable to cache.
|
|
131
|
+
"""
|
|
132
|
+
self.dependencies[key] = dependencies
|
|
133
|
+
|
|
134
|
+
def get_dependencies(self, key: int) -> "Callable[..., list[FilterTypes]] | None":
|
|
135
|
+
"""Get dependencies from cache.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
key: Cache key (hash of config).
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
Cached dependency callable or None if not found.
|
|
142
|
+
"""
|
|
143
|
+
return self.dependencies.get(key)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
dep_cache = DependencyCache()
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _empty_filter_list() -> "list[FilterTypes]":
|
|
150
|
+
return []
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def provide_filters(
|
|
154
|
+
config: FilterConfig, dep_defaults: DependencyDefaults = DEPENDENCY_DEFAULTS
|
|
155
|
+
) -> "Callable[..., list[FilterTypes]]":
|
|
156
|
+
"""Create FastAPI dependency provider for filters based on configuration.
|
|
157
|
+
|
|
158
|
+
This function dynamically generates a FastAPI dependency function that parses
|
|
159
|
+
query parameters into SQLSpec filter objects.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
config: Filter configuration specifying which filters to enable.
|
|
163
|
+
dep_defaults: Dependency defaults for filter configuration.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
A FastAPI dependency callable that returns list of filters.
|
|
167
|
+
|
|
168
|
+
Example:
|
|
169
|
+
from fastapi import Depends, FastAPI
|
|
170
|
+
from sqlspec.extensions.fastapi import SQLSpecPlugin, FilterConfig
|
|
171
|
+
|
|
172
|
+
app = FastAPI()
|
|
173
|
+
db_ext = SQLSpecPlugin(sql, app)
|
|
174
|
+
|
|
175
|
+
@app.get("/users")
|
|
176
|
+
async def list_users(
|
|
177
|
+
filters = Depends(
|
|
178
|
+
db_ext.provide_filters({
|
|
179
|
+
"id_filter": UUID,
|
|
180
|
+
"search": "name,email",
|
|
181
|
+
"pagination_type": "limit_offset",
|
|
182
|
+
})
|
|
183
|
+
),
|
|
184
|
+
):
|
|
185
|
+
stmt = sql("SELECT * FROM users")
|
|
186
|
+
for filter in filters:
|
|
187
|
+
stmt = filter.append_to_statement(stmt)
|
|
188
|
+
result = await db.execute(stmt)
|
|
189
|
+
return result.all()
|
|
190
|
+
"""
|
|
191
|
+
filter_keys = {
|
|
192
|
+
"id_filter",
|
|
193
|
+
"created_at",
|
|
194
|
+
"updated_at",
|
|
195
|
+
"pagination_type",
|
|
196
|
+
"search",
|
|
197
|
+
"sort_field",
|
|
198
|
+
"not_in_fields",
|
|
199
|
+
"in_fields",
|
|
200
|
+
"null_fields",
|
|
201
|
+
"not_null_fields",
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
has_filters = False
|
|
205
|
+
for key in filter_keys:
|
|
206
|
+
value = config.get(key)
|
|
207
|
+
if value is not None and value is not False and value != []:
|
|
208
|
+
has_filters = True
|
|
209
|
+
break
|
|
210
|
+
|
|
211
|
+
if not has_filters:
|
|
212
|
+
return _empty_filter_list
|
|
213
|
+
|
|
214
|
+
cache_key = hash(_make_hashable(config))
|
|
215
|
+
|
|
216
|
+
cached_dep = dep_cache.get_dependencies(cache_key)
|
|
217
|
+
if cached_dep is not None:
|
|
218
|
+
return cached_dep
|
|
219
|
+
|
|
220
|
+
dep = _create_filter_aggregate_function_fastapi(config, dep_defaults)
|
|
221
|
+
dep_cache.add_dependencies(cache_key, dep)
|
|
222
|
+
return dep
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def _make_hashable(value: Any) -> HashableType:
|
|
226
|
+
"""Convert a value into a hashable type for caching purposes.
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
value: Any value that needs to be made hashable.
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
A hashable version of the value.
|
|
233
|
+
"""
|
|
234
|
+
if isinstance(value, dict):
|
|
235
|
+
items = []
|
|
236
|
+
for k in sorted(value.keys()):
|
|
237
|
+
v = value[k]
|
|
238
|
+
items.append((str(k), _make_hashable(v)))
|
|
239
|
+
return tuple(items)
|
|
240
|
+
if isinstance(value, (list, set)):
|
|
241
|
+
hashable_items = [_make_hashable(item) for item in value]
|
|
242
|
+
filtered_items = [item for item in hashable_items if item is not None]
|
|
243
|
+
return tuple(sorted(filtered_items, key=str))
|
|
244
|
+
if isinstance(value, (str, int, float, bool, type(None))):
|
|
245
|
+
return value
|
|
246
|
+
return str(value)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def _create_filter_aggregate_function_fastapi( # noqa: C901
|
|
250
|
+
config: FilterConfig, dep_defaults: DependencyDefaults = DEPENDENCY_DEFAULTS
|
|
251
|
+
) -> "Callable[..., list[FilterTypes]]":
|
|
252
|
+
"""Create a FastAPI dependency function that aggregates multiple filter dependencies.
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
config: Filter configuration.
|
|
256
|
+
dep_defaults: Dependency defaults.
|
|
257
|
+
|
|
258
|
+
Returns:
|
|
259
|
+
A FastAPI dependency function that aggregates multiple filter dependencies.
|
|
260
|
+
"""
|
|
261
|
+
params: list[inspect.Parameter] = []
|
|
262
|
+
annotations: dict[str, Any] = {}
|
|
263
|
+
|
|
264
|
+
if config.get("id_filter", False) is not False:
|
|
265
|
+
|
|
266
|
+
def provide_id_filter(
|
|
267
|
+
ids: Annotated[list[Any] | None, Query(alias="ids", description="IDs to filter by.")] = None,
|
|
268
|
+
) -> InCollectionFilter[Any] | None:
|
|
269
|
+
return InCollectionFilter(field_name=config.get("id_field", "id"), values=ids) if ids else None
|
|
270
|
+
|
|
271
|
+
params.append(
|
|
272
|
+
inspect.Parameter(
|
|
273
|
+
name=dep_defaults.ID_FILTER_DEPENDENCY_KEY,
|
|
274
|
+
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
275
|
+
annotation=Annotated["InCollectionFilter[Any] | None", Depends(provide_id_filter)],
|
|
276
|
+
)
|
|
277
|
+
)
|
|
278
|
+
annotations[dep_defaults.ID_FILTER_DEPENDENCY_KEY] = Annotated[
|
|
279
|
+
"InCollectionFilter[Any] | None", Depends(provide_id_filter)
|
|
280
|
+
]
|
|
281
|
+
|
|
282
|
+
if config.get("created_at", False):
|
|
283
|
+
|
|
284
|
+
def provide_created_at_filter(
|
|
285
|
+
before: Annotated[
|
|
286
|
+
str | None,
|
|
287
|
+
Query(
|
|
288
|
+
alias="createdBefore",
|
|
289
|
+
description="Filter by created date before this timestamp.",
|
|
290
|
+
json_schema_extra={"format": "date-time"},
|
|
291
|
+
),
|
|
292
|
+
] = None,
|
|
293
|
+
after: Annotated[
|
|
294
|
+
str | None,
|
|
295
|
+
Query(
|
|
296
|
+
alias="createdAfter",
|
|
297
|
+
description="Filter by created date after this timestamp.",
|
|
298
|
+
json_schema_extra={"format": "date-time"},
|
|
299
|
+
),
|
|
300
|
+
] = None,
|
|
301
|
+
) -> "BeforeAfterFilter | None":
|
|
302
|
+
before_dt = None
|
|
303
|
+
after_dt = None
|
|
304
|
+
|
|
305
|
+
if before is not None:
|
|
306
|
+
try:
|
|
307
|
+
before_dt = datetime.datetime.fromisoformat(before.replace("Z", "+00:00"))
|
|
308
|
+
except (ValueError, TypeError, AttributeError):
|
|
309
|
+
msg = "Invalid date format for createdBefore"
|
|
310
|
+
raise RequestValidationError(
|
|
311
|
+
errors=[{"loc": ("query", "createdBefore"), "msg": msg, "type": "value_error.datetime"}]
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
if after is not None:
|
|
315
|
+
try:
|
|
316
|
+
after_dt = datetime.datetime.fromisoformat(after.replace("Z", "+00:00"))
|
|
317
|
+
except (ValueError, TypeError, AttributeError):
|
|
318
|
+
msg = "Invalid date format for createdAfter"
|
|
319
|
+
raise RequestValidationError(
|
|
320
|
+
errors=[{"loc": ("query", "createdAfter"), "msg": msg, "type": "value_error.datetime"}]
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
return (
|
|
324
|
+
BeforeAfterFilter(field_name="created_at", before=before_dt, after=after_dt)
|
|
325
|
+
if before_dt or after_dt
|
|
326
|
+
else None
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
param_name = dep_defaults.CREATED_FILTER_DEPENDENCY_KEY
|
|
330
|
+
params.append(
|
|
331
|
+
inspect.Parameter(
|
|
332
|
+
name=param_name,
|
|
333
|
+
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
334
|
+
annotation=Annotated["BeforeAfterFilter | None", Depends(provide_created_at_filter)],
|
|
335
|
+
)
|
|
336
|
+
)
|
|
337
|
+
annotations[param_name] = Annotated["BeforeAfterFilter | None", Depends(provide_created_at_filter)]
|
|
338
|
+
|
|
339
|
+
if config.get("updated_at", False):
|
|
340
|
+
|
|
341
|
+
def provide_updated_at_filter(
|
|
342
|
+
before: Annotated[
|
|
343
|
+
str | None,
|
|
344
|
+
Query(
|
|
345
|
+
alias="updatedBefore",
|
|
346
|
+
description="Filter by updated date before this timestamp.",
|
|
347
|
+
json_schema_extra={"format": "date-time"},
|
|
348
|
+
),
|
|
349
|
+
] = None,
|
|
350
|
+
after: Annotated[
|
|
351
|
+
str | None,
|
|
352
|
+
Query(
|
|
353
|
+
alias="updatedAfter",
|
|
354
|
+
description="Filter by updated date after this timestamp.",
|
|
355
|
+
json_schema_extra={"format": "date-time"},
|
|
356
|
+
),
|
|
357
|
+
] = None,
|
|
358
|
+
) -> "BeforeAfterFilter | None":
|
|
359
|
+
before_dt = None
|
|
360
|
+
after_dt = None
|
|
361
|
+
|
|
362
|
+
if before is not None:
|
|
363
|
+
try:
|
|
364
|
+
before_dt = datetime.datetime.fromisoformat(before.replace("Z", "+00:00"))
|
|
365
|
+
except (ValueError, TypeError, AttributeError):
|
|
366
|
+
msg = "Invalid date format for updatedBefore"
|
|
367
|
+
raise RequestValidationError(
|
|
368
|
+
errors=[{"loc": ("query", "updatedBefore"), "msg": msg, "type": "value_error.datetime"}]
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
if after is not None:
|
|
372
|
+
try:
|
|
373
|
+
after_dt = datetime.datetime.fromisoformat(after.replace("Z", "+00:00"))
|
|
374
|
+
except (ValueError, TypeError, AttributeError):
|
|
375
|
+
msg = "Invalid date format for updatedAfter"
|
|
376
|
+
raise RequestValidationError(
|
|
377
|
+
errors=[{"loc": ("query", "updatedAfter"), "msg": msg, "type": "value_error.datetime"}]
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
return (
|
|
381
|
+
BeforeAfterFilter(field_name="updated_at", before=before_dt, after=after_dt)
|
|
382
|
+
if before_dt or after_dt
|
|
383
|
+
else None
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
param_name = dep_defaults.UPDATED_FILTER_DEPENDENCY_KEY
|
|
387
|
+
params.append(
|
|
388
|
+
inspect.Parameter(
|
|
389
|
+
name=param_name,
|
|
390
|
+
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
391
|
+
annotation=Annotated["BeforeAfterFilter | None", Depends(provide_updated_at_filter)],
|
|
392
|
+
)
|
|
393
|
+
)
|
|
394
|
+
annotations[param_name] = Annotated["BeforeAfterFilter | None", Depends(provide_updated_at_filter)]
|
|
395
|
+
|
|
396
|
+
if config.get("pagination_type") == "limit_offset":
|
|
397
|
+
|
|
398
|
+
def provide_limit_offset_pagination(
|
|
399
|
+
current_page: Annotated[
|
|
400
|
+
int, Query(ge=1, alias="currentPage", description="Page number for pagination.")
|
|
401
|
+
] = 1,
|
|
402
|
+
page_size: Annotated[
|
|
403
|
+
int, Query(ge=1, alias="pageSize", description="Number of items per page.")
|
|
404
|
+
] = config.get("pagination_size", dep_defaults.DEFAULT_PAGINATION_SIZE),
|
|
405
|
+
) -> LimitOffsetFilter:
|
|
406
|
+
return LimitOffsetFilter(limit=page_size, offset=page_size * (current_page - 1))
|
|
407
|
+
|
|
408
|
+
param_name = dep_defaults.LIMIT_OFFSET_FILTER_DEPENDENCY_KEY
|
|
409
|
+
params.append(
|
|
410
|
+
inspect.Parameter(
|
|
411
|
+
name=param_name,
|
|
412
|
+
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
413
|
+
annotation=Annotated[LimitOffsetFilter, Depends(provide_limit_offset_pagination)],
|
|
414
|
+
)
|
|
415
|
+
)
|
|
416
|
+
annotations[param_name] = Annotated[LimitOffsetFilter, Depends(provide_limit_offset_pagination)]
|
|
417
|
+
|
|
418
|
+
if search_fields := config.get("search"):
|
|
419
|
+
|
|
420
|
+
def provide_search_filter(
|
|
421
|
+
search_string: Annotated[str | None, Query(alias="searchString", description="Search term.")] = None,
|
|
422
|
+
ignore_case: Annotated[
|
|
423
|
+
bool | None, Query(alias="searchIgnoreCase", description="Whether search should be case-insensitive.")
|
|
424
|
+
] = config.get("search_ignore_case", False),
|
|
425
|
+
) -> "SearchFilter | None":
|
|
426
|
+
field_names = set(search_fields.split(",")) if isinstance(search_fields, str) else search_fields
|
|
427
|
+
|
|
428
|
+
return (
|
|
429
|
+
SearchFilter(field_name=field_names, value=search_string, ignore_case=ignore_case or False)
|
|
430
|
+
if search_string
|
|
431
|
+
else None
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
param_name = dep_defaults.SEARCH_FILTER_DEPENDENCY_KEY
|
|
435
|
+
params.append(
|
|
436
|
+
inspect.Parameter(
|
|
437
|
+
name=param_name,
|
|
438
|
+
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
439
|
+
annotation=Annotated["SearchFilter | None", Depends(provide_search_filter)],
|
|
440
|
+
)
|
|
441
|
+
)
|
|
442
|
+
annotations[param_name] = Annotated["SearchFilter | None", Depends(provide_search_filter)]
|
|
443
|
+
|
|
444
|
+
if sort_field := config.get("sort_field"):
|
|
445
|
+
sort_order_default = config.get("sort_order", "desc")
|
|
446
|
+
default_field = sort_field if isinstance(sort_field, str) else next(iter(sort_field))
|
|
447
|
+
|
|
448
|
+
def provide_order_by(
|
|
449
|
+
field_name: Annotated[str, Query(alias="orderBy", description="Field to order by.")] = default_field,
|
|
450
|
+
sort_order: Annotated[
|
|
451
|
+
SortOrder | None, Query(alias="sortOrder", description="Sort order ('asc' or 'desc').")
|
|
452
|
+
] = sort_order_default,
|
|
453
|
+
) -> OrderByFilter:
|
|
454
|
+
return OrderByFilter(field_name=field_name, sort_order=sort_order or sort_order_default)
|
|
455
|
+
|
|
456
|
+
param_name = dep_defaults.ORDER_BY_FILTER_DEPENDENCY_KEY
|
|
457
|
+
params.append(
|
|
458
|
+
inspect.Parameter(
|
|
459
|
+
name=param_name,
|
|
460
|
+
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
461
|
+
annotation=Annotated[OrderByFilter, Depends(provide_order_by)],
|
|
462
|
+
)
|
|
463
|
+
)
|
|
464
|
+
annotations[param_name] = Annotated[OrderByFilter, Depends(provide_order_by)]
|
|
465
|
+
|
|
466
|
+
if not_in_fields := config.get("not_in_fields"):
|
|
467
|
+
not_in_fields = {not_in_fields} if isinstance(not_in_fields, (str, FieldNameType)) else not_in_fields
|
|
468
|
+
for field_def in not_in_fields:
|
|
469
|
+
|
|
470
|
+
def create_not_in_filter_provider(
|
|
471
|
+
field_name: FieldNameType = field_def,
|
|
472
|
+
) -> "Callable[..., NotInCollectionFilter[Any] | None]":
|
|
473
|
+
def provide_not_in_filter(
|
|
474
|
+
values: Annotated[
|
|
475
|
+
set[Any] | None,
|
|
476
|
+
Query(
|
|
477
|
+
alias=camelize(f"{field_name.name}_not_in"),
|
|
478
|
+
description=f"Filter {field_name.name} not in values",
|
|
479
|
+
),
|
|
480
|
+
] = None,
|
|
481
|
+
) -> "NotInCollectionFilter[Any] | None":
|
|
482
|
+
return NotInCollectionFilter(field_name=field_name.name, values=values) if values else None
|
|
483
|
+
|
|
484
|
+
return provide_not_in_filter
|
|
485
|
+
|
|
486
|
+
not_in_provider = create_not_in_filter_provider()
|
|
487
|
+
param_name = f"{field_def.name}_not_in_filter"
|
|
488
|
+
params.append(
|
|
489
|
+
inspect.Parameter(
|
|
490
|
+
name=param_name,
|
|
491
|
+
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
492
|
+
annotation=Annotated["NotInCollectionFilter[Any] | None", Depends(not_in_provider)],
|
|
493
|
+
)
|
|
494
|
+
)
|
|
495
|
+
annotations[param_name] = Annotated["NotInCollectionFilter[Any] | None", Depends(not_in_provider)]
|
|
496
|
+
|
|
497
|
+
if in_fields := config.get("in_fields"):
|
|
498
|
+
in_fields = {in_fields} if isinstance(in_fields, (str, FieldNameType)) else in_fields
|
|
499
|
+
for field_def in in_fields:
|
|
500
|
+
|
|
501
|
+
def create_in_filter_provider(
|
|
502
|
+
field_name: FieldNameType = field_def,
|
|
503
|
+
) -> "Callable[..., InCollectionFilter[Any] | None]":
|
|
504
|
+
def provide_in_filter(
|
|
505
|
+
values: Annotated[
|
|
506
|
+
set[Any] | None,
|
|
507
|
+
Query(
|
|
508
|
+
alias=camelize(f"{field_name.name}_in"), description=f"Filter {field_name.name} in values"
|
|
509
|
+
),
|
|
510
|
+
] = None,
|
|
511
|
+
) -> "InCollectionFilter[Any] | None":
|
|
512
|
+
return InCollectionFilter(field_name=field_name.name, values=values) if values else None
|
|
513
|
+
|
|
514
|
+
return provide_in_filter
|
|
515
|
+
|
|
516
|
+
in_provider = create_in_filter_provider()
|
|
517
|
+
param_name = f"{field_def.name}_in_filter"
|
|
518
|
+
params.append(
|
|
519
|
+
inspect.Parameter(
|
|
520
|
+
name=param_name,
|
|
521
|
+
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
522
|
+
annotation=Annotated["InCollectionFilter[Any] | None", Depends(in_provider)],
|
|
523
|
+
)
|
|
524
|
+
)
|
|
525
|
+
annotations[param_name] = Annotated["InCollectionFilter[Any] | None", Depends(in_provider)]
|
|
526
|
+
|
|
527
|
+
if null_fields := config.get("null_fields"):
|
|
528
|
+
null_fields = {null_fields} if isinstance(null_fields, str) else null_fields
|
|
529
|
+
for field_name in null_fields:
|
|
530
|
+
|
|
531
|
+
def create_null_filter_provider(fname: str = field_name) -> "Callable[..., NullFilter | None]":
|
|
532
|
+
def provide_null_filter(
|
|
533
|
+
is_null: Annotated[
|
|
534
|
+
bool | None,
|
|
535
|
+
Query(alias=camelize(f"{fname}_is_null"), description=f"Filter where {fname} IS NULL"),
|
|
536
|
+
] = None,
|
|
537
|
+
) -> "NullFilter | None":
|
|
538
|
+
return NullFilter(field_name=fname) if is_null else None
|
|
539
|
+
|
|
540
|
+
return provide_null_filter
|
|
541
|
+
|
|
542
|
+
null_provider = create_null_filter_provider()
|
|
543
|
+
param_name = f"{field_name}_null_filter"
|
|
544
|
+
params.append(
|
|
545
|
+
inspect.Parameter(
|
|
546
|
+
name=param_name,
|
|
547
|
+
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
548
|
+
annotation=Annotated["NullFilter | None", Depends(null_provider)],
|
|
549
|
+
)
|
|
550
|
+
)
|
|
551
|
+
annotations[param_name] = Annotated["NullFilter | None", Depends(null_provider)]
|
|
552
|
+
|
|
553
|
+
if not_null_fields := config.get("not_null_fields"):
|
|
554
|
+
not_null_fields = {not_null_fields} if isinstance(not_null_fields, str) else not_null_fields
|
|
555
|
+
for field_name in not_null_fields:
|
|
556
|
+
|
|
557
|
+
def create_not_null_filter_provider(fname: str = field_name) -> "Callable[..., NotNullFilter | None]":
|
|
558
|
+
def provide_not_null_filter(
|
|
559
|
+
is_not_null: Annotated[
|
|
560
|
+
bool | None,
|
|
561
|
+
Query(alias=camelize(f"{fname}_is_not_null"), description=f"Filter where {fname} IS NOT NULL"),
|
|
562
|
+
] = None,
|
|
563
|
+
) -> "NotNullFilter | None":
|
|
564
|
+
return NotNullFilter(field_name=fname) if is_not_null else None
|
|
565
|
+
|
|
566
|
+
return provide_not_null_filter
|
|
567
|
+
|
|
568
|
+
not_null_provider = create_not_null_filter_provider()
|
|
569
|
+
param_name = f"{field_name}_not_null_filter"
|
|
570
|
+
params.append(
|
|
571
|
+
inspect.Parameter(
|
|
572
|
+
name=param_name,
|
|
573
|
+
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
574
|
+
annotation=Annotated["NotNullFilter | None", Depends(not_null_provider)],
|
|
575
|
+
)
|
|
576
|
+
)
|
|
577
|
+
annotations[param_name] = Annotated["NotNullFilter | None", Depends(not_null_provider)]
|
|
578
|
+
|
|
579
|
+
_aggregate_filter_function.__signature__ = inspect.Signature( # type: ignore[attr-defined]
|
|
580
|
+
parameters=params, return_annotation=Annotated["list[FilterTypes]", _aggregate_filter_function]
|
|
581
|
+
)
|
|
582
|
+
|
|
583
|
+
return _aggregate_filter_function
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
def _aggregate_filter_function(**kwargs: Any) -> "list[FilterTypes]":
|
|
587
|
+
"""Aggregate filter dependencies based on configuration.
|
|
588
|
+
|
|
589
|
+
Args:
|
|
590
|
+
**kwargs: Filter parameters dynamically provided based on configuration.
|
|
591
|
+
|
|
592
|
+
Returns:
|
|
593
|
+
List of configured filters.
|
|
594
|
+
"""
|
|
595
|
+
filters: list[FilterTypes] = []
|
|
596
|
+
for filter_value in kwargs.values():
|
|
597
|
+
if filter_value is None:
|
|
598
|
+
continue
|
|
599
|
+
if isinstance(filter_value, list):
|
|
600
|
+
filters.extend(filter_value)
|
|
601
|
+
elif (isinstance(filter_value, SearchFilter) and filter_value.value is None) or (
|
|
602
|
+
isinstance(filter_value, OrderByFilter) and filter_value.field_name is None
|
|
603
|
+
):
|
|
604
|
+
continue
|
|
605
|
+
else:
|
|
606
|
+
filters.append(filter_value)
|
|
607
|
+
return filters
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Flask extension for SQLSpec.
|
|
2
|
+
|
|
3
|
+
Provides request-scoped session management, automatic transaction handling,
|
|
4
|
+
and async adapter support via portal pattern.
|
|
5
|
+
|
|
6
|
+
Example:
|
|
7
|
+
from flask import Flask
|
|
8
|
+
from sqlspec import SQLSpec
|
|
9
|
+
from sqlspec.adapters.sqlite import SqliteConfig
|
|
10
|
+
from sqlspec.extensions.flask import SQLSpecPlugin
|
|
11
|
+
|
|
12
|
+
sqlspec = SQLSpec()
|
|
13
|
+
config = SqliteConfig(
|
|
14
|
+
connection_config={"database": "app.db"},
|
|
15
|
+
extension_config={
|
|
16
|
+
"flask": {
|
|
17
|
+
"commit_mode": "autocommit",
|
|
18
|
+
"session_key": "db"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
)
|
|
22
|
+
sqlspec.add_config(config)
|
|
23
|
+
|
|
24
|
+
app = Flask(__name__)
|
|
25
|
+
plugin = SQLSpecPlugin(sqlspec, app)
|
|
26
|
+
|
|
27
|
+
@app.route("/users")
|
|
28
|
+
def list_users():
|
|
29
|
+
db = plugin.get_session()
|
|
30
|
+
result = db.execute("SELECT * FROM users")
|
|
31
|
+
return {"users": result.all()}
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from sqlspec.extensions.flask._state import FlaskConfigState
|
|
35
|
+
from sqlspec.extensions.flask.extension import SQLSpecPlugin
|
|
36
|
+
|
|
37
|
+
__all__ = ("FlaskConfigState", "SQLSpecPlugin")
|