sqlspec 0.65.0__py3-none-any.whl → 0.66.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.
Files changed (36) hide show
  1. sqlspec/adapters/arrow_odbc/driver.py +1 -1
  2. sqlspec/adapters/spanner/__init__.py +23 -1
  3. sqlspec/adapters/spanner/_typing.py +150 -20
  4. sqlspec/adapters/spanner/adk/__init__.py +10 -1
  5. sqlspec/adapters/spanner/adk/store.py +1348 -680
  6. sqlspec/adapters/spanner/config.py +622 -201
  7. sqlspec/adapters/spanner/core.py +567 -3
  8. sqlspec/adapters/spanner/data_dictionary.py +268 -9
  9. sqlspec/adapters/spanner/driver.py +776 -261
  10. sqlspec/adapters/spanner/events/__init__.py +2 -2
  11. sqlspec/adapters/spanner/events/store.py +92 -58
  12. sqlspec/adapters/spanner/litestar/__init__.py +2 -2
  13. sqlspec/adapters/spanner/litestar/store.py +305 -124
  14. sqlspec/adapters/spanner/type_converter.py +74 -11
  15. sqlspec/builder/_base.py +21 -9
  16. sqlspec/builder/_parsing_utils.py +1 -1
  17. sqlspec/core/_operators.py +8 -4
  18. sqlspec/core/filters.py +1 -1
  19. sqlspec/core/parameters/_converter.py +1 -1
  20. sqlspec/core/query_modifiers.py +1 -2
  21. sqlspec/core/splitter.py +3 -1
  22. sqlspec/core/statement.py +1 -1
  23. sqlspec/dialects/spanner/_generators.py +45 -0
  24. sqlspec/dialects/spanner/_parsers.py +92 -6
  25. sqlspec/extensions/adk/memory/store.py +10 -1
  26. sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +8 -2
  27. sqlspec/extensions/adk/store.py +9 -1
  28. sqlspec/extensions/sanic/extension.py +2 -2
  29. sqlspec/migrations/base.py +1 -1
  30. sqlspec/migrations/squash.py +1 -1
  31. sqlspec/protocols.py +2 -0
  32. {sqlspec-0.65.0.dist-info → sqlspec-0.66.0.dist-info}/METADATA +2 -2
  33. {sqlspec-0.65.0.dist-info → sqlspec-0.66.0.dist-info}/RECORD +36 -36
  34. {sqlspec-0.65.0.dist-info → sqlspec-0.66.0.dist-info}/WHEEL +0 -0
  35. {sqlspec-0.65.0.dist-info → sqlspec-0.66.0.dist-info}/entry_points.txt +0 -0
  36. {sqlspec-0.65.0.dist-info → sqlspec-0.66.0.dist-info}/licenses/LICENSE +0 -0
@@ -574,7 +574,7 @@ def _inline_mssql_pagination_parameters(
574
574
 
575
575
  if not consumed:
576
576
  return sql, parameters
577
- for position, value in reversed(replacements):
577
+ for position, value in replacements[::-1]:
578
578
  sql = sql[:position] + value + sql[position + 1 :]
579
579
  return sql, [value for index, value in enumerate(parameters) if index not in consumed]
580
580
 
@@ -1,13 +1,26 @@
1
1
  """Google Cloud Spanner Adapter."""
2
2
 
3
+ from sqlspec.adapters.spanner._typing import (
4
+ SpannerAsyncConnection,
5
+ SpannerAsyncCursor,
6
+ SpannerSyncConnection,
7
+ SpannerSyncCursor,
8
+ )
3
9
  from sqlspec.adapters.spanner.config import (
10
+ SpannerAsyncConfig,
4
11
  SpannerConnectionParams,
5
12
  SpannerDriverFeatures,
6
13
  SpannerPoolParams,
7
14
  SpannerSyncConfig,
8
15
  build_connection_config,
9
16
  )
10
- from sqlspec.adapters.spanner.driver import SpannerSyncDriver
17
+ from sqlspec.adapters.spanner.core import default_statement_config
18
+ from sqlspec.adapters.spanner.driver import (
19
+ SpannerAsyncDriver,
20
+ SpannerAsyncExceptionHandler,
21
+ SpannerSyncDriver,
22
+ SpannerSyncExceptionHandler,
23
+ )
11
24
  from sqlspec.adapters.spanner.type_converter import (
12
25
  bytes_to_spanner,
13
26
  coerce_params_for_spanner,
@@ -19,14 +32,23 @@ from sqlspec.adapters.spanner.type_converter import (
19
32
  )
20
33
 
21
34
  __all__ = (
35
+ "SpannerAsyncConfig",
36
+ "SpannerAsyncConnection",
37
+ "SpannerAsyncCursor",
38
+ "SpannerAsyncDriver",
39
+ "SpannerAsyncExceptionHandler",
22
40
  "SpannerConnectionParams",
23
41
  "SpannerDriverFeatures",
24
42
  "SpannerPoolParams",
25
43
  "SpannerSyncConfig",
44
+ "SpannerSyncConnection",
45
+ "SpannerSyncCursor",
26
46
  "SpannerSyncDriver",
47
+ "SpannerSyncExceptionHandler",
27
48
  "build_connection_config",
28
49
  "bytes_to_spanner",
29
50
  "coerce_params_for_spanner",
51
+ "default_statement_config",
30
52
  "infer_spanner_param_types",
31
53
  "spanner_json",
32
54
  "spanner_to_bytes",
@@ -18,8 +18,12 @@ class _UnavailableSpannerTransaction:
18
18
  """Fallback Spanner transaction class when google-cloud-spanner is unavailable."""
19
19
 
20
20
 
21
+ class _UnavailableSpannerAsyncTransaction:
22
+ """Fallback Spanner async transaction class when google-cloud-spanner is unavailable."""
23
+
24
+
21
25
  if TYPE_CHECKING:
22
- from collections.abc import Callable
26
+ from collections.abc import Awaitable, Callable
23
27
  from types import TracebackType
24
28
  from typing import TypeAlias
25
29
 
@@ -37,6 +41,22 @@ if TYPE_CHECKING:
37
41
  from google.cloud.spanner_v1 import ExecuteSqlRequest as SpannerExecuteSqlRequest
38
42
  from google.cloud.spanner_v1 import RequestOptions as SpannerRequestOptions
39
43
  from google.cloud.spanner_v1 import param_types as spanner_param_types
44
+ from google.cloud.spanner_v1._async.batch import Batch as SpannerAsyncBatch
45
+ from google.cloud.spanner_v1._async.batch import MutationGroups as SpannerAsyncMutationGroups
46
+ from google.cloud.spanner_v1._async.client import Client as SpannerAsyncClient
47
+ from google.cloud.spanner_v1._async.database import Database as SpannerAsyncDatabase
48
+ from google.cloud.spanner_v1._async.database import SnapshotCheckout as SpannerAsyncSnapshotCheckout
49
+ from google.cloud.spanner_v1._async.database_sessions_manager import TransactionType as SpannerAsyncTransactionType
50
+ from google.cloud.spanner_v1._async.pool import AbstractSessionPool as SpannerAsyncAbstractSessionPool
51
+ from google.cloud.spanner_v1._async.pool import BurstyPool as SpannerAsyncBurstyPool
52
+ from google.cloud.spanner_v1._async.pool import FixedSizePool as SpannerAsyncFixedSizePool
53
+ from google.cloud.spanner_v1._async.pool import PingingPool as SpannerAsyncPingingPool
54
+ from google.cloud.spanner_v1._async.pool import TransactionPingingPool as SpannerAsyncTransactionPingingPool
55
+ from google.cloud.spanner_v1._async.session import Session as SpannerAsyncSession
56
+ from google.cloud.spanner_v1._async.snapshot import Snapshot as SpannerAsyncSnapshot
57
+ from google.cloud.spanner_v1._async.streamed import StreamedResultSet as SpannerAsyncStreamedResultSet
58
+ from google.cloud.spanner_v1._async.transaction import Transaction as _SpannerAsyncTransaction
59
+ from google.cloud.spanner_v1.data_types import Interval as SpannerInterval
40
60
  from google.cloud.spanner_v1.data_types import JsonObject as SpannerJsonObject
41
61
  from google.cloud.spanner_v1.database import Database as SpannerDatabase
42
62
  from google.cloud.spanner_v1.database import SnapshotCheckout
@@ -45,21 +65,27 @@ if TYPE_CHECKING:
45
65
  from google.cloud.spanner_v1.pool import BurstyPool as SpannerBurstyPool
46
66
  from google.cloud.spanner_v1.pool import FixedSizePool as SpannerFixedSizePool
47
67
  from google.cloud.spanner_v1.pool import PingingPool as SpannerPingingPool
68
+ from google.cloud.spanner_v1.pool import TransactionPingingPool as SpannerTransactionPingingPool
48
69
  from google.cloud.spanner_v1.snapshot import Snapshot
49
70
  from google.cloud.spanner_v1.transaction import DefaultTransactionOptions as SpannerDefaultTransactionOptions
50
71
  from google.cloud.spanner_v1.transaction import Transaction as _SpannerTransaction
51
72
  from google.cloud.spanner_v1.types.type import TypeCode as SpannerTypeCode
52
73
 
53
- from sqlspec.adapters.spanner.driver import SpannerSyncDriver
74
+ from sqlspec.adapters.spanner.driver import SpannerAsyncDriver, SpannerSyncDriver
54
75
  from sqlspec.core import StatementConfig
55
76
 
56
- SpannerConnection: TypeAlias = Snapshot | SnapshotCheckout | _SpannerTransaction
77
+ SpannerSyncConnection: TypeAlias = Snapshot | SnapshotCheckout | _SpannerTransaction
78
+ SpannerAsyncConnection: TypeAlias = (
79
+ SpannerAsyncSnapshot | SpannerAsyncSnapshotCheckout | _SpannerAsyncTransaction | SpannerAsyncBatch
80
+ )
57
81
  SpannerGoogleAPICallError: TypeAlias = _SpannerGoogleAPICallError
58
82
  SpannerTransaction: TypeAlias = _SpannerTransaction
83
+ SpannerAsyncTransaction: TypeAlias = _SpannerAsyncTransaction
59
84
 
60
85
 
61
86
  if not TYPE_CHECKING:
62
- SpannerConnection = Any
87
+ SpannerSyncConnection = Any
88
+ SpannerAsyncConnection = Any
63
89
  SpannerGoogleAPICallError = (
64
90
  import_optional_attr("google.api_core.exceptions", "GoogleAPICallError")
65
91
  or _UnavailableSpannerGoogleAPICallError
@@ -67,15 +93,35 @@ if not TYPE_CHECKING:
67
93
  SpannerTransaction = (
68
94
  import_optional_attr("google.cloud.spanner_v1.transaction", "Transaction") or _UnavailableSpannerTransaction
69
95
  )
96
+ SpannerAsyncTransaction = (
97
+ import_optional_attr("google.cloud.spanner_v1._async.transaction", "Transaction")
98
+ or _UnavailableSpannerAsyncTransaction
99
+ )
70
100
 
71
101
 
72
102
  __all__ = (
73
103
  "SpannerAbstractSessionPool",
104
+ "SpannerAsyncAbstractSessionPool",
105
+ "SpannerAsyncBatch",
106
+ "SpannerAsyncBurstyPool",
107
+ "SpannerAsyncClient",
108
+ "SpannerAsyncConnection",
109
+ "SpannerAsyncCursor",
110
+ "SpannerAsyncDatabase",
111
+ "SpannerAsyncFixedSizePool",
112
+ "SpannerAsyncMutationGroups",
113
+ "SpannerAsyncPingingPool",
114
+ "SpannerAsyncSession",
115
+ "SpannerAsyncSessionContext",
116
+ "SpannerAsyncSnapshot",
117
+ "SpannerAsyncStreamedResultSet",
118
+ "SpannerAsyncTransaction",
119
+ "SpannerAsyncTransactionPingingPool",
120
+ "SpannerAsyncTransactionType",
74
121
  "SpannerBurstyPool",
75
122
  "SpannerClient",
76
123
  "SpannerClientInfo",
77
124
  "SpannerClientOptions",
78
- "SpannerConnection",
79
125
  "SpannerCredentials",
80
126
  "SpannerDatabase",
81
127
  "SpannerDatabaseDialect",
@@ -85,14 +131,17 @@ __all__ = (
85
131
  "SpannerExecuteSqlRequest",
86
132
  "SpannerFixedSizePool",
87
133
  "SpannerGoogleAPICallError",
134
+ "SpannerInterval",
88
135
  "SpannerJsonObject",
89
136
  "SpannerNotFound",
90
137
  "SpannerPingingPool",
91
138
  "SpannerRequestOptions",
92
139
  "SpannerRetry",
93
- "SpannerSessionContext",
140
+ "SpannerSyncConnection",
94
141
  "SpannerSyncCursor",
142
+ "SpannerSyncSessionContext",
95
143
  "SpannerTransaction",
144
+ "SpannerTransactionPingingPool",
96
145
  "SpannerTransactionType",
97
146
  "SpannerTypeCode",
98
147
  "spanner_exceptions",
@@ -105,31 +154,40 @@ class SpannerSyncCursor:
105
154
 
106
155
  __slots__ = ("connection",)
107
156
 
108
- def __init__(self, connection: "SpannerConnection") -> None:
157
+ def __init__(self, connection: "SpannerSyncConnection") -> None:
109
158
  self.connection = connection
110
159
 
111
- def __enter__(self) -> "SpannerConnection":
160
+ def __enter__(self) -> "SpannerSyncConnection":
112
161
  return self.connection
113
162
 
114
163
  def __exit__(self, *_: Any) -> None:
115
164
  return None
116
165
 
117
166
 
118
- class SpannerSessionContext:
119
- """Sync context manager for Spanner sessions.
167
+ class SpannerAsyncCursor:
168
+ """Async context manager that yields the active Spanner async connection."""
169
+
170
+ __slots__ = ("connection",)
120
171
 
121
- This class is intentionally excluded from mypyc compilation to avoid ABI
122
- boundary issues. It receives callables from uncompiled config classes and
123
- instantiates compiled Driver objects, acting as a bridge between compiled
124
- and uncompiled code.
172
+ def __init__(self, connection: "SpannerAsyncConnection") -> None:
173
+ self.connection = connection
174
+
175
+ async def __aenter__(self) -> "SpannerAsyncConnection":
176
+ return self.connection
177
+
178
+ async def __aexit__(
179
+ self, exc_type: "type[BaseException] | None", exc_val: "BaseException | None", exc_tb: "TracebackType | None"
180
+ ) -> None:
181
+ return None
125
182
 
126
- Note: This context manager receives a pre-configured connection context
127
- that already has the transaction flag set. The config.provide_session()
128
- creates the connection context with the appropriate transaction setting.
129
183
 
130
- Uses callable-based connection management to decouple from config implementation.
184
+ class SpannerSyncSessionContext:
185
+ """Sync context manager for Spanner sessions.
131
186
 
132
- Spanner requires exception info in release_connection for commit/rollback decisions.
187
+ Excluded from mypyc compilation: it receives callables from uncompiled
188
+ config classes and instantiates compiled driver objects. The release
189
+ callable receives exception details so the connection context can commit
190
+ or roll back the active transaction.
133
191
  """
134
192
 
135
193
  __slots__ = (
@@ -171,15 +229,87 @@ class SpannerSessionContext:
171
229
  self, exc_type: "type[BaseException] | None", exc_val: "BaseException | None", exc_tb: "TracebackType | None"
172
230
  ) -> "bool | None":
173
231
  if self._connection is not None:
174
- self._release_connection(self._connection, exc_type=exc_type, exc_val=exc_val, exc_tb=exc_tb)
232
+ connection = self._driver.connection if self._driver is not None else self._connection
233
+ self._release_connection(connection, exc_type=exc_type, exc_val=exc_val, exc_tb=exc_tb)
234
+ self._connection = None
235
+ self._driver = None
236
+ return None
237
+
238
+
239
+ class SpannerAsyncSessionContext:
240
+ """Async context manager for Spanner sessions.
241
+
242
+ Excluded from mypyc compilation: it receives callables from uncompiled
243
+ config classes and instantiates compiled driver objects. The release
244
+ callable receives exception details so the connection context can commit
245
+ or roll back the active transaction.
246
+ """
247
+
248
+ __slots__ = (
249
+ "_acquire_connection",
250
+ "_connection",
251
+ "_driver",
252
+ "_driver_features",
253
+ "_prepare_driver",
254
+ "_release_connection",
255
+ "_statement_config",
256
+ )
257
+
258
+ def __init__(
259
+ self,
260
+ acquire_connection: "Callable[[], Awaitable[Any]]",
261
+ release_connection: "Callable[..., Awaitable[Any]]",
262
+ statement_config: "StatementConfig",
263
+ driver_features: "dict[str, Any]",
264
+ prepare_driver: "Callable[[SpannerAsyncDriver], SpannerAsyncDriver]",
265
+ ) -> None:
266
+ self._acquire_connection = acquire_connection
267
+ self._release_connection = release_connection
268
+ self._statement_config = statement_config
269
+ self._driver_features = driver_features
270
+ self._prepare_driver = prepare_driver
271
+ self._connection: Any = None
272
+ self._driver: SpannerAsyncDriver | None = None
273
+
274
+ async def __aenter__(self) -> "SpannerAsyncDriver":
275
+ from sqlspec.adapters.spanner.driver import SpannerAsyncDriver
276
+
277
+ self._connection = await self._acquire_connection()
278
+ self._driver = SpannerAsyncDriver(
279
+ connection=self._connection, statement_config=self._statement_config, driver_features=self._driver_features
280
+ )
281
+ return self._prepare_driver(self._driver)
282
+
283
+ async def __aexit__(
284
+ self, exc_type: "type[BaseException] | None", exc_val: "BaseException | None", exc_tb: "TracebackType | None"
285
+ ) -> "bool | None":
286
+ if self._connection is not None:
287
+ connection = self._driver.connection if self._driver is not None else self._connection
288
+ await self._release_connection(connection, exc_type=exc_type, exc_val=exc_val, exc_tb=exc_tb)
175
289
  self._connection = None
290
+ self._driver = None
176
291
  return None
177
292
 
178
293
 
179
294
  _LAZY_DRIVER_EXPORTS: dict[str, tuple[str, str]] = {
295
+ "SpannerAsyncTransactionType": ("google.cloud.spanner_v1._async.database_sessions_manager", "TransactionType"),
296
+ "SpannerInterval": ("google.cloud.spanner_v1.data_types", "Interval"),
297
+ "SpannerAsyncAbstractSessionPool": ("google.cloud.spanner_v1._async.pool", "AbstractSessionPool"),
298
+ "SpannerAsyncBatch": ("google.cloud.spanner_v1._async.batch", "Batch"),
299
+ "SpannerAsyncBurstyPool": ("google.cloud.spanner_v1._async.pool", "BurstyPool"),
300
+ "SpannerAsyncClient": ("google.cloud.spanner_v1._async.client", "Client"),
301
+ "SpannerAsyncDatabase": ("google.cloud.spanner_v1._async.database", "Database"),
302
+ "SpannerAsyncFixedSizePool": ("google.cloud.spanner_v1._async.pool", "FixedSizePool"),
303
+ "SpannerAsyncMutationGroups": ("google.cloud.spanner_v1._async.batch", "MutationGroups"),
304
+ "SpannerAsyncPingingPool": ("google.cloud.spanner_v1._async.pool", "PingingPool"),
305
+ "SpannerAsyncSession": ("google.cloud.spanner_v1._async.session", "Session"),
306
+ "SpannerAsyncSnapshot": ("google.cloud.spanner_v1._async.snapshot", "Snapshot"),
307
+ "SpannerAsyncStreamedResultSet": ("google.cloud.spanner_v1._async.streamed", "StreamedResultSet"),
308
+ "SpannerAsyncTransactionPingingPool": ("google.cloud.spanner_v1._async.pool", "TransactionPingingPool"),
180
309
  "SpannerBurstyPool": ("google.cloud.spanner_v1.pool", "BurstyPool"),
181
310
  "SpannerFixedSizePool": ("google.cloud.spanner_v1.pool", "FixedSizePool"),
182
311
  "SpannerPingingPool": ("google.cloud.spanner_v1.pool", "PingingPool"),
312
+ "SpannerTransactionPingingPool": ("google.cloud.spanner_v1.pool", "TransactionPingingPool"),
183
313
  "spanner_exceptions": ("google.api_core", "exceptions"),
184
314
  "SpannerNotFound": ("google.api_core.exceptions", "NotFound"),
185
315
  "SpannerClient": ("google.cloud.spanner_v1", "Client"),
@@ -3,8 +3,17 @@
3
3
  from sqlspec.adapters.spanner.adk.store import (
4
4
  SpannerADKConfig,
5
5
  SpannerADKRetentionConfig,
6
+ SpannerAsyncADKMemoryStore,
7
+ SpannerAsyncADKStore,
6
8
  SpannerSyncADKMemoryStore,
7
9
  SpannerSyncADKStore,
8
10
  )
9
11
 
10
- __all__ = ("SpannerADKConfig", "SpannerADKRetentionConfig", "SpannerSyncADKMemoryStore", "SpannerSyncADKStore")
12
+ __all__ = (
13
+ "SpannerADKConfig",
14
+ "SpannerADKRetentionConfig",
15
+ "SpannerAsyncADKMemoryStore",
16
+ "SpannerAsyncADKStore",
17
+ "SpannerSyncADKMemoryStore",
18
+ "SpannerSyncADKStore",
19
+ )