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,508 @@
|
|
|
1
|
+
"""SQLSpec-backed artifact service for Google ADK.
|
|
2
|
+
|
|
3
|
+
Implements ``BaseArtifactService`` by composing SQL-backed metadata storage
|
|
4
|
+
(via :class:`BaseAsyncADKArtifactStore`) with ``sqlspec/storage/`` content
|
|
5
|
+
backends (via :class:`StorageRegistry`).
|
|
6
|
+
|
|
7
|
+
Metadata (version, filename, MIME type, custom metadata, canonical URI) lives
|
|
8
|
+
in a SQL table. Content bytes live in object storage addressed by canonical
|
|
9
|
+
URI. Versioning is append-only with monotonically increasing version numbers
|
|
10
|
+
starting from 0.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
import logging
|
|
15
|
+
import re
|
|
16
|
+
from typing import TYPE_CHECKING, Any
|
|
17
|
+
|
|
18
|
+
from google.adk.artifacts.base_artifact_service import BaseArtifactService
|
|
19
|
+
|
|
20
|
+
from sqlspec.extensions.adk.artifact._types import ArtifactRecord
|
|
21
|
+
from sqlspec.storage.registry import StorageRegistry, storage_registry
|
|
22
|
+
from sqlspec.utils.logging import get_logger, log_with_context
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from google.adk.artifacts.base_artifact_service import ArtifactVersion
|
|
26
|
+
from google.genai import types
|
|
27
|
+
|
|
28
|
+
from sqlspec.extensions.adk.artifact.store import BaseAsyncADKArtifactStore
|
|
29
|
+
|
|
30
|
+
logger = get_logger("sqlspec.extensions.adk.artifact.service")
|
|
31
|
+
|
|
32
|
+
__all__ = ("SQLSpecArtifactService",)
|
|
33
|
+
|
|
34
|
+
# Matches path traversal and absolute path components
|
|
35
|
+
_UNSAFE_PATH_CHARS = re.compile(r"(?:^|/)\.\.(?:/|$)|[\x00]")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _sanitize_path_component(value: str) -> str:
|
|
39
|
+
"""Sanitize a path component to prevent directory traversal.
|
|
40
|
+
|
|
41
|
+
Removes leading/trailing slashes, rejects ``..`` traversals, and
|
|
42
|
+
replaces NUL bytes.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
value: Raw path component.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Sanitized path component.
|
|
49
|
+
|
|
50
|
+
Raises:
|
|
51
|
+
ValueError: If the value contains path traversal sequences.
|
|
52
|
+
"""
|
|
53
|
+
value = value.strip("/")
|
|
54
|
+
if _UNSAFE_PATH_CHARS.search(value):
|
|
55
|
+
msg = f"Unsafe path component: {value!r}"
|
|
56
|
+
raise ValueError(msg)
|
|
57
|
+
return value
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _build_content_path(
|
|
61
|
+
app_name: str, user_id: str, filename: str, version: int, session_id: "str | None" = None
|
|
62
|
+
) -> str:
|
|
63
|
+
"""Build the storage path for artifact content.
|
|
64
|
+
|
|
65
|
+
Pattern:
|
|
66
|
+
``apps/{app_name}/users/{user_id}/[sessions/{session_id}/]artifacts/{filename}/v{version}``
|
|
67
|
+
|
|
68
|
+
All path components are sanitized to prevent directory traversal.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
app_name: Application name.
|
|
72
|
+
user_id: User identifier.
|
|
73
|
+
filename: Artifact filename.
|
|
74
|
+
version: Version number.
|
|
75
|
+
session_id: Optional session identifier.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Sanitized storage path.
|
|
79
|
+
"""
|
|
80
|
+
parts = ["apps", _sanitize_path_component(app_name), "users", _sanitize_path_component(user_id)]
|
|
81
|
+
if session_id is not None:
|
|
82
|
+
parts.extend(["sessions", _sanitize_path_component(session_id)])
|
|
83
|
+
parts.extend(["artifacts", _sanitize_path_component(filename), f"v{version}"])
|
|
84
|
+
return "/".join(parts)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _extract_mime_type(artifact: "types.Part | dict[str, Any]") -> "str | None":
|
|
88
|
+
"""Extract MIME type from an artifact Part.
|
|
89
|
+
|
|
90
|
+
Checks ``inline_data.mime_type`` and ``file_data.mime_type`` on the Part.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
artifact: ADK Part or dict representation.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
MIME type string, or None if not determinable.
|
|
97
|
+
"""
|
|
98
|
+
if isinstance(artifact, dict):
|
|
99
|
+
# Handle camelCase and snake_case keys
|
|
100
|
+
inline = artifact.get("inline_data") or artifact.get("inlineData")
|
|
101
|
+
if isinstance(inline, dict):
|
|
102
|
+
return inline.get("mime_type") or inline.get("mimeType")
|
|
103
|
+
file_data = artifact.get("file_data") or artifact.get("fileData")
|
|
104
|
+
if isinstance(file_data, dict):
|
|
105
|
+
return file_data.get("mime_type") or file_data.get("mimeType")
|
|
106
|
+
return None
|
|
107
|
+
|
|
108
|
+
# types.Part object
|
|
109
|
+
if hasattr(artifact, "inline_data") and artifact.inline_data is not None:
|
|
110
|
+
return getattr(artifact.inline_data, "mime_type", None)
|
|
111
|
+
if hasattr(artifact, "file_data") and artifact.file_data is not None:
|
|
112
|
+
return getattr(artifact.file_data, "mime_type", None)
|
|
113
|
+
return None
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _serialize_artifact(artifact: "types.Part | dict[str, Any]") -> bytes:
|
|
117
|
+
"""Serialize an artifact Part to bytes for content storage.
|
|
118
|
+
|
|
119
|
+
The artifact is serialized as JSON via ``model_dump(exclude_none=True)``.
|
|
120
|
+
This preserves the full Part structure including text, inline_data,
|
|
121
|
+
file_data, and any future Part fields.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
artifact: ADK Part or dict representation.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
JSON-encoded bytes.
|
|
128
|
+
"""
|
|
129
|
+
if isinstance(artifact, dict):
|
|
130
|
+
return json.dumps(artifact, default=str).encode("utf-8")
|
|
131
|
+
|
|
132
|
+
# Use Pydantic model serialization
|
|
133
|
+
if hasattr(artifact, "model_dump"):
|
|
134
|
+
data = artifact.model_dump(exclude_none=True)
|
|
135
|
+
return json.dumps(data, default=str).encode("utf-8")
|
|
136
|
+
|
|
137
|
+
# Fallback for unexpected types
|
|
138
|
+
return json.dumps({"text": str(artifact)}).encode("utf-8")
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _deserialize_artifact(data: bytes) -> "types.Part":
|
|
142
|
+
"""Deserialize bytes back into an ADK Part.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
data: JSON-encoded bytes from content storage.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
Reconstructed Part object.
|
|
149
|
+
"""
|
|
150
|
+
from google.genai import types
|
|
151
|
+
|
|
152
|
+
parsed = json.loads(data.decode("utf-8"))
|
|
153
|
+
return types.Part.model_validate(parsed)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _record_to_artifact_version(record: "ArtifactRecord") -> "ArtifactVersion":
|
|
157
|
+
"""Convert a database artifact record to an ADK ArtifactVersion.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
record: Database artifact record.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
ArtifactVersion model instance.
|
|
164
|
+
"""
|
|
165
|
+
from google.adk.artifacts.base_artifact_service import ArtifactVersion
|
|
166
|
+
|
|
167
|
+
return ArtifactVersion(
|
|
168
|
+
version=record["version"],
|
|
169
|
+
canonical_uri=record["canonical_uri"],
|
|
170
|
+
custom_metadata=record["custom_metadata"] or {},
|
|
171
|
+
create_time=record["created_at"].timestamp(),
|
|
172
|
+
mime_type=record["mime_type"],
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class SQLSpecArtifactService(BaseArtifactService):
|
|
177
|
+
"""SQLSpec-backed implementation of BaseArtifactService.
|
|
178
|
+
|
|
179
|
+
Composes SQL metadata storage with ``sqlspec/storage/`` content backends
|
|
180
|
+
to provide versioned artifact management for Google ADK.
|
|
181
|
+
|
|
182
|
+
Metadata (version number, filename, MIME type, custom metadata, canonical
|
|
183
|
+
URI) is stored in a SQL table managed by the artifact store. Content
|
|
184
|
+
bytes are stored in object storage (S3, GCS, Azure, local filesystem)
|
|
185
|
+
via the storage registry.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
store: Artifact metadata store implementation.
|
|
189
|
+
artifact_storage_uri: Base URI for content storage (e.g.,
|
|
190
|
+
``"s3://my-bucket/adk-artifacts/"``, ``"file:///var/data/artifacts/"``).
|
|
191
|
+
Can also be a registered alias in the storage registry.
|
|
192
|
+
registry: Storage registry to use. Defaults to the global singleton.
|
|
193
|
+
|
|
194
|
+
Example:
|
|
195
|
+
from sqlspec.extensions.adk.artifact import SQLSpecArtifactService
|
|
196
|
+
|
|
197
|
+
artifact_store = MyArtifactMetadataStore(config)
|
|
198
|
+
await artifact_store.ensure_table()
|
|
199
|
+
|
|
200
|
+
service = SQLSpecArtifactService(
|
|
201
|
+
store=artifact_store,
|
|
202
|
+
artifact_storage_uri="s3://my-bucket/adk-artifacts/",
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
version = await service.save_artifact(
|
|
206
|
+
app_name="my_app",
|
|
207
|
+
user_id="user123",
|
|
208
|
+
filename="output.png",
|
|
209
|
+
artifact=part,
|
|
210
|
+
)
|
|
211
|
+
"""
|
|
212
|
+
|
|
213
|
+
def __init__(
|
|
214
|
+
self, store: "BaseAsyncADKArtifactStore", artifact_storage_uri: str, registry: "StorageRegistry | None" = None
|
|
215
|
+
) -> None:
|
|
216
|
+
self._store = store
|
|
217
|
+
self._artifact_storage_uri = artifact_storage_uri.rstrip("/")
|
|
218
|
+
self._registry = registry or storage_registry
|
|
219
|
+
|
|
220
|
+
@property
|
|
221
|
+
def store(self) -> "BaseAsyncADKArtifactStore":
|
|
222
|
+
"""Return the artifact metadata store."""
|
|
223
|
+
return self._store
|
|
224
|
+
|
|
225
|
+
@property
|
|
226
|
+
def artifact_storage_uri(self) -> str:
|
|
227
|
+
"""Return the base URI for content storage."""
|
|
228
|
+
return self._artifact_storage_uri
|
|
229
|
+
|
|
230
|
+
async def save_artifact(
|
|
231
|
+
self,
|
|
232
|
+
*,
|
|
233
|
+
app_name: str,
|
|
234
|
+
user_id: str,
|
|
235
|
+
filename: str,
|
|
236
|
+
artifact: "types.Part | dict[str, Any]",
|
|
237
|
+
session_id: "str | None" = None,
|
|
238
|
+
custom_metadata: "dict[str, Any] | None" = None,
|
|
239
|
+
) -> int:
|
|
240
|
+
"""Save an artifact, returning the new version number.
|
|
241
|
+
|
|
242
|
+
Writes content to object storage first, then inserts the metadata
|
|
243
|
+
row. If content write succeeds but metadata insert fails, the
|
|
244
|
+
orphaned content blob is logged but not automatically cleaned up
|
|
245
|
+
(eventual consistency is acceptable; orphan sweep can be added later).
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
app_name: Application name.
|
|
249
|
+
user_id: User identifier.
|
|
250
|
+
filename: Artifact filename.
|
|
251
|
+
artifact: ADK Part or dict to save.
|
|
252
|
+
session_id: Session identifier (None for user-scoped).
|
|
253
|
+
custom_metadata: Optional per-version metadata dict.
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
The version number (0-based, incrementing).
|
|
257
|
+
"""
|
|
258
|
+
from google.adk.artifacts.base_artifact_service import ensure_part
|
|
259
|
+
|
|
260
|
+
# Normalize artifact to Part
|
|
261
|
+
artifact_part: types.Part = ensure_part(artifact)
|
|
262
|
+
|
|
263
|
+
# Determine the next version
|
|
264
|
+
version = await self._store.get_next_version(
|
|
265
|
+
app_name=app_name, user_id=user_id, filename=filename, session_id=session_id
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
# Build the content path and canonical URI
|
|
269
|
+
content_path = _build_content_path(
|
|
270
|
+
app_name=app_name, user_id=user_id, filename=filename, version=version, session_id=session_id
|
|
271
|
+
)
|
|
272
|
+
canonical_uri = f"{self._artifact_storage_uri}/{content_path}"
|
|
273
|
+
|
|
274
|
+
# Serialize content
|
|
275
|
+
content_bytes = _serialize_artifact(artifact_part)
|
|
276
|
+
|
|
277
|
+
# Extract MIME type
|
|
278
|
+
mime_type = _extract_mime_type(artifact_part)
|
|
279
|
+
|
|
280
|
+
# Write content first (fail-fast before metadata)
|
|
281
|
+
backend = self._registry.get(self._artifact_storage_uri)
|
|
282
|
+
if hasattr(backend, "write_bytes_async"):
|
|
283
|
+
await backend.write_bytes_async(content_path, content_bytes)
|
|
284
|
+
else:
|
|
285
|
+
backend.write_bytes_sync(content_path, content_bytes)
|
|
286
|
+
|
|
287
|
+
# Insert metadata row
|
|
288
|
+
from datetime import datetime, timezone
|
|
289
|
+
|
|
290
|
+
record = ArtifactRecord(
|
|
291
|
+
app_name=app_name,
|
|
292
|
+
user_id=user_id,
|
|
293
|
+
session_id=session_id,
|
|
294
|
+
filename=filename,
|
|
295
|
+
version=version,
|
|
296
|
+
mime_type=mime_type,
|
|
297
|
+
canonical_uri=canonical_uri,
|
|
298
|
+
custom_metadata=custom_metadata,
|
|
299
|
+
created_at=datetime.now(tz=timezone.utc),
|
|
300
|
+
)
|
|
301
|
+
await self._store.insert_artifact(record)
|
|
302
|
+
|
|
303
|
+
log_with_context(
|
|
304
|
+
logger,
|
|
305
|
+
logging.DEBUG,
|
|
306
|
+
"adk.artifact.save",
|
|
307
|
+
app_name=app_name,
|
|
308
|
+
user_id=user_id,
|
|
309
|
+
filename=filename,
|
|
310
|
+
version=version,
|
|
311
|
+
session_id=session_id,
|
|
312
|
+
mime_type=mime_type,
|
|
313
|
+
)
|
|
314
|
+
return version
|
|
315
|
+
|
|
316
|
+
async def load_artifact(
|
|
317
|
+
self,
|
|
318
|
+
*,
|
|
319
|
+
app_name: str,
|
|
320
|
+
user_id: str,
|
|
321
|
+
filename: str,
|
|
322
|
+
session_id: "str | None" = None,
|
|
323
|
+
version: "int | None" = None,
|
|
324
|
+
) -> "types.Part | None":
|
|
325
|
+
"""Load an artifact by reading metadata then fetching content.
|
|
326
|
+
|
|
327
|
+
Args:
|
|
328
|
+
app_name: Application name.
|
|
329
|
+
user_id: User identifier.
|
|
330
|
+
filename: Artifact filename.
|
|
331
|
+
session_id: Session identifier (None for user-scoped).
|
|
332
|
+
version: Specific version, or None for latest.
|
|
333
|
+
|
|
334
|
+
Returns:
|
|
335
|
+
Deserialized Part, or None if not found.
|
|
336
|
+
"""
|
|
337
|
+
record = await self._store.get_artifact(
|
|
338
|
+
app_name=app_name, user_id=user_id, filename=filename, session_id=session_id, version=version
|
|
339
|
+
)
|
|
340
|
+
if record is None:
|
|
341
|
+
log_with_context(
|
|
342
|
+
logger,
|
|
343
|
+
logging.DEBUG,
|
|
344
|
+
"adk.artifact.load",
|
|
345
|
+
app_name=app_name,
|
|
346
|
+
filename=filename,
|
|
347
|
+
version=version,
|
|
348
|
+
found=False,
|
|
349
|
+
)
|
|
350
|
+
return None
|
|
351
|
+
|
|
352
|
+
# Derive content path from canonical URI
|
|
353
|
+
content_path = record["canonical_uri"].removeprefix(self._artifact_storage_uri + "/")
|
|
354
|
+
|
|
355
|
+
backend = self._registry.get(self._artifact_storage_uri)
|
|
356
|
+
if hasattr(backend, "read_bytes_async"):
|
|
357
|
+
content_bytes = await backend.read_bytes_async(content_path)
|
|
358
|
+
else:
|
|
359
|
+
content_bytes = backend.read_bytes_sync(content_path)
|
|
360
|
+
|
|
361
|
+
log_with_context(
|
|
362
|
+
logger,
|
|
363
|
+
logging.DEBUG,
|
|
364
|
+
"adk.artifact.load",
|
|
365
|
+
app_name=app_name,
|
|
366
|
+
filename=filename,
|
|
367
|
+
version=record["version"],
|
|
368
|
+
found=True,
|
|
369
|
+
)
|
|
370
|
+
return _deserialize_artifact(content_bytes)
|
|
371
|
+
|
|
372
|
+
async def list_artifact_keys(self, *, app_name: str, user_id: str, session_id: "str | None" = None) -> "list[str]":
|
|
373
|
+
"""List distinct artifact filenames.
|
|
374
|
+
|
|
375
|
+
When ``session_id`` is provided, returns both session-scoped and
|
|
376
|
+
user-scoped filenames. When None, returns only user-scoped filenames.
|
|
377
|
+
|
|
378
|
+
Args:
|
|
379
|
+
app_name: Application name.
|
|
380
|
+
user_id: User identifier.
|
|
381
|
+
session_id: Session identifier.
|
|
382
|
+
|
|
383
|
+
Returns:
|
|
384
|
+
List of artifact filenames.
|
|
385
|
+
"""
|
|
386
|
+
keys = await self._store.list_artifact_keys(app_name=app_name, user_id=user_id, session_id=session_id)
|
|
387
|
+
log_with_context(
|
|
388
|
+
logger,
|
|
389
|
+
logging.DEBUG,
|
|
390
|
+
"adk.artifact.list_keys",
|
|
391
|
+
app_name=app_name,
|
|
392
|
+
user_id=user_id,
|
|
393
|
+
session_id=session_id,
|
|
394
|
+
count=len(keys),
|
|
395
|
+
)
|
|
396
|
+
return keys
|
|
397
|
+
|
|
398
|
+
async def delete_artifact(
|
|
399
|
+
self, *, app_name: str, user_id: str, filename: str, session_id: "str | None" = None
|
|
400
|
+
) -> None:
|
|
401
|
+
"""Delete an artifact and all its versions.
|
|
402
|
+
|
|
403
|
+
Deletes metadata rows first (fail-fast), then removes content
|
|
404
|
+
objects from storage (best-effort).
|
|
405
|
+
|
|
406
|
+
Args:
|
|
407
|
+
app_name: Application name.
|
|
408
|
+
user_id: User identifier.
|
|
409
|
+
filename: Artifact filename.
|
|
410
|
+
session_id: Session identifier (None for user-scoped).
|
|
411
|
+
"""
|
|
412
|
+
deleted_records = await self._store.delete_artifact(
|
|
413
|
+
app_name=app_name, user_id=user_id, filename=filename, session_id=session_id
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
# Best-effort content cleanup
|
|
417
|
+
backend = self._registry.get(self._artifact_storage_uri)
|
|
418
|
+
for record in deleted_records:
|
|
419
|
+
content_path = record["canonical_uri"].removeprefix(self._artifact_storage_uri + "/")
|
|
420
|
+
try:
|
|
421
|
+
if hasattr(backend, "delete_async"):
|
|
422
|
+
await backend.delete_async(content_path)
|
|
423
|
+
else:
|
|
424
|
+
backend.delete_sync(content_path)
|
|
425
|
+
except Exception:
|
|
426
|
+
log_with_context(
|
|
427
|
+
logger,
|
|
428
|
+
logging.WARNING,
|
|
429
|
+
"adk.artifact.delete.content_cleanup_failed",
|
|
430
|
+
canonical_uri=record["canonical_uri"],
|
|
431
|
+
version=record["version"],
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
log_with_context(
|
|
435
|
+
logger,
|
|
436
|
+
logging.DEBUG,
|
|
437
|
+
"adk.artifact.delete",
|
|
438
|
+
app_name=app_name,
|
|
439
|
+
filename=filename,
|
|
440
|
+
session_id=session_id,
|
|
441
|
+
versions_deleted=len(deleted_records),
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
async def list_versions(
|
|
445
|
+
self, *, app_name: str, user_id: str, filename: str, session_id: "str | None" = None
|
|
446
|
+
) -> "list[int]":
|
|
447
|
+
"""List all version numbers for an artifact.
|
|
448
|
+
|
|
449
|
+
Args:
|
|
450
|
+
app_name: Application name.
|
|
451
|
+
user_id: User identifier.
|
|
452
|
+
filename: Artifact filename.
|
|
453
|
+
session_id: Session identifier (None for user-scoped).
|
|
454
|
+
|
|
455
|
+
Returns:
|
|
456
|
+
Sorted list of version numbers.
|
|
457
|
+
"""
|
|
458
|
+
records = await self._store.list_artifact_versions(
|
|
459
|
+
app_name=app_name, user_id=user_id, filename=filename, session_id=session_id
|
|
460
|
+
)
|
|
461
|
+
return [r["version"] for r in records]
|
|
462
|
+
|
|
463
|
+
async def list_artifact_versions(
|
|
464
|
+
self, *, app_name: str, user_id: str, filename: str, session_id: "str | None" = None
|
|
465
|
+
) -> "list[ArtifactVersion]":
|
|
466
|
+
"""List all versions with full metadata for an artifact.
|
|
467
|
+
|
|
468
|
+
Args:
|
|
469
|
+
app_name: Application name.
|
|
470
|
+
user_id: User identifier.
|
|
471
|
+
filename: Artifact filename.
|
|
472
|
+
session_id: Session identifier (None for user-scoped).
|
|
473
|
+
|
|
474
|
+
Returns:
|
|
475
|
+
List of ArtifactVersion objects ordered by version ascending.
|
|
476
|
+
"""
|
|
477
|
+
records = await self._store.list_artifact_versions(
|
|
478
|
+
app_name=app_name, user_id=user_id, filename=filename, session_id=session_id
|
|
479
|
+
)
|
|
480
|
+
return [_record_to_artifact_version(r) for r in records]
|
|
481
|
+
|
|
482
|
+
async def get_artifact_version(
|
|
483
|
+
self,
|
|
484
|
+
*,
|
|
485
|
+
app_name: str,
|
|
486
|
+
user_id: str,
|
|
487
|
+
filename: str,
|
|
488
|
+
session_id: "str | None" = None,
|
|
489
|
+
version: "int | None" = None,
|
|
490
|
+
) -> "ArtifactVersion | None":
|
|
491
|
+
"""Get metadata for a specific artifact version.
|
|
492
|
+
|
|
493
|
+
Args:
|
|
494
|
+
app_name: Application name.
|
|
495
|
+
user_id: User identifier.
|
|
496
|
+
filename: Artifact filename.
|
|
497
|
+
session_id: Session identifier (None for user-scoped).
|
|
498
|
+
version: Version number, or None for latest.
|
|
499
|
+
|
|
500
|
+
Returns:
|
|
501
|
+
ArtifactVersion if found, None otherwise.
|
|
502
|
+
"""
|
|
503
|
+
record = await self._store.get_artifact(
|
|
504
|
+
app_name=app_name, user_id=user_id, filename=filename, session_id=session_id, version=version
|
|
505
|
+
)
|
|
506
|
+
if record is None:
|
|
507
|
+
return None
|
|
508
|
+
return _record_to_artifact_version(record)
|