sqlspec 0.10.1__py3-none-any.whl → 0.11.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.

sqlspec/typing.py CHANGED
@@ -474,7 +474,7 @@ def dataclass_to_dict(
474
474
  return cast("dict[str, Any]", ret)
475
475
 
476
476
 
477
- def schema_dump( # noqa: PLR0911
477
+ def schema_dump(
478
478
  data: "Union[dict[str, Any], DataclassProtocol, Struct, BaseModel]",
479
479
  exclude_unset: bool = True,
480
480
  ) -> "dict[str, Any]":
@@ -503,6 +503,18 @@ def schema_dump( # noqa: PLR0911
503
503
  return cast("dict[str, Any]", data)
504
504
 
505
505
 
506
+ def is_dto_data(v: Any) -> TypeGuard[DTOData[Any]]:
507
+ """Check if a value is a Litestar DTOData object.
508
+
509
+ Args:
510
+ v: Value to check.
511
+
512
+ Returns:
513
+ bool
514
+ """
515
+ return LITESTAR_INSTALLED and isinstance(v, DTOData)
516
+
517
+
506
518
  __all__ = (
507
519
  "LITESTAR_INSTALLED",
508
520
  "MSGSPEC_INSTALLED",
@@ -536,6 +548,7 @@ __all__ = (
536
548
  "is_dict",
537
549
  "is_dict_with_field",
538
550
  "is_dict_without_field",
551
+ "is_dto_data",
539
552
  "is_msgspec_struct",
540
553
  "is_msgspec_struct_with_field",
541
554
  "is_msgspec_struct_without_field",
@@ -566,3 +579,7 @@ if TYPE_CHECKING:
566
579
  from sqlspec._typing import ArrowTable
567
580
  else:
568
581
  from pyarrow import Table as ArrowTable # noqa: TC004
582
+ if not LITESTAR_INSTALLED:
583
+ from sqlspec._typing import DTOData
584
+ else:
585
+ from litestar.dto import DTOData # noqa: TC004
sqlspec/utils/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
- from sqlspec.utils import deprecation, fixtures, module_loader, sync_tools, text
1
+ from sqlspec.utils import deprecation, fixtures, module_loader, singleton, sync_tools, text
2
2
 
3
- __all__ = ("deprecation", "fixtures", "module_loader", "sync_tools", "text")
3
+ __all__ = ("deprecation", "fixtures", "module_loader", "singleton", "sync_tools", "text")
@@ -0,0 +1,35 @@
1
+ from typing import Any, TypeVar
2
+
3
+ __all__ = ("SingletonMeta",)
4
+
5
+
6
+ _T = TypeVar("_T")
7
+
8
+
9
+ class SingletonMeta(type):
10
+ """Metaclass for singleton pattern."""
11
+
12
+ # We store instances keyed by the class type
13
+ _instances: dict[type, object] = {}
14
+
15
+ def __call__(cls: type[_T], *args: Any, **kwargs: Any) -> _T:
16
+ """Call method for the singleton metaclass.
17
+
18
+ Args:
19
+ cls: The class being instantiated.
20
+ *args: Positional arguments for the class constructor.
21
+ **kwargs: Keyword arguments for the class constructor.
22
+
23
+ Returns:
24
+ The singleton instance of the class.
25
+ """
26
+ # Use SingletonMeta._instances to access the class attribute
27
+ if cls not in SingletonMeta._instances: # pyright: ignore[reportUnnecessaryContains]
28
+ # Create the instance using super().__call__ which calls the class's __new__ and __init__
29
+ instance = super().__call__(*args, **kwargs) # type: ignore[misc]
30
+ SingletonMeta._instances[cls] = instance
31
+
32
+ # Return the cached instance. We cast here because the dictionary stores `object`,
33
+ # but we know it's of type _T for the given cls key.
34
+ # Mypy might need an ignore here depending on configuration, but pyright should handle it.
35
+ return SingletonMeta._instances[cls] # type: ignore[return-value]
@@ -30,139 +30,6 @@ ParamSpecT = ParamSpec("ParamSpecT")
30
30
  T = TypeVar("T")
31
31
 
32
32
 
33
- class PendingType:
34
- def __repr__(self) -> str:
35
- return "AsyncPending"
36
-
37
-
38
- Pending = PendingType()
39
-
40
-
41
- class PendingValueError(Exception):
42
- """Exception raised when a value is accessed before it is ready."""
43
-
44
-
45
- class SoonValue(Generic[T]):
46
- """Holds a value that will be available soon after an async operation."""
47
-
48
- def __init__(self) -> None:
49
- self._stored_value: Union[T, PendingType] = Pending
50
-
51
- @property
52
- def value(self) -> "T":
53
- if isinstance(self._stored_value, PendingType):
54
- msg = "The return value of this task is still pending."
55
- raise PendingValueError(msg)
56
- return self._stored_value
57
-
58
- @property
59
- def ready(self) -> bool:
60
- return not isinstance(self._stored_value, PendingType)
61
-
62
-
63
- class TaskGroup:
64
- """Manages a group of asyncio tasks, allowing them to be run concurrently."""
65
-
66
- def __init__(self) -> None:
67
- self._tasks: set[asyncio.Task[Any]] = set()
68
- self._exceptions: list[BaseException] = []
69
- self._closed = False
70
-
71
- async def __aenter__(self) -> "TaskGroup":
72
- if self._closed:
73
- msg = "Cannot enter a task group that has already been closed."
74
- raise RuntimeError(msg)
75
- return self
76
-
77
- async def __aexit__(
78
- self,
79
- exc_type: "Optional[type[BaseException]]", # noqa: PYI036
80
- exc_val: "Optional[BaseException]", # noqa: PYI036
81
- exc_tb: "Optional[TracebackType]", # noqa: PYI036
82
- ) -> None:
83
- self._closed = True
84
- if exc_val:
85
- self._exceptions.append(exc_val)
86
-
87
- if self._tasks:
88
- await asyncio.wait(self._tasks)
89
-
90
- if self._exceptions:
91
- # Re-raise the first exception encountered.
92
- raise self._exceptions[0]
93
-
94
- def create_task(self, coro: "Coroutine[Any, Any, Any]") -> "asyncio.Task[Any]":
95
- """Create and add a coroutine as a task to the task group.
96
-
97
- Args:
98
- coro (Coroutine): The coroutine to be added as a task.
99
-
100
- Returns:
101
- asyncio.Task: The created asyncio task.
102
-
103
- Raises:
104
- RuntimeError: If the task group has already been closed.
105
- """
106
- if self._closed:
107
- msg = "Cannot create a task in a task group that has already been closed."
108
- raise RuntimeError(msg)
109
- task = asyncio.create_task(coro)
110
- self._tasks.add(task)
111
- task.add_done_callback(self._tasks.discard)
112
- task.add_done_callback(self._check_result)
113
- return task
114
-
115
- def _check_result(self, task: "asyncio.Task[Any]") -> None:
116
- """Check and store exceptions from a completed task.
117
-
118
- Args:
119
- task (asyncio.Task): The task to check for exceptions.
120
- """
121
- try:
122
- task.result() # This will raise the exception if one occurred.
123
- except Exception as e: # noqa: BLE001
124
- self._exceptions.append(e)
125
-
126
- def start_soon_(
127
- self,
128
- async_function: "Callable[ParamSpecT, Awaitable[T]]",
129
- name: object = None,
130
- ) -> "Callable[ParamSpecT, SoonValue[T]]":
131
- """Create a function to start a new task in this task group.
132
-
133
- Args:
134
- async_function (Callable): An async function to call soon.
135
- name (object, optional): Name of the task for introspection and debugging.
136
-
137
- Returns:
138
- Callable: A function that starts the task and returns a SoonValue object.
139
- """
140
-
141
- @functools.wraps(async_function)
142
- def wrapper(*args: "ParamSpecT.args", **kwargs: "ParamSpecT.kwargs") -> "SoonValue[T]":
143
- partial_f = functools.partial(async_function, *args, **kwargs)
144
- soon_value: SoonValue[T] = SoonValue()
145
-
146
- @functools.wraps(partial_f)
147
- async def value_wrapper(*args: "Any") -> None:
148
- value = await partial_f()
149
- soon_value._stored_value = value # pyright: ignore[reportPrivateUsage] # noqa: SLF001
150
-
151
- self.create_task(value_wrapper) # type: ignore[arg-type]
152
- return soon_value
153
-
154
- return wrapper
155
-
156
-
157
- def create_task_group() -> "TaskGroup":
158
- """Create a TaskGroup for managing multiple concurrent async tasks.
159
-
160
- Returns:
161
- TaskGroup: A new TaskGroup instance.
162
- """
163
- return TaskGroup()
164
-
165
-
166
33
  class CapacityLimiter:
167
34
  """Limits the number of concurrent operations using a semaphore."""
168
35
 
@@ -195,7 +62,7 @@ class CapacityLimiter:
195
62
  self.release()
196
63
 
197
64
 
198
- _default_limiter = CapacityLimiter(40)
65
+ _default_limiter = CapacityLimiter(15)
199
66
 
200
67
 
201
68
  def run_(async_function: "Callable[ParamSpecT, Coroutine[Any, Any, ReturnT]]") -> "Callable[ParamSpecT, ReturnT]":
@@ -237,6 +104,7 @@ def await_(
237
104
  Args:
238
105
  async_function (Callable): The async function to convert.
239
106
  raise_sync_error (bool, optional): If False, runs in a new event loop if no loop is present.
107
+ If True (default), raises RuntimeError if no loop is running.
240
108
 
241
109
  Returns:
242
110
  Callable: A blocking function that runs the async function.
@@ -248,12 +116,39 @@ def await_(
248
116
  try:
249
117
  loop = asyncio.get_running_loop()
250
118
  except RuntimeError:
251
- loop = None
252
-
253
- if loop is None and raise_sync_error is False:
119
+ # No running event loop
120
+ if raise_sync_error:
121
+ msg = "await_ called without a running event loop and raise_sync_error=True"
122
+ raise RuntimeError(msg) from None
123
+ return asyncio.run(partial_f())
124
+ else:
125
+ # Running in an existing event loop.
126
+ if loop.is_running():
127
+ try:
128
+ # Check if the current context is within a task managed by this loop
129
+ current_task = asyncio.current_task(loop=loop)
130
+ except RuntimeError:
131
+ # Not running inside a task managed by this loop
132
+ current_task = None
133
+
134
+ if current_task is not None:
135
+ # Called from within the event loop's execution context (a task).
136
+ # Blocking here would deadlock the loop.
137
+ msg = "await_ cannot be called from within an async task running on the same event loop. Use 'await' instead."
138
+ raise RuntimeError(msg)
139
+ # Called from a different thread than the loop's thread.
140
+ # It's safe to block this thread and wait for the loop.
141
+ future = asyncio.run_coroutine_threadsafe(partial_f(), loop)
142
+ # This blocks the *calling* thread, not the loop thread.
143
+ return future.result()
144
+ # This case should ideally not happen if get_running_loop() succeeded
145
+ # but the loop isn't running, but handle defensively.
146
+ # loop is not running
147
+ if raise_sync_error:
148
+ msg = "await_ found a non-running loop via get_running_loop()"
149
+ raise RuntimeError(msg)
150
+ # Fallback to running in a new loop
254
151
  return asyncio.run(partial_f())
255
- # Running in an existing event loop
256
- return asyncio.run(partial_f())
257
152
 
258
153
  return wrapper
259
154
 
@@ -286,9 +181,17 @@ def async_(
286
181
  return wrapper
287
182
 
288
183
 
289
- def maybe_async_(
184
+ def ensure_async_(
290
185
  function: "Callable[ParamSpecT, Union[Awaitable[ReturnT], ReturnT]]",
291
186
  ) -> "Callable[ParamSpecT, Awaitable[ReturnT]]":
187
+ """Convert a function to an async one if it is not already.
188
+
189
+ Args:
190
+ function (Callable): The function to convert.
191
+
192
+ Returns:
193
+ Callable: An async function that runs the original function.
194
+ """
292
195
  if inspect.iscoroutinefunction(function):
293
196
  return function
294
197
 
@@ -301,16 +204,6 @@ def maybe_async_(
301
204
  return wrapper
302
205
 
303
206
 
304
- def wrap_sync(fn: "Callable[ParamSpecT, ReturnT]") -> "Callable[ParamSpecT, Awaitable[ReturnT]]":
305
- if inspect.iscoroutinefunction(fn):
306
- return fn
307
-
308
- async def wrapped(*args: "ParamSpecT.args", **kwargs: "ParamSpecT.kwargs") -> ReturnT:
309
- return await async_(functools.partial(fn, *args, **kwargs))()
310
-
311
- return wrapped
312
-
313
-
314
207
  class _ContextManagerWrapper(Generic[T]):
315
208
  def __init__(self, cm: AbstractContextManager[T]) -> None:
316
209
  self._cm = cm
@@ -327,9 +220,55 @@ class _ContextManagerWrapper(Generic[T]):
327
220
  return self._cm.__exit__(exc_type, exc_val, exc_tb)
328
221
 
329
222
 
330
- def maybe_async_context(
223
+ def with_ensure_async_(
331
224
  obj: "Union[AbstractContextManager[T], AbstractAsyncContextManager[T]]",
332
225
  ) -> "AbstractAsyncContextManager[T]":
226
+ """Convert a context manager to an async one if it is not already.
227
+
228
+ Args:
229
+ obj (AbstractContextManager[T] or AbstractAsyncContextManager[T]): The context manager to convert.
230
+
231
+ Returns:
232
+ AbstractAsyncContextManager[T]: An async context manager that runs the original context manager.
233
+ """
234
+
333
235
  if isinstance(obj, AbstractContextManager):
334
236
  return cast("AbstractAsyncContextManager[T]", _ContextManagerWrapper(obj))
335
237
  return obj
238
+
239
+
240
+ class NoValue:
241
+ """A fake "Empty class"""
242
+
243
+
244
+ async def get_next(iterable: Any, default: Any = NoValue, *args: Any) -> Any: # pragma: no cover
245
+ """Return the next item from an async iterator.
246
+
247
+ In Python <3.10, `anext` is not available. This function is a drop-in replacement.
248
+
249
+ This function will return the next value form an async iterable. If the
250
+ iterable is empty the StopAsyncIteration will be propagated. However, if
251
+ a default value is given as a second argument the exception is silenced and
252
+ the default value is returned instead.
253
+
254
+ Args:
255
+ iterable: An async iterable.
256
+ default: An optional default value to return if the iterable is empty.
257
+ *args: The remaining args
258
+ Return:
259
+ The next value of the iterable.
260
+
261
+ Raises:
262
+ StopAsyncIteration: The iterable given is not async.
263
+
264
+
265
+ """
266
+ has_default = bool(not isinstance(default, NoValue))
267
+ try:
268
+ return await iterable.__anext__()
269
+
270
+ except StopAsyncIteration as exc:
271
+ if has_default:
272
+ return default
273
+
274
+ raise StopAsyncIteration from exc
sqlspec/utils/text.py CHANGED
@@ -2,23 +2,52 @@
2
2
 
3
3
  import re
4
4
  import unicodedata
5
+ from functools import lru_cache
5
6
  from typing import Optional
6
7
 
8
+ # Compiled regex for slugify
9
+ _SLUGIFY_REMOVE_INVALID_CHARS_RE = re.compile(r"[^\w\s-]")
10
+ _SLUGIFY_COLLAPSE_SEPARATORS_RE = re.compile(r"[-\s]+")
11
+
12
+ # Compiled regex for snake_case
13
+ # Handles sequences like "HTTPRequest" -> "HTTP_Request" or "SSLError" -> "SSL_Error"
14
+ _SNAKE_CASE_RE_ACRONYM_SEQUENCE = re.compile(r"([A-Z\d]+)([A-Z][a-z])")
15
+ # Handles transitions like "camelCase" -> "camel_Case" or "PascalCase" -> "Pascal_Case" (partially)
16
+ _SNAKE_CASE_RE_LOWER_UPPER_TRANSITION = re.compile(r"([a-z\d])([A-Z])")
17
+ # Replaces hyphens, spaces, and dots with a single underscore
18
+ _SNAKE_CASE_RE_REPLACE_SEP = re.compile(r"[-\s.]+")
19
+ # Cleans up multiple consecutive underscores
20
+ _SNAKE_CASE_RE_CLEAN_MULTIPLE_UNDERSCORE = re.compile(r"__+")
21
+
7
22
  __all__ = (
23
+ "camelize",
8
24
  "check_email",
9
25
  "slugify",
26
+ "snake_case",
10
27
  )
11
28
 
12
29
 
13
30
  def check_email(email: str) -> str:
14
- """Validate an email."""
31
+ """Validate an email.
32
+
33
+ Very simple email validation.
34
+
35
+ Args:
36
+ email (str): The email to validate.
37
+
38
+ Raises:
39
+ ValueError: If the email is invalid.
40
+
41
+ Returns:
42
+ str: The validated email.
43
+ """
15
44
  if "@" not in email:
16
45
  msg = "Invalid email!"
17
46
  raise ValueError(msg)
18
47
  return email.lower()
19
48
 
20
49
 
21
- def slugify(value: str, allow_unicode: bool = False, separator: "Optional[str]" = None) -> str:
50
+ def slugify(value: str, allow_unicode: bool = False, separator: Optional[str] = None) -> str:
22
51
  """Slugify.
23
52
 
24
53
  Convert to ASCII if ``allow_unicode`` is ``False``. Convert spaces or repeated
@@ -39,7 +68,41 @@ def slugify(value: str, allow_unicode: bool = False, separator: "Optional[str]"
39
68
  value = unicodedata.normalize("NFKC", value)
40
69
  else:
41
70
  value = unicodedata.normalize("NFKD", value).encode("ascii", "ignore").decode("ascii")
42
- value = re.sub(r"[^\w\s-]", "", value.lower())
71
+ value = _SLUGIFY_REMOVE_INVALID_CHARS_RE.sub("", value.lower())
43
72
  if separator is not None:
44
- return re.sub(r"[-\s]+", "-", value).strip("-_").replace("-", separator)
45
- return re.sub(r"[-\s]+", "-", value).strip("-_")
73
+ return _SLUGIFY_COLLAPSE_SEPARATORS_RE.sub("-", value).strip("-_").replace("-", separator)
74
+ return _SLUGIFY_COLLAPSE_SEPARATORS_RE.sub("-", value).strip("-_")
75
+
76
+
77
+ @lru_cache(maxsize=100)
78
+ def camelize(string: str) -> str:
79
+ """Convert a string to camel case.
80
+
81
+ Args:
82
+ string (str): The string to convert.
83
+
84
+ Returns:
85
+ str: The converted string.
86
+ """
87
+ return "".join(word if index == 0 else word.capitalize() for index, word in enumerate(string.split("_")))
88
+
89
+
90
+ @lru_cache(maxsize=100)
91
+ def snake_case(string: str) -> str:
92
+ """Convert a string to snake_case.
93
+
94
+ Handles CamelCase, PascalCase, strings with spaces, hyphens, or dots
95
+ as separators, and ensures single underscores. It also correctly
96
+ handles acronyms (e.g., "HTTPRequest" becomes "http_request").
97
+
98
+ Args:
99
+ string: The string to convert.
100
+
101
+ Returns:
102
+ The snake_case version of the string.
103
+ """
104
+ s = _SNAKE_CASE_RE_ACRONYM_SEQUENCE.sub(r"\1_\2", string)
105
+ s = _SNAKE_CASE_RE_LOWER_UPPER_TRANSITION.sub(r"\1_\2", s)
106
+ s = _SNAKE_CASE_RE_REPLACE_SEP.sub("_", s).lower()
107
+ s = _SNAKE_CASE_RE_CLEAN_MULTIPLE_UNDERSCORE.sub("_", s)
108
+ return s.strip("_")
@@ -1,7 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlspec
3
- Version: 0.10.1
3
+ Version: 0.11.0
4
4
  Summary: SQL Experiments in Python
5
+ Project-URL: Discord, https://discord.gg/litestar
6
+ Project-URL: Issue, https://github.com/litestar-org/sqlspec/issues/
7
+ Project-URL: Source, https://github.com/litestar-org/sqlspec
5
8
  Author-email: Cody Fincher <cody@litestar.dev>
6
9
  Maintainer-email: Litestar Developers <hello@litestar.dev>
7
10
  License-Expression: MIT
@@ -258,6 +261,7 @@ This list is not final. If you have a driver you'd like to see added, please ope
258
261
  | [`spanner`](https://googleapis.dev/python/spanner/latest/index.html) | Spanner | Sync | 🗓️ |
259
262
  | [`sqlserver`](https://docs.microsoft.com/en-us/sql/connect/python/pyodbc/python-sql-driver-for-pyodbc?view=sql-server-ver16) | SQL Server | Sync | 🗓️ |
260
263
  | [`mysql`](https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysql-connector-python.html) | MySQL | Sync | 🗓️ |
264
+ | [`asyncmy`](https://github.com/long2ice/asyncmy) | MySQL | Async | ✅ |
261
265
  | [`snowflake`](https://docs.snowflake.com) | Snowflake | Sync | 🗓️ |
262
266
 
263
267
  ## Proposed Project Structure
@@ -2,66 +2,68 @@ sqlspec/__init__.py,sha256=Dl1QOZAK21--ORQcRn15n4YPFklFMe2-Lb7TWWq_WQE,338
2
2
  sqlspec/__metadata__.py,sha256=hNP3wXvtk8fQVPKGjRLpZ9mP-gaPJqzrmgm3UqpDIXQ,460
3
3
  sqlspec/_serialization.py,sha256=tSwWwFImlYviC6ARdXRz0Bp4QXbCdc8cKGgZr33OglY,2657
4
4
  sqlspec/_typing.py,sha256=a8QTy3oqdUfjrA6Iu4PxfQcUf9DuG9pZcalcevM_xIU,7037
5
- sqlspec/base.py,sha256=SQDE27igKL6OVQ-D9lz3oNrEZz4vWggRSuE4SDXJSbs,32789
5
+ sqlspec/base.py,sha256=Q6fIHtOqYXAcNt8fFe6zeqP34MLWm72do-l2Xc8pjLA,34140
6
6
  sqlspec/exceptions.py,sha256=WnA56CdDSSdOjA5UE4jnfXXtrfClgwjCRxT-id0eVAo,4302
7
- sqlspec/filters.py,sha256=Gqwt4VQ7e8ffphkuR-jBfqW4m0OWGGUPiYWyEQ0Xn7M,3620
8
- sqlspec/mixins.py,sha256=JWniOJfjviNBpAj3AnTnd2ZA79C0Vcu-bVHPS3Lbxcg,4751
7
+ sqlspec/filters.py,sha256=Up8lDFbAcObwhxHApxlqh84Zco57wPLIeMxdxiyUih4,11999
8
+ sqlspec/mixins.py,sha256=TkXGJg8eR54_LRGgzAKz0v6BT98XPNEwXUoMq02nckY,10416
9
9
  sqlspec/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- sqlspec/statement.py,sha256=lbnF_flv4sWPPiZtHX-53d72eCFcceBYB4BgQQYjnCU,17451
11
- sqlspec/typing.py,sha256=eMLeqi-j28PNLs8jBb4oxeMjOe95jjV1DW8FIp0uCJY,15932
10
+ sqlspec/statement.py,sha256=LNagGHKt-ixjom5WW5VLRzT9YIJC0lOfvwnn41Zz-fw,16433
11
+ sqlspec/typing.py,sha256=XAQpyOPAcHzlGScY3DCxIfiaQpfbFP4PntIgvYdcLwk,16313
12
12
  sqlspec/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  sqlspec/adapters/adbc/__init__.py,sha256=Ih0mdciGyhmOlqmz4uiByj7mEaqvP4upRjYhlUNopAQ,193
14
- sqlspec/adapters/adbc/config.py,sha256=uCY-PD06QFJW0v7XpA9vruYgq1eoVwQ63juZe9imMu4,9663
15
- sqlspec/adapters/adbc/driver.py,sha256=Q619R8nFdSk-lPab2jk0F5xkzhXZPEDqbxw-67_1NBM,20100
14
+ sqlspec/adapters/adbc/config.py,sha256=yayt62Mx789_B7Xo8DrlWCyeXclFchL4OxUxZIFnh9I,9646
15
+ sqlspec/adapters/adbc/driver.py,sha256=qOvZ1g-S02GRPX35AywciwB_S9d7ffXkaE_obd8EP-w,28871
16
16
  sqlspec/adapters/aiosqlite/__init__.py,sha256=CndH49GREnHuIB-jY1XAxVlLwZTvKNuk8XJu9jiiM7A,233
17
17
  sqlspec/adapters/aiosqlite/config.py,sha256=tE-DnjKbdy5FaqqRyA1q3s06rMSAglt0HkhO2oWQT2w,4603
18
- sqlspec/adapters/aiosqlite/driver.py,sha256=319ixRaD03L465xa5ZsK2pXXaZ7wIxuWDm7ZXr-OMcg,15552
18
+ sqlspec/adapters/aiosqlite/driver.py,sha256=d9Gz4bQmmqPhkJ0GrGNRVKwzPrUOEeHjWrj-Rr-7GA4,16802
19
19
  sqlspec/adapters/asyncmy/__init__.py,sha256=7jQFc0WOgc58XPeIiDgX9a95scMa6PuFgGXQaxG33nI,291
20
20
  sqlspec/adapters/asyncmy/config.py,sha256=5ILV46FWjc9Cy46aMuhinpfc70b_708h9ubHj9HRCmE,9412
21
- sqlspec/adapters/asyncmy/driver.py,sha256=yFgSNtInWshm994eiKd8c_rNJtM1mToAHfQ039egci0,12376
21
+ sqlspec/adapters/asyncmy/driver.py,sha256=jbaO3O3heNVF016FmlbHt0tCR2yczS2dlbttx9A2oUU,17207
22
22
  sqlspec/adapters/asyncpg/__init__.py,sha256=iR-vJYxImcw5hLaDgMqPLLRxW_vOYylEpemSg5G4dP4,261
23
- sqlspec/adapters/asyncpg/config.py,sha256=yhLcZyJksx9eKUGVlcKSsR7FQmj8F2caryeTdh1CNvQ,9966
24
- sqlspec/adapters/asyncpg/driver.py,sha256=93f7ePb91GSrmJhAaMC7PwgZLvwr3RC5zq8xk8OEQPw,22431
23
+ sqlspec/adapters/asyncpg/config.py,sha256=cuQ_cCQ6xtqluaNO5Ax9vqZ-4JZoaUR31-QE6xAVbns,10011
24
+ sqlspec/adapters/asyncpg/driver.py,sha256=cmyxzieTcXSOnvNHdPORg5qHTGqYJyIi-ogNMBbL6hg,20495
25
25
  sqlspec/adapters/bigquery/__init__.py,sha256=8kcl0_tnvnk8omVKnAljIY9n2XVnzkPRCfhfedGO0m4,264
26
- sqlspec/adapters/bigquery/driver.py,sha256=8Y9Iq3d9U11wLOrd7_QlmAXMF3VAg7Werp0i5v0WStg,28402
26
+ sqlspec/adapters/bigquery/driver.py,sha256=IcYWbP61-z2xLs7f5Df6mWidpWnDXbD9ONn7bFSOvo4,27601
27
27
  sqlspec/adapters/bigquery/config/__init__.py,sha256=4ij4LAS-kIt-vOK8KetewVoYN90i1RV_BjtowKWDIs0,150
28
28
  sqlspec/adapters/bigquery/config/_common.py,sha256=LSbBC302-Ewx8XHTRzYR-tInMYywVW9I6UcL8cO7-HQ,1901
29
29
  sqlspec/adapters/bigquery/config/_sync.py,sha256=oglaEErXuce1TnE2wj5KrfFLkScRGFYAoOTCVV5BFcw,3323
30
30
  sqlspec/adapters/duckdb/__init__.py,sha256=GMSHigyHgtaJKu751kE_Sxl5Ry4hnQOnFUSIeLSg1qs,209
31
31
  sqlspec/adapters/duckdb/config.py,sha256=b-Ev7UnpguC12CJSxK9DDqcPw0R2dZUZXaVIePf_EEg,15700
32
- sqlspec/adapters/duckdb/driver.py,sha256=rpBIGuAQlHtUp3oVInjdMdCQSgyx_oiOP39sjGlrdOA,13960
32
+ sqlspec/adapters/duckdb/driver.py,sha256=OZX9bx8qAK5N19KeM1OunZbHXfduSk_0CScQWH68SdA,16117
33
33
  sqlspec/adapters/oracledb/__init__.py,sha256=vVe8cXZJLFvBA6LPx4NzGRLdOeRugzRjz92UYjb0lC0,521
34
- sqlspec/adapters/oracledb/driver.py,sha256=nLsSggAN4Zs1uo6J3Cd_3f0e54EzjLAoTlgaatb5ll8,31053
34
+ sqlspec/adapters/oracledb/driver.py,sha256=6KH-GNpHIjKKIV2uzD1SGo4QBUPBN2plyRHKnTst7vo,37603
35
35
  sqlspec/adapters/oracledb/config/__init__.py,sha256=emx5jWXqw3ifoW-m_tNI7sTz_duq2vRkubc0J2QqEQ4,306
36
36
  sqlspec/adapters/oracledb/config/_asyncio.py,sha256=k0wGr4FflFR03jUSgrw-4LC4mYtRlyH9gnbbBXNcMRM,7310
37
37
  sqlspec/adapters/oracledb/config/_common.py,sha256=UJZL2DQQZM3uOn1E1A_gnsB8nX3-yCDXGd66PDI29_s,5691
38
38
  sqlspec/adapters/oracledb/config/_sync.py,sha256=nm5FnrRG1ScrNviw3MR_40Vq8WJCXX5mJGtHhhRTPb0,7055
39
39
  sqlspec/adapters/psqlpy/__init__.py,sha256=K8UlQrKfbCZmxGAaT4CHzQvdwGPxPLB9TDOHJgkESFc,251
40
40
  sqlspec/adapters/psqlpy/config.py,sha256=qssXcu_Nd6o_X8QU1i61sAXwi9FiTApWxiTRU0gyBhk,10205
41
- sqlspec/adapters/psqlpy/driver.py,sha256=dDLH6OyCIEtCjPktBcZEmRqBEB3FUaczpQrPDVNfAtc,17165
41
+ sqlspec/adapters/psqlpy/driver.py,sha256=AzoD-Gfm7VGoBXZYPORlzn_6ZE5A6blg2uV4COQF4aI,21156
42
42
  sqlspec/adapters/psycopg/__init__.py,sha256=xmFWHSB6hwPNQS1wpBmAczJThABmhRv2PDNKqaMFX3E,535
43
- sqlspec/adapters/psycopg/driver.py,sha256=LelXlEWMn9gcuMPYz9WsRfEds3y08A-XmXzVIgA5zio,28746
43
+ sqlspec/adapters/psycopg/driver.py,sha256=1YiIz_HX6tNj7LhU6gKxW4sr-5iza_eBPJ4VZPygy9w,27529
44
44
  sqlspec/adapters/psycopg/config/__init__.py,sha256=hUmtNkSma4M-Y66B-l1gh601Lx7FVYVhU0BWo9ssdJo,570
45
45
  sqlspec/adapters/psycopg/config/_async.py,sha256=oKitbfpsJVLhMnbMUmICQub3rBzVZ5n9lwsU_ZvB45s,6661
46
46
  sqlspec/adapters/psycopg/config/_common.py,sha256=UqqvqPE9zlSO9G_Gh6fI190cHfCDG98S0GaznGAHpdU,2181
47
47
  sqlspec/adapters/psycopg/config/_sync.py,sha256=GYPgE7jfb15gbVdTWRoGGS3B7hauN8wk61CW6Bdrjcs,6512
48
48
  sqlspec/adapters/sqlite/__init__.py,sha256=N8VL4Y850OOt63qz-Yvu6rIaCXiziASmn_qDY5tsRuA,209
49
49
  sqlspec/adapters/sqlite/config.py,sha256=lGz0G-JFd7dZLhbUrITn9V-ipbhlekwNUr0bXEzM-8k,4498
50
- sqlspec/adapters/sqlite/driver.py,sha256=S7__m5AJst86tKaDCYyyeBixbeyiPxqECkeNX_a4sgs,14057
50
+ sqlspec/adapters/sqlite/driver.py,sha256=QBy0Rfhw_9ozTM5yyWETdzqAzOXjtsoGWVjURbDGQec,14669
51
51
  sqlspec/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
- sqlspec/extensions/litestar/__init__.py,sha256=vJf0co-AUM75c7ZLil_TUCYilVNDtmVsdeVLbm9_xn8,512
52
+ sqlspec/extensions/litestar/__init__.py,sha256=ifiR2AXv3m4iDncA2XsVsgk8NnEjcEKxjK2jhFe6A-8,262
53
53
  sqlspec/extensions/litestar/_utils.py,sha256=UgwFxqLnjDw9S8G0H24DP2GsbMGas81W1lfhfTY68m8,1969
54
- sqlspec/extensions/litestar/config.py,sha256=M91ClAl15twFYcsQyJ-w-CdW5dMAxHztRlTDqg2hw_M,4368
55
- sqlspec/extensions/litestar/handlers.py,sha256=eO5rmj3LcomaPerZ6Mpsur3J0QmucutjByQlID0XZtM,7962
56
- sqlspec/extensions/litestar/plugin.py,sha256=kQgKnBIXnSm87SAngfSfYWAAN3BNZ6fPLxm2MefnD8Q,5216
57
- sqlspec/utils/__init__.py,sha256=nVIUuMaHhhC1vXydoSBvnc-xTArqwWJaAtpjHhiM84Q,159
54
+ sqlspec/extensions/litestar/config.py,sha256=Lz5_NqZ-XDXvaLh7fsPqxvuSDJ1JLJg1XUqbC-PdZPU,4666
55
+ sqlspec/extensions/litestar/handlers.py,sha256=3RJJ5rCEQCbmrhDhkz9Tp03UxqPYhyL8PYR7WKyvuP8,10372
56
+ sqlspec/extensions/litestar/plugin.py,sha256=0isCQ_VFC33_xyRf1Zcb2oWYbZpjFTg-OOZ2EGwTV5M,5175
57
+ sqlspec/extensions/litestar/providers.py,sha256=dwdw7o0jfhDGNbwgabx41dROQ3HCgA0cdXNhWsJPVuw,21805
58
+ sqlspec/utils/__init__.py,sha256=_Ya8IZuc2cZIstXr_xjgnSfxICXHXvu5mfWsi2USDrw,183
58
59
  sqlspec/utils/deprecation.py,sha256=4pwGxoQYI3dAc3L1lh4tszZG6e2jp5m4e0ICk8SJx5M,3886
59
60
  sqlspec/utils/fixtures.py,sha256=ni51rAuen6S1wuSi1kUwn6Qh25B-XrewPEsjV8G4gQ0,2029
60
61
  sqlspec/utils/module_loader.py,sha256=tmMy9JcTTQETcwT8Wt8adCIuqr4zinQnPbCiBJ6JTSQ,2703
61
- sqlspec/utils/sync_tools.py,sha256=xxHZ-5rnTrPEUNr7gxQUVvJd0NGJeO_MgisR8X7sI3c,10425
62
- sqlspec/utils/text.py,sha256=Ya-fWBcfkQRhguNs7MNFIYtAUiArBo62w8sRPHavMWM,1476
63
- sqlspec-0.10.1.dist-info/METADATA,sha256=O8m1zio3ZUnEejLUKIawOrQ9KxIJskq2fQ6oR0m_Zd8,14034
64
- sqlspec-0.10.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
65
- sqlspec-0.10.1.dist-info/licenses/LICENSE,sha256=MdujfZ6l5HuLz4mElxlu049itenOR3gnhN1_Nd3nVcM,1078
66
- sqlspec-0.10.1.dist-info/licenses/NOTICE,sha256=Lyir8ozXWov7CyYS4huVaOCNrtgL17P-bNV-5daLntQ,1634
67
- sqlspec-0.10.1.dist-info/RECORD,,
62
+ sqlspec/utils/singleton.py,sha256=YsHuo8_blPRQJRvXnjWXa8-Y-TO5V7jFGRwql-rNpO0,1363
63
+ sqlspec/utils/sync_tools.py,sha256=IRzgLMvdkYIwPGUG_EBYGwoOiBBmQSaphwaGachkV4M,9146
64
+ sqlspec/utils/text.py,sha256=-RlwmGjXtfD_ZkqIesZTHAPi46xg-uqlpVKDMcNwFrU,3539
65
+ sqlspec-0.11.0.dist-info/METADATA,sha256=a-INDP1gbHtG1KmqYdfxG4wcVN0zqzkYxca-m7hjaWU,14361
66
+ sqlspec-0.11.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
67
+ sqlspec-0.11.0.dist-info/licenses/LICENSE,sha256=MdujfZ6l5HuLz4mElxlu049itenOR3gnhN1_Nd3nVcM,1078
68
+ sqlspec-0.11.0.dist-info/licenses/NOTICE,sha256=Lyir8ozXWov7CyYS4huVaOCNrtgL17P-bNV-5daLntQ,1634
69
+ sqlspec-0.11.0.dist-info/RECORD,,