sqlspec 0.26.0__py3-none-any.whl → 0.27.0__py3-none-any.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.

Potentially problematic release.


This version of sqlspec might be problematic. Click here for more details.

Files changed (197) hide show
  1. sqlspec/__init__.py +7 -15
  2. sqlspec/_serialization.py +55 -25
  3. sqlspec/_typing.py +62 -52
  4. sqlspec/adapters/adbc/_types.py +1 -1
  5. sqlspec/adapters/adbc/adk/__init__.py +5 -0
  6. sqlspec/adapters/adbc/adk/store.py +870 -0
  7. sqlspec/adapters/adbc/config.py +62 -12
  8. sqlspec/adapters/adbc/data_dictionary.py +52 -2
  9. sqlspec/adapters/adbc/driver.py +144 -45
  10. sqlspec/adapters/adbc/litestar/__init__.py +5 -0
  11. sqlspec/adapters/adbc/litestar/store.py +504 -0
  12. sqlspec/adapters/adbc/type_converter.py +44 -50
  13. sqlspec/adapters/aiosqlite/_types.py +1 -1
  14. sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
  15. sqlspec/adapters/aiosqlite/adk/store.py +527 -0
  16. sqlspec/adapters/aiosqlite/config.py +86 -16
  17. sqlspec/adapters/aiosqlite/data_dictionary.py +34 -2
  18. sqlspec/adapters/aiosqlite/driver.py +127 -38
  19. sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
  20. sqlspec/adapters/aiosqlite/litestar/store.py +281 -0
  21. sqlspec/adapters/aiosqlite/pool.py +7 -7
  22. sqlspec/adapters/asyncmy/__init__.py +7 -1
  23. sqlspec/adapters/asyncmy/_types.py +1 -1
  24. sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
  25. sqlspec/adapters/asyncmy/adk/store.py +493 -0
  26. sqlspec/adapters/asyncmy/config.py +59 -17
  27. sqlspec/adapters/asyncmy/data_dictionary.py +41 -2
  28. sqlspec/adapters/asyncmy/driver.py +293 -62
  29. sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
  30. sqlspec/adapters/asyncmy/litestar/store.py +296 -0
  31. sqlspec/adapters/asyncpg/__init__.py +2 -1
  32. sqlspec/adapters/asyncpg/_type_handlers.py +71 -0
  33. sqlspec/adapters/asyncpg/_types.py +11 -7
  34. sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
  35. sqlspec/adapters/asyncpg/adk/store.py +450 -0
  36. sqlspec/adapters/asyncpg/config.py +57 -36
  37. sqlspec/adapters/asyncpg/data_dictionary.py +41 -2
  38. sqlspec/adapters/asyncpg/driver.py +153 -23
  39. sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
  40. sqlspec/adapters/asyncpg/litestar/store.py +253 -0
  41. sqlspec/adapters/bigquery/_types.py +1 -1
  42. sqlspec/adapters/bigquery/adk/__init__.py +5 -0
  43. sqlspec/adapters/bigquery/adk/store.py +576 -0
  44. sqlspec/adapters/bigquery/config.py +25 -11
  45. sqlspec/adapters/bigquery/data_dictionary.py +42 -2
  46. sqlspec/adapters/bigquery/driver.py +352 -144
  47. sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
  48. sqlspec/adapters/bigquery/litestar/store.py +327 -0
  49. sqlspec/adapters/bigquery/type_converter.py +55 -23
  50. sqlspec/adapters/duckdb/_types.py +2 -2
  51. sqlspec/adapters/duckdb/adk/__init__.py +14 -0
  52. sqlspec/adapters/duckdb/adk/store.py +553 -0
  53. sqlspec/adapters/duckdb/config.py +79 -21
  54. sqlspec/adapters/duckdb/data_dictionary.py +41 -2
  55. sqlspec/adapters/duckdb/driver.py +138 -43
  56. sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
  57. sqlspec/adapters/duckdb/litestar/store.py +332 -0
  58. sqlspec/adapters/duckdb/pool.py +5 -5
  59. sqlspec/adapters/duckdb/type_converter.py +51 -21
  60. sqlspec/adapters/oracledb/_numpy_handlers.py +133 -0
  61. sqlspec/adapters/oracledb/_types.py +20 -2
  62. sqlspec/adapters/oracledb/adk/__init__.py +5 -0
  63. sqlspec/adapters/oracledb/adk/store.py +1745 -0
  64. sqlspec/adapters/oracledb/config.py +120 -36
  65. sqlspec/adapters/oracledb/data_dictionary.py +87 -20
  66. sqlspec/adapters/oracledb/driver.py +292 -84
  67. sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
  68. sqlspec/adapters/oracledb/litestar/store.py +767 -0
  69. sqlspec/adapters/oracledb/migrations.py +316 -25
  70. sqlspec/adapters/oracledb/type_converter.py +91 -16
  71. sqlspec/adapters/psqlpy/_type_handlers.py +44 -0
  72. sqlspec/adapters/psqlpy/_types.py +2 -1
  73. sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
  74. sqlspec/adapters/psqlpy/adk/store.py +482 -0
  75. sqlspec/adapters/psqlpy/config.py +45 -19
  76. sqlspec/adapters/psqlpy/data_dictionary.py +41 -2
  77. sqlspec/adapters/psqlpy/driver.py +101 -31
  78. sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
  79. sqlspec/adapters/psqlpy/litestar/store.py +272 -0
  80. sqlspec/adapters/psqlpy/type_converter.py +40 -11
  81. sqlspec/adapters/psycopg/_type_handlers.py +80 -0
  82. sqlspec/adapters/psycopg/_types.py +2 -1
  83. sqlspec/adapters/psycopg/adk/__init__.py +5 -0
  84. sqlspec/adapters/psycopg/adk/store.py +944 -0
  85. sqlspec/adapters/psycopg/config.py +65 -37
  86. sqlspec/adapters/psycopg/data_dictionary.py +77 -3
  87. sqlspec/adapters/psycopg/driver.py +200 -78
  88. sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
  89. sqlspec/adapters/psycopg/litestar/store.py +554 -0
  90. sqlspec/adapters/sqlite/__init__.py +2 -1
  91. sqlspec/adapters/sqlite/_type_handlers.py +86 -0
  92. sqlspec/adapters/sqlite/_types.py +1 -1
  93. sqlspec/adapters/sqlite/adk/__init__.py +5 -0
  94. sqlspec/adapters/sqlite/adk/store.py +572 -0
  95. sqlspec/adapters/sqlite/config.py +85 -16
  96. sqlspec/adapters/sqlite/data_dictionary.py +34 -2
  97. sqlspec/adapters/sqlite/driver.py +120 -52
  98. sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
  99. sqlspec/adapters/sqlite/litestar/store.py +318 -0
  100. sqlspec/adapters/sqlite/pool.py +5 -5
  101. sqlspec/base.py +45 -26
  102. sqlspec/builder/__init__.py +73 -4
  103. sqlspec/builder/_base.py +91 -58
  104. sqlspec/builder/_column.py +5 -5
  105. sqlspec/builder/_ddl.py +98 -89
  106. sqlspec/builder/_delete.py +5 -4
  107. sqlspec/builder/_dml.py +388 -0
  108. sqlspec/{_sql.py → builder/_factory.py} +41 -44
  109. sqlspec/builder/_insert.py +5 -82
  110. sqlspec/builder/{mixins/_join_operations.py → _join.py} +145 -143
  111. sqlspec/builder/_merge.py +446 -11
  112. sqlspec/builder/_parsing_utils.py +9 -11
  113. sqlspec/builder/_select.py +1313 -25
  114. sqlspec/builder/_update.py +11 -42
  115. sqlspec/cli.py +76 -69
  116. sqlspec/config.py +231 -60
  117. sqlspec/core/__init__.py +5 -4
  118. sqlspec/core/cache.py +18 -18
  119. sqlspec/core/compiler.py +6 -8
  120. sqlspec/core/filters.py +37 -37
  121. sqlspec/core/hashing.py +9 -9
  122. sqlspec/core/parameters.py +76 -45
  123. sqlspec/core/result.py +102 -46
  124. sqlspec/core/splitter.py +16 -17
  125. sqlspec/core/statement.py +32 -31
  126. sqlspec/core/type_conversion.py +3 -2
  127. sqlspec/driver/__init__.py +1 -3
  128. sqlspec/driver/_async.py +95 -161
  129. sqlspec/driver/_common.py +133 -80
  130. sqlspec/driver/_sync.py +95 -162
  131. sqlspec/driver/mixins/_result_tools.py +20 -236
  132. sqlspec/driver/mixins/_sql_translator.py +4 -4
  133. sqlspec/exceptions.py +70 -7
  134. sqlspec/extensions/adk/__init__.py +53 -0
  135. sqlspec/extensions/adk/_types.py +51 -0
  136. sqlspec/extensions/adk/converters.py +172 -0
  137. sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +144 -0
  138. sqlspec/extensions/adk/migrations/__init__.py +0 -0
  139. sqlspec/extensions/adk/service.py +181 -0
  140. sqlspec/extensions/adk/store.py +536 -0
  141. sqlspec/extensions/aiosql/adapter.py +73 -53
  142. sqlspec/extensions/litestar/__init__.py +21 -4
  143. sqlspec/extensions/litestar/cli.py +54 -10
  144. sqlspec/extensions/litestar/config.py +59 -266
  145. sqlspec/extensions/litestar/handlers.py +46 -17
  146. sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
  147. sqlspec/extensions/litestar/migrations/__init__.py +3 -0
  148. sqlspec/extensions/litestar/plugin.py +324 -223
  149. sqlspec/extensions/litestar/providers.py +25 -25
  150. sqlspec/extensions/litestar/store.py +265 -0
  151. sqlspec/loader.py +30 -49
  152. sqlspec/migrations/base.py +200 -76
  153. sqlspec/migrations/commands.py +591 -62
  154. sqlspec/migrations/context.py +6 -9
  155. sqlspec/migrations/fix.py +199 -0
  156. sqlspec/migrations/loaders.py +47 -19
  157. sqlspec/migrations/runner.py +241 -75
  158. sqlspec/migrations/tracker.py +237 -21
  159. sqlspec/migrations/utils.py +51 -3
  160. sqlspec/migrations/validation.py +177 -0
  161. sqlspec/protocols.py +66 -36
  162. sqlspec/storage/_utils.py +98 -0
  163. sqlspec/storage/backends/fsspec.py +134 -106
  164. sqlspec/storage/backends/local.py +78 -51
  165. sqlspec/storage/backends/obstore.py +278 -162
  166. sqlspec/storage/registry.py +75 -39
  167. sqlspec/typing.py +14 -84
  168. sqlspec/utils/config_resolver.py +6 -6
  169. sqlspec/utils/correlation.py +4 -5
  170. sqlspec/utils/data_transformation.py +3 -2
  171. sqlspec/utils/deprecation.py +9 -8
  172. sqlspec/utils/fixtures.py +4 -4
  173. sqlspec/utils/logging.py +46 -6
  174. sqlspec/utils/module_loader.py +2 -2
  175. sqlspec/utils/schema.py +288 -0
  176. sqlspec/utils/serializers.py +3 -3
  177. sqlspec/utils/sync_tools.py +21 -17
  178. sqlspec/utils/text.py +1 -2
  179. sqlspec/utils/type_guards.py +111 -20
  180. sqlspec/utils/version.py +433 -0
  181. {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/METADATA +40 -21
  182. sqlspec-0.27.0.dist-info/RECORD +207 -0
  183. sqlspec/builder/mixins/__init__.py +0 -55
  184. sqlspec/builder/mixins/_cte_and_set_ops.py +0 -253
  185. sqlspec/builder/mixins/_delete_operations.py +0 -50
  186. sqlspec/builder/mixins/_insert_operations.py +0 -282
  187. sqlspec/builder/mixins/_merge_operations.py +0 -698
  188. sqlspec/builder/mixins/_order_limit_operations.py +0 -145
  189. sqlspec/builder/mixins/_pivot_operations.py +0 -157
  190. sqlspec/builder/mixins/_select_operations.py +0 -930
  191. sqlspec/builder/mixins/_update_operations.py +0 -199
  192. sqlspec/builder/mixins/_where_clause.py +0 -1298
  193. sqlspec-0.26.0.dist-info/RECORD +0 -157
  194. sqlspec-0.26.0.dist-info/licenses/NOTICE +0 -29
  195. {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/WHEEL +0 -0
  196. {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/entry_points.txt +0 -0
  197. {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/licenses/LICENSE +0 -0
sqlspec/__init__.py CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  from sqlspec import adapters, base, builder, core, driver, exceptions, extensions, loader, migrations, typing, utils
4
4
  from sqlspec.__metadata__ import __version__
5
- from sqlspec._sql import SQLFactory, sql
6
5
  from sqlspec.base import SQLSpec
7
6
  from sqlspec.builder import (
8
7
  Column,
@@ -15,7 +14,9 @@ from sqlspec.builder import (
15
14
  Merge,
16
15
  QueryBuilder,
17
16
  Select,
17
+ SQLFactory,
18
18
  Update,
19
+ sql,
19
20
  )
20
21
  from sqlspec.config import AsyncDatabaseConfig, SyncDatabaseConfig
21
22
  from sqlspec.core import (
@@ -34,16 +35,10 @@ from sqlspec.core import (
34
35
  from sqlspec.core import filters as filters
35
36
  from sqlspec.driver import AsyncDriverAdapterBase, ExecutionResult, SyncDriverAdapterBase
36
37
  from sqlspec.loader import SQLFile, SQLFileLoader
37
- from sqlspec.typing import (
38
- ConnectionT,
39
- DictRow,
40
- ModelDTOT,
41
- ModelT,
42
- PoolT,
43
- RowT,
44
- StatementParameters,
45
- SupportedSchemaModel,
46
- )
38
+ from sqlspec.typing import ConnectionT, PoolT, SchemaT, StatementParameters, SupportedSchemaModel
39
+ from sqlspec.utils.logging import suppress_erroneous_sqlglot_log_messages
40
+
41
+ suppress_erroneous_sqlglot_log_messages()
47
42
 
48
43
  __all__ = (
49
44
  "SQL",
@@ -57,26 +52,23 @@ __all__ = (
57
52
  "ConnectionT",
58
53
  "CreateTable",
59
54
  "Delete",
60
- "DictRow",
61
55
  "DropTable",
62
56
  "ExecutionResult",
63
57
  "FunctionColumn",
64
58
  "Insert",
65
59
  "Merge",
66
- "ModelDTOT",
67
- "ModelT",
68
60
  "ParameterConverter",
69
61
  "ParameterProcessor",
70
62
  "ParameterStyle",
71
63
  "ParameterStyleConfig",
72
64
  "PoolT",
73
65
  "QueryBuilder",
74
- "RowT",
75
66
  "SQLFactory",
76
67
  "SQLFile",
77
68
  "SQLFileLoader",
78
69
  "SQLResult",
79
70
  "SQLSpec",
71
+ "SchemaT",
80
72
  "Select",
81
73
  "Statement",
82
74
  "StatementConfig",
sqlspec/_serialization.py CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  Provides a Protocol-based serialization system that users can extend.
4
4
  Supports msgspec, orjson, and standard library JSON with automatic fallback.
5
+
6
+ Features optional numpy array serialization when numpy is installed.
7
+ Arrays are automatically converted to lists during JSON encoding.
5
8
  """
6
9
 
7
10
  import contextlib
@@ -9,19 +12,25 @@ import datetime
9
12
  import enum
10
13
  import json
11
14
  from abc import ABC, abstractmethod
12
- from typing import Any, Final, Literal, Optional, Protocol, Union, overload
15
+ from typing import Any, Final, Literal, Protocol, overload
13
16
 
17
+ from sqlspec._typing import NUMPY_INSTALLED
14
18
  from sqlspec.typing import MSGSPEC_INSTALLED, ORJSON_INSTALLED, PYDANTIC_INSTALLED, BaseModel
15
19
 
16
20
 
17
- def _type_to_string(value: Any) -> str: # pragma: no cover
21
+ def _type_to_string(value: Any) -> Any: # pragma: no cover
18
22
  """Convert special types to strings for JSON serialization.
19
23
 
24
+ Handles datetime, date, enums, Pydantic models, and numpy arrays.
25
+
20
26
  Args:
21
27
  value: Value to convert.
22
28
 
23
29
  Returns:
24
- String representation of the value.
30
+ Serializable representation of the value (string, list, dict, etc.).
31
+
32
+ Raises:
33
+ TypeError: If value cannot be serialized.
25
34
  """
26
35
  if isinstance(value, datetime.datetime):
27
36
  return convert_datetime_to_gmt_iso(value)
@@ -31,10 +40,16 @@ def _type_to_string(value: Any) -> str: # pragma: no cover
31
40
  return str(value.value)
32
41
  if PYDANTIC_INSTALLED and isinstance(value, BaseModel):
33
42
  return value.model_dump_json()
43
+ if NUMPY_INSTALLED:
44
+ import numpy as np
45
+
46
+ if isinstance(value, np.ndarray):
47
+ return value.tolist()
34
48
  try:
35
49
  return str(value)
36
50
  except Exception as exc:
37
- raise TypeError from exc
51
+ msg = f"Cannot serialize {type(value).__name__}"
52
+ raise TypeError(msg) from exc
38
53
 
39
54
 
40
55
  class JSONSerializer(Protocol):
@@ -43,7 +58,7 @@ class JSONSerializer(Protocol):
43
58
  Users can implement this protocol to create custom serializers.
44
59
  """
45
60
 
46
- def encode(self, data: Any, *, as_bytes: bool = False) -> Union[str, bytes]:
61
+ def encode(self, data: Any, *, as_bytes: bool = False) -> str | bytes:
47
62
  """Encode data to JSON.
48
63
 
49
64
  Args:
@@ -55,7 +70,7 @@ class JSONSerializer(Protocol):
55
70
  """
56
71
  ...
57
72
 
58
- def decode(self, data: Union[str, bytes], *, decode_bytes: bool = True) -> Any:
73
+ def decode(self, data: str | bytes, *, decode_bytes: bool = True) -> Any:
59
74
  """Decode from JSON.
60
75
 
61
76
  Args:
@@ -74,18 +89,18 @@ class BaseJSONSerializer(ABC):
74
89
  __slots__ = ()
75
90
 
76
91
  @abstractmethod
77
- def encode(self, data: Any, *, as_bytes: bool = False) -> Union[str, bytes]:
92
+ def encode(self, data: Any, *, as_bytes: bool = False) -> str | bytes:
78
93
  """Encode data to JSON."""
79
94
  ...
80
95
 
81
96
  @abstractmethod
82
- def decode(self, data: Union[str, bytes], *, decode_bytes: bool = True) -> Any:
97
+ def decode(self, data: str | bytes, *, decode_bytes: bool = True) -> Any:
83
98
  """Decode from JSON."""
84
99
  ...
85
100
 
86
101
 
87
102
  class MsgspecSerializer(BaseJSONSerializer):
88
- """Msgspec-based JSON serializer for optimal performance."""
103
+ """Msgspec-based JSON serializer."""
89
104
 
90
105
  __slots__ = ("_decoder", "_encoder")
91
106
 
@@ -96,7 +111,7 @@ class MsgspecSerializer(BaseJSONSerializer):
96
111
  self._encoder: Final[Encoder] = Encoder(enc_hook=_type_to_string)
97
112
  self._decoder: Final[Decoder] = Decoder()
98
113
 
99
- def encode(self, data: Any, *, as_bytes: bool = False) -> Union[str, bytes]:
114
+ def encode(self, data: Any, *, as_bytes: bool = False) -> str | bytes:
100
115
  """Encode data using msgspec."""
101
116
  try:
102
117
  if as_bytes:
@@ -107,7 +122,7 @@ class MsgspecSerializer(BaseJSONSerializer):
107
122
  return OrjsonSerializer().encode(data, as_bytes=as_bytes)
108
123
  return StandardLibSerializer().encode(data, as_bytes=as_bytes)
109
124
 
110
- def decode(self, data: Union[str, bytes], *, decode_bytes: bool = True) -> Any:
125
+ def decode(self, data: str | bytes, *, decode_bytes: bool = True) -> Any:
111
126
  """Decode data using msgspec."""
112
127
  if isinstance(data, bytes):
113
128
  if decode_bytes:
@@ -128,25 +143,40 @@ class MsgspecSerializer(BaseJSONSerializer):
128
143
 
129
144
 
130
145
  class OrjsonSerializer(BaseJSONSerializer):
131
- """Orjson-based JSON serializer with native datetime/UUID support."""
146
+ """Orjson-based JSON serializer with native datetime/UUID support.
147
+
148
+ Automatically enables numpy serialization if numpy is installed.
149
+ """
132
150
 
133
151
  __slots__ = ()
134
152
 
135
- def encode(self, data: Any, *, as_bytes: bool = False) -> Union[str, bytes]:
136
- """Encode data using orjson."""
153
+ def encode(self, data: Any, *, as_bytes: bool = False) -> str | bytes:
154
+ """Encode data using orjson.
155
+
156
+ Args:
157
+ data: Data to encode.
158
+ as_bytes: Whether to return bytes instead of string.
159
+
160
+ Returns:
161
+ JSON string or bytes depending on as_bytes parameter.
162
+ """
137
163
  from orjson import (
138
164
  OPT_NAIVE_UTC, # pyright: ignore[reportUnknownVariableType]
139
- OPT_SERIALIZE_NUMPY, # pyright: ignore[reportUnknownVariableType]
140
165
  OPT_SERIALIZE_UUID, # pyright: ignore[reportUnknownVariableType]
141
166
  )
142
167
  from orjson import dumps as _orjson_dumps # pyright: ignore[reportMissingImports]
143
168
 
144
- result = _orjson_dumps(
145
- data, default=_type_to_string, option=OPT_SERIALIZE_NUMPY | OPT_NAIVE_UTC | OPT_SERIALIZE_UUID
146
- )
169
+ options = OPT_NAIVE_UTC | OPT_SERIALIZE_UUID
170
+
171
+ if NUMPY_INSTALLED:
172
+ from orjson import OPT_SERIALIZE_NUMPY # pyright: ignore[reportUnknownVariableType]
173
+
174
+ options |= OPT_SERIALIZE_NUMPY
175
+
176
+ result = _orjson_dumps(data, default=_type_to_string, option=options)
147
177
  return result if as_bytes else result.decode("utf-8")
148
178
 
149
- def decode(self, data: Union[str, bytes], *, decode_bytes: bool = True) -> Any:
179
+ def decode(self, data: str | bytes, *, decode_bytes: bool = True) -> Any:
150
180
  """Decode data using orjson."""
151
181
  from orjson import loads as _orjson_loads # pyright: ignore[reportMissingImports]
152
182
 
@@ -162,12 +192,12 @@ class StandardLibSerializer(BaseJSONSerializer):
162
192
 
163
193
  __slots__ = ()
164
194
 
165
- def encode(self, data: Any, *, as_bytes: bool = False) -> Union[str, bytes]:
195
+ def encode(self, data: Any, *, as_bytes: bool = False) -> str | bytes:
166
196
  """Encode data using standard library json."""
167
197
  json_str = json.dumps(data, default=_type_to_string)
168
198
  return json_str.encode("utf-8") if as_bytes else json_str
169
199
 
170
- def decode(self, data: Union[str, bytes], *, decode_bytes: bool = True) -> Any:
200
+ def decode(self, data: str | bytes, *, decode_bytes: bool = True) -> Any:
171
201
  """Decode data using standard library json."""
172
202
  if isinstance(data, bytes):
173
203
  if decode_bytes:
@@ -176,7 +206,7 @@ class StandardLibSerializer(BaseJSONSerializer):
176
206
  return json.loads(data)
177
207
 
178
208
 
179
- _default_serializer: Optional[JSONSerializer] = None
209
+ _default_serializer: JSONSerializer | None = None
180
210
 
181
211
 
182
212
  def get_default_serializer() -> JSONSerializer:
@@ -213,8 +243,8 @@ def encode_json(data: Any, *, as_bytes: Literal[False] = ...) -> str: ... # pra
213
243
  def encode_json(data: Any, *, as_bytes: Literal[True]) -> bytes: ... # pragma: no cover
214
244
 
215
245
 
216
- def encode_json(data: Any, *, as_bytes: bool = False) -> Union[str, bytes]:
217
- """Encode to JSON, optionally returning bytes for optimal performance.
246
+ def encode_json(data: Any, *, as_bytes: bool = False) -> str | bytes:
247
+ """Encode to JSON, optionally returning bytes.
218
248
 
219
249
  Args:
220
250
  data: The data to encode.
@@ -226,7 +256,7 @@ def encode_json(data: Any, *, as_bytes: bool = False) -> Union[str, bytes]:
226
256
  return get_default_serializer().encode(data, as_bytes=as_bytes)
227
257
 
228
258
 
229
- def decode_json(data: Union[str, bytes], *, decode_bytes: bool = True) -> Any:
259
+ def decode_json(data: str | bytes, *, decode_bytes: bool = True) -> Any:
230
260
  """Decode from JSON string or bytes efficiently.
231
261
 
232
262
  Args:
sqlspec/_typing.py CHANGED
@@ -6,9 +6,9 @@ from collections.abc import Iterable, Mapping
6
6
  from dataclasses import dataclass
7
7
  from enum import Enum
8
8
  from importlib.util import find_spec
9
- from typing import Any, ClassVar, Final, Optional, Protocol, Union, cast, runtime_checkable
9
+ from typing import Any, ClassVar, Final, Literal, Protocol, cast, runtime_checkable
10
10
 
11
- from typing_extensions import Literal, TypeVar, dataclass_transform
11
+ from typing_extensions import TypeVar, dataclass_transform
12
12
 
13
13
 
14
14
  @runtime_checkable
@@ -38,15 +38,15 @@ class BaseModelStub:
38
38
  self,
39
39
  /,
40
40
  *,
41
- include: "Optional[Any]" = None, # noqa: ARG002
42
- exclude: "Optional[Any]" = None, # noqa: ARG002
43
- context: "Optional[Any]" = None, # noqa: ARG002
41
+ include: "Any | None" = None, # noqa: ARG002
42
+ exclude: "Any | None" = None, # noqa: ARG002
43
+ context: "Any | None" = None, # noqa: ARG002
44
44
  by_alias: bool = False, # noqa: ARG002
45
45
  exclude_unset: bool = False, # noqa: ARG002
46
46
  exclude_defaults: bool = False, # noqa: ARG002
47
47
  exclude_none: bool = False, # noqa: ARG002
48
48
  round_trip: bool = False, # noqa: ARG002
49
- warnings: "Union[bool, Literal['none', 'warn', 'error']]" = True, # noqa: ARG002
49
+ warnings: "bool | Literal['none', 'warn', 'error']" = True, # noqa: ARG002
50
50
  serialize_as_any: bool = False, # noqa: ARG002
51
51
  ) -> "dict[str, Any]":
52
52
  """Placeholder implementation."""
@@ -56,15 +56,15 @@ class BaseModelStub:
56
56
  self,
57
57
  /,
58
58
  *,
59
- include: "Optional[Any]" = None, # noqa: ARG002
60
- exclude: "Optional[Any]" = None, # noqa: ARG002
61
- context: "Optional[Any]" = None, # noqa: ARG002
59
+ include: "Any | None" = None, # noqa: ARG002
60
+ exclude: "Any | None" = None, # noqa: ARG002
61
+ context: "Any | None" = None, # noqa: ARG002
62
62
  by_alias: bool = False, # noqa: ARG002
63
63
  exclude_unset: bool = False, # noqa: ARG002
64
64
  exclude_defaults: bool = False, # noqa: ARG002
65
65
  exclude_none: bool = False, # noqa: ARG002
66
66
  round_trip: bool = False, # noqa: ARG002
67
- warnings: "Union[bool, Literal['none', 'warn', 'error']]" = True, # noqa: ARG002
67
+ warnings: "bool | Literal['none', 'warn', 'error']" = True, # noqa: ARG002
68
68
  serialize_as_any: bool = False, # noqa: ARG002
69
69
  ) -> str:
70
70
  """Placeholder implementation."""
@@ -78,9 +78,9 @@ class TypeAdapterStub:
78
78
  self,
79
79
  type: Any, # noqa: A002
80
80
  *,
81
- config: "Optional[Any]" = None, # noqa: ARG002
81
+ config: "Any | None" = None, # noqa: ARG002
82
82
  _parent_depth: int = 2, # noqa: ARG002
83
- module: "Optional[str]" = None, # noqa: ARG002
83
+ module: "str | None" = None, # noqa: ARG002
84
84
  ) -> None:
85
85
  """Initialize."""
86
86
  self._type = type
@@ -90,10 +90,10 @@ class TypeAdapterStub:
90
90
  object: Any,
91
91
  /,
92
92
  *,
93
- strict: "Optional[bool]" = None, # noqa: ARG002
94
- from_attributes: "Optional[bool]" = None, # noqa: ARG002
95
- context: "Optional[dict[str, Any]]" = None, # noqa: ARG002
96
- experimental_allow_partial: "Union[bool, Literal['off', 'on', 'trailing-strings']]" = False, # noqa: ARG002
93
+ strict: "bool | None" = None, # noqa: ARG002
94
+ from_attributes: "bool | None" = None, # noqa: ARG002
95
+ context: "dict[str, Any] | None" = None, # noqa: ARG002
96
+ experimental_allow_partial: "bool | Literal['off', 'on', 'trailing-strings']" = False, # noqa: ARG002
97
97
  ) -> Any:
98
98
  """Validate Python object."""
99
99
  return object
@@ -143,8 +143,8 @@ def convert_stub( # noqa: PLR0913
143
143
  *,
144
144
  strict: bool = True, # noqa: ARG001
145
145
  from_attributes: bool = False, # noqa: ARG001
146
- dec_hook: "Optional[Any]" = None, # noqa: ARG001
147
- builtin_types: "Optional[Any]" = None, # noqa: ARG001
146
+ dec_hook: "Any | None" = None, # noqa: ARG001
147
+ builtin_types: "Any | None" = None, # noqa: ARG001
148
148
  str_keys: bool = False, # noqa: ARG001
149
149
  ) -> Any:
150
150
  """Placeholder implementation."""
@@ -308,7 +308,7 @@ class EmptyEnum(Enum):
308
308
  EMPTY = 0
309
309
 
310
310
 
311
- EmptyType = Union[Literal[EmptyEnum.EMPTY], UnsetType]
311
+ EmptyType = Literal[EmptyEnum.EMPTY] | UnsetType
312
312
  Empty: Final = EmptyEnum.EMPTY
313
313
 
314
314
 
@@ -336,18 +336,18 @@ class ArrowTableResult(Protocol):
336
336
  def from_arrays(
337
337
  self,
338
338
  arrays: list[Any],
339
- names: "Optional[list[str]]" = None,
340
- schema: "Optional[Any]" = None,
341
- metadata: "Optional[Mapping[str, Any]]" = None,
339
+ names: "list[str] | None" = None,
340
+ schema: "Any | None" = None,
341
+ metadata: "Mapping[str, Any] | None" = None,
342
342
  ) -> Any:
343
343
  return None
344
344
 
345
345
  def from_pydict(
346
- self, mapping: dict[str, Any], schema: "Optional[Any]" = None, metadata: "Optional[Mapping[str, Any]]" = None
346
+ self, mapping: dict[str, Any], schema: "Any | None" = None, metadata: "Mapping[str, Any] | None" = None
347
347
  ) -> Any:
348
348
  return None
349
349
 
350
- def from_batches(self, batches: Iterable[Any], schema: Optional[Any] = None) -> Any:
350
+ def from_batches(self, batches: Iterable[Any], schema: Any | None = None) -> Any:
351
351
  return None
352
352
 
353
353
 
@@ -373,7 +373,7 @@ class ArrowRecordBatchResult(Protocol):
373
373
  def column(self, i: int) -> Any:
374
374
  return None
375
375
 
376
- def slice(self, offset: int = 0, length: "Optional[int]" = None) -> Any:
376
+ def slice(self, offset: int = 0, length: "int | None" = None) -> Any:
377
377
  return None
378
378
 
379
379
 
@@ -389,6 +389,24 @@ except ImportError:
389
389
  PYARROW_INSTALLED = False # pyright: ignore[reportConstantRedefinition]
390
390
 
391
391
 
392
+ @runtime_checkable
393
+ class NumpyArrayStub(Protocol):
394
+ """Protocol stub for numpy.ndarray when numpy is not installed.
395
+
396
+ Provides minimal interface for type checking and serialization support.
397
+ """
398
+
399
+ def tolist(self) -> "list[Any]":
400
+ """Convert array to Python list."""
401
+ ...
402
+
403
+
404
+ try:
405
+ from numpy import ndarray as NumpyArray # noqa: N812
406
+ except ImportError:
407
+ NumpyArray = NumpyArrayStub # type: ignore[assignment,misc]
408
+
409
+
392
410
  try:
393
411
  from opentelemetry import trace # pyright: ignore[reportMissingImports, reportAssignmentType]
394
412
  from opentelemetry.trace import ( # pyright: ignore[reportMissingImports, reportAssignmentType]
@@ -409,16 +427,16 @@ except ImportError:
409
427
  def record_exception(
410
428
  self,
411
429
  exception: "Exception",
412
- attributes: "Optional[Mapping[str, Any]]" = None,
413
- timestamp: "Optional[int]" = None,
430
+ attributes: "Mapping[str, Any] | None" = None,
431
+ timestamp: "int | None" = None,
414
432
  escaped: bool = False,
415
433
  ) -> None:
416
434
  return None
417
435
 
418
- def set_status(self, status: Any, description: "Optional[str]" = None) -> None:
436
+ def set_status(self, status: Any, description: "str | None" = None) -> None:
419
437
  return None
420
438
 
421
- def end(self, end_time: "Optional[int]" = None) -> None:
439
+ def end(self, end_time: "int | None" = None) -> None:
422
440
  return None
423
441
 
424
442
  def __enter__(self) -> "Span":
@@ -445,8 +463,8 @@ except ImportError:
445
463
  def get_tracer(
446
464
  self,
447
465
  instrumenting_module_name: str,
448
- instrumenting_library_version: "Optional[str]" = None,
449
- schema_url: "Optional[str]" = None,
466
+ instrumenting_library_version: "str | None" = None,
467
+ schema_url: "str | None" = None,
450
468
  tracer_provider: Any = None,
451
469
  ) -> Tracer:
452
470
  return Tracer() # type: ignore[abstract] # pragma: no cover
@@ -522,9 +540,6 @@ try:
522
540
  from aiosql.types import ( # pyright: ignore[reportMissingImports, reportAssignmentType]
523
541
  AsyncDriverAdapterProtocol as AiosqlAsyncProtocol, # pyright: ignore[reportMissingImports, reportAssignmentType]
524
542
  )
525
- from aiosql.types import ( # pyright: ignore[reportMissingImports, reportAssignmentType]
526
- DriverAdapterProtocol as AiosqlProtocol, # pyright: ignore[reportMissingImports, reportAssignmentType]
527
- )
528
543
  from aiosql.types import ParamType as AiosqlParamType # pyright: ignore[reportMissingImports, reportAssignmentType]
529
544
  from aiosql.types import (
530
545
  SQLOperationType as AiosqlSQLOperationType, # pyright: ignore[reportMissingImports, reportAssignmentType]
@@ -553,7 +568,7 @@ except ImportError:
553
568
  aiosql = _AiosqlShim() # type: ignore[assignment]
554
569
 
555
570
  # Placeholder types for aiosql protocols
556
- AiosqlParamType = Union[dict[str, Any], list[Any], tuple[Any, ...], None] # type: ignore[misc]
571
+ AiosqlParamType = Any # type: ignore[misc]
557
572
 
558
573
  class AiosqlSQLOperationType(Enum): # type: ignore[no-redef]
559
574
  """Enumeration of aiosql operation types."""
@@ -566,12 +581,6 @@ except ImportError:
566
581
  SELECT_ONE = 5
567
582
  SELECT_VALUE = 6
568
583
 
569
- @runtime_checkable
570
- class AiosqlProtocol(Protocol): # type: ignore[no-redef]
571
- """Placeholder for aiosql DriverAdapterProtocol"""
572
-
573
- def process_sql(self, query_name: str, op_type: Any, sql: str) -> str: ...
574
-
575
584
  @runtime_checkable
576
585
  class AiosqlSyncProtocol(Protocol): # type: ignore[no-redef]
577
586
  """Placeholder for aiosql SyncDriverAdapterProtocol"""
@@ -580,16 +589,16 @@ except ImportError:
580
589
 
581
590
  def process_sql(self, query_name: str, op_type: Any, sql: str) -> str: ...
582
591
  def select(
583
- self, conn: Any, query_name: str, sql: str, parameters: Any, record_class: "Optional[Any]" = None
592
+ self, conn: Any, query_name: str, sql: str, parameters: Any, record_class: "Any | None" = None
584
593
  ) -> Any: ...
585
594
  def select_one(
586
- self, conn: Any, query_name: str, sql: str, parameters: Any, record_class: "Optional[Any]" = None
587
- ) -> "Optional[Any]": ...
588
- def select_value(self, conn: Any, query_name: str, sql: str, parameters: Any) -> "Optional[Any]": ...
595
+ self, conn: Any, query_name: str, sql: str, parameters: Any, record_class: "Any | None" = None
596
+ ) -> "Any | None": ...
597
+ def select_value(self, conn: Any, query_name: str, sql: str, parameters: Any) -> "Any | None": ...
589
598
  def select_cursor(self, conn: Any, query_name: str, sql: str, parameters: Any) -> Any: ...
590
599
  def insert_update_delete(self, conn: Any, query_name: str, sql: str, parameters: Any) -> int: ...
591
600
  def insert_update_delete_many(self, conn: Any, query_name: str, sql: str, parameters: Any) -> int: ...
592
- def insert_returning(self, conn: Any, query_name: str, sql: str, parameters: Any) -> "Optional[Any]": ...
601
+ def insert_returning(self, conn: Any, query_name: str, sql: str, parameters: Any) -> "Any | None": ...
593
602
 
594
603
  @runtime_checkable
595
604
  class AiosqlAsyncProtocol(Protocol): # type: ignore[no-redef]
@@ -599,16 +608,16 @@ except ImportError:
599
608
 
600
609
  def process_sql(self, query_name: str, op_type: Any, sql: str) -> str: ...
601
610
  async def select(
602
- self, conn: Any, query_name: str, sql: str, parameters: Any, record_class: "Optional[Any]" = None
611
+ self, conn: Any, query_name: str, sql: str, parameters: Any, record_class: "Any | None" = None
603
612
  ) -> Any: ...
604
613
  async def select_one(
605
- self, conn: Any, query_name: str, sql: str, parameters: Any, record_class: "Optional[Any]" = None
606
- ) -> "Optional[Any]": ...
607
- async def select_value(self, conn: Any, query_name: str, sql: str, parameters: Any) -> "Optional[Any]": ...
614
+ self, conn: Any, query_name: str, sql: str, parameters: Any, record_class: "Any | None" = None
615
+ ) -> "Any | None": ...
616
+ async def select_value(self, conn: Any, query_name: str, sql: str, parameters: Any) -> "Any | None": ...
608
617
  async def select_cursor(self, conn: Any, query_name: str, sql: str, parameters: Any) -> Any: ...
609
618
  async def insert_update_delete(self, conn: Any, query_name: str, sql: str, parameters: Any) -> None: ...
610
619
  async def insert_update_delete_many(self, conn: Any, query_name: str, sql: str, parameters: Any) -> None: ...
611
- async def insert_returning(self, conn: Any, query_name: str, sql: str, parameters: Any) -> "Optional[Any]": ...
620
+ async def insert_returning(self, conn: Any, query_name: str, sql: str, parameters: Any) -> "Any | None": ...
612
621
 
613
622
  AIOSQL_INSTALLED = False # pyright: ignore[reportConstantRedefinition] # pyright: ignore[reportConstantRedefinition]
614
623
 
@@ -638,7 +647,6 @@ __all__ = (
638
647
  "UNSET_STUB",
639
648
  "AiosqlAsyncProtocol",
640
649
  "AiosqlParamType",
641
- "AiosqlProtocol",
642
650
  "AiosqlSQLOperationType",
643
651
  "AiosqlSyncProtocol",
644
652
  "ArrowRecordBatch",
@@ -660,6 +668,8 @@ __all__ = (
660
668
  "FailFastStub",
661
669
  "Gauge",
662
670
  "Histogram",
671
+ "NumpyArray",
672
+ "NumpyArrayStub",
663
673
  "Span",
664
674
  "Status",
665
675
  "StatusCode",
@@ -4,7 +4,7 @@ from typing import TYPE_CHECKING
4
4
  from adbc_driver_manager.dbapi import Connection
5
5
 
6
6
  if TYPE_CHECKING:
7
- from typing_extensions import TypeAlias
7
+ from typing import TypeAlias
8
8
 
9
9
  AdbcConnection: TypeAlias = Connection
10
10
  else:
@@ -0,0 +1,5 @@
1
+ """ADBC ADK integration for Google Agent Development Kit."""
2
+
3
+ from sqlspec.adapters.adbc.adk.store import AdbcADKStore
4
+
5
+ __all__ = ("AdbcADKStore",)