sqlspec 0.5.0__py3-none-any.whl → 0.7.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/__init__.py +0 -1
- sqlspec/__metadata__.py +1 -3
- sqlspec/_serialization.py +55 -8
- sqlspec/_typing.py +69 -20
- sqlspec/adapters/adbc/config.py +8 -13
- sqlspec/adapters/aiosqlite/__init__.py +1 -1
- sqlspec/adapters/aiosqlite/config.py +15 -24
- sqlspec/adapters/asyncmy/__init__.py +1 -1
- sqlspec/adapters/asyncmy/config.py +46 -46
- sqlspec/adapters/asyncpg/config.py +28 -33
- sqlspec/adapters/duckdb/config.py +75 -79
- sqlspec/adapters/oracledb/config/_asyncio.py +23 -18
- sqlspec/adapters/oracledb/config/_common.py +52 -72
- sqlspec/adapters/oracledb/config/_sync.py +21 -16
- sqlspec/adapters/psycopg/config/_async.py +17 -17
- sqlspec/adapters/psycopg/config/_common.py +17 -34
- sqlspec/adapters/psycopg/config/_sync.py +16 -17
- sqlspec/adapters/sqlite/config.py +13 -15
- sqlspec/base.py +148 -8
- sqlspec/exceptions.py +4 -6
- sqlspec/extensions/litestar/config.py +0 -0
- sqlspec/extensions/litestar/plugin.py +21 -12
- sqlspec/filters.py +11 -13
- sqlspec/typing.py +110 -127
- sqlspec/utils/deprecation.py +8 -10
- sqlspec/utils/fixtures.py +3 -5
- sqlspec/utils/module_loader.py +4 -6
- sqlspec/utils/text.py +2 -3
- {sqlspec-0.5.0.dist-info → sqlspec-0.7.0.dist-info}/METADATA +24 -15
- sqlspec-0.7.0.dist-info/RECORD +46 -0
- sqlspec-0.7.0.dist-info/licenses/LICENSE +21 -0
- sqlspec-0.5.0.dist-info/RECORD +0 -44
- {sqlspec-0.5.0.dist-info → sqlspec-0.7.0.dist-info}/WHEEL +0 -0
- {sqlspec-0.5.0.dist-info → sqlspec-0.7.0.dist-info}/licenses/NOTICE +0 -0
sqlspec/typing.py
CHANGED
|
@@ -1,20 +1,11 @@
|
|
|
1
|
-
from __future__ import annotations # noqa: A005
|
|
2
|
-
|
|
3
|
-
from collections.abc import Sequence
|
|
4
1
|
from dataclasses import Field, fields
|
|
5
2
|
from functools import lru_cache
|
|
6
|
-
from typing import
|
|
7
|
-
TYPE_CHECKING,
|
|
8
|
-
Annotated,
|
|
9
|
-
Any,
|
|
10
|
-
TypeVar,
|
|
11
|
-
Union,
|
|
12
|
-
cast,
|
|
13
|
-
)
|
|
3
|
+
from typing import TYPE_CHECKING, Annotated, Any, Optional, TypeVar, Union, cast
|
|
14
4
|
|
|
15
5
|
from typing_extensions import TypeAlias, TypeGuard
|
|
16
6
|
|
|
17
7
|
from sqlspec._typing import (
|
|
8
|
+
LITESTAR_INSTALLED,
|
|
18
9
|
MSGSPEC_INSTALLED,
|
|
19
10
|
PYDANTIC_INSTALLED,
|
|
20
11
|
UNSET,
|
|
@@ -22,7 +13,6 @@ from sqlspec._typing import (
|
|
|
22
13
|
DataclassProtocol,
|
|
23
14
|
Empty,
|
|
24
15
|
EmptyType,
|
|
25
|
-
FailFast,
|
|
26
16
|
Struct,
|
|
27
17
|
TypeAdapter,
|
|
28
18
|
UnsetType,
|
|
@@ -30,7 +20,7 @@ from sqlspec._typing import (
|
|
|
30
20
|
)
|
|
31
21
|
|
|
32
22
|
if TYPE_CHECKING:
|
|
33
|
-
from collections.abc import Iterable
|
|
23
|
+
from collections.abc import Iterable, Sequence
|
|
34
24
|
from collections.abc import Set as AbstractSet
|
|
35
25
|
|
|
36
26
|
from sqlspec.filters import StatementFilter
|
|
@@ -41,39 +31,36 @@ PYDANTIC_USE_FAILFAST = False # leave permanently disabled for now
|
|
|
41
31
|
|
|
42
32
|
T = TypeVar("T")
|
|
43
33
|
|
|
44
|
-
ModelT = TypeVar("ModelT", bound="Struct
|
|
34
|
+
ModelT = TypeVar("ModelT", bound="Union[Struct, BaseModel, DataclassProtocol]")
|
|
45
35
|
|
|
46
36
|
FilterTypeT = TypeVar("FilterTypeT", bound="StatementFilter")
|
|
47
37
|
"""Type variable for filter types.
|
|
48
38
|
|
|
49
39
|
:class:`~advanced_alchemy.filters.StatementFilter`
|
|
50
40
|
"""
|
|
51
|
-
ModelDTOT = TypeVar("ModelDTOT", bound="Struct | BaseModel")
|
|
52
|
-
"""Type variable for model DTOs.
|
|
53
41
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
PydanticOrMsgspecT: TypeAlias = Union[Struct, BaseModel]
|
|
42
|
+
|
|
43
|
+
SupportedSchemaModel: TypeAlias = Union[Struct, BaseModel]
|
|
57
44
|
"""Type alias for pydantic or msgspec models.
|
|
58
45
|
|
|
59
46
|
:class:`msgspec.Struct` or :class:`pydantic.BaseModel`
|
|
60
47
|
"""
|
|
61
|
-
ModelDictT: TypeAlias = Union[dict[str, Any], ModelT
|
|
48
|
+
ModelDictT: TypeAlias = "Union[dict[str, Any], ModelT ]"
|
|
62
49
|
"""Type alias for model dictionaries.
|
|
63
50
|
|
|
64
51
|
Represents:
|
|
65
|
-
- :type:`dict[str, Any]` |
|
|
52
|
+
- :type:`dict[str, Any]` | :class:`DataclassProtocol` | :class:`msgspec.Struct` | :class:`pydantic.BaseModel`
|
|
66
53
|
"""
|
|
67
|
-
ModelDictListT: TypeAlias = Sequence[Union[dict[str, Any], ModelT
|
|
54
|
+
ModelDictListT: TypeAlias = "Sequence[Union[dict[str, Any], ModelT ]]"
|
|
68
55
|
"""Type alias for model dictionary lists.
|
|
69
56
|
|
|
70
57
|
A list or sequence of any of the following:
|
|
71
|
-
- :type:`Sequence`[:type:`dict[str, Any]` | :class
|
|
58
|
+
- :type:`Sequence`[:type:`dict[str, Any]` | :class:`DataclassProtocol` | :class:`msgspec.Struct` | :class:`pydantic.BaseModel`]
|
|
72
59
|
|
|
73
60
|
"""
|
|
74
61
|
|
|
75
62
|
|
|
76
|
-
def is_dataclass_instance(obj: Any) -> TypeGuard[DataclassProtocol]:
|
|
63
|
+
def is_dataclass_instance(obj: Any) -> "TypeGuard[DataclassProtocol]":
|
|
77
64
|
"""Check if an object is a dataclass instance.
|
|
78
65
|
|
|
79
66
|
Args:
|
|
@@ -86,7 +73,7 @@ def is_dataclass_instance(obj: Any) -> TypeGuard[DataclassProtocol]:
|
|
|
86
73
|
|
|
87
74
|
|
|
88
75
|
@lru_cache(typed=True)
|
|
89
|
-
def get_type_adapter(f: type[T]) -> TypeAdapter[T]:
|
|
76
|
+
def get_type_adapter(f: "type[T]") -> "TypeAdapter[T]":
|
|
90
77
|
"""Caches and returns a pydantic type adapter.
|
|
91
78
|
|
|
92
79
|
Args:
|
|
@@ -102,241 +89,227 @@ def get_type_adapter(f: type[T]) -> TypeAdapter[T]:
|
|
|
102
89
|
return TypeAdapter(f)
|
|
103
90
|
|
|
104
91
|
|
|
105
|
-
def is_pydantic_model(
|
|
92
|
+
def is_pydantic_model(obj: Any) -> "TypeGuard[BaseModel]":
|
|
106
93
|
"""Check if a value is a pydantic model.
|
|
107
94
|
|
|
108
95
|
Args:
|
|
109
|
-
|
|
96
|
+
obj: Value to check.
|
|
110
97
|
|
|
111
98
|
Returns:
|
|
112
99
|
bool
|
|
113
100
|
"""
|
|
114
|
-
return PYDANTIC_INSTALLED and isinstance(
|
|
101
|
+
return PYDANTIC_INSTALLED and isinstance(obj, BaseModel)
|
|
115
102
|
|
|
116
103
|
|
|
117
|
-
def is_pydantic_model_with_field(
|
|
104
|
+
def is_pydantic_model_with_field(obj: "Any", field_name: str) -> "TypeGuard[BaseModel]":
|
|
118
105
|
"""Check if a pydantic model has a specific field.
|
|
119
106
|
|
|
120
107
|
Args:
|
|
121
|
-
|
|
108
|
+
obj: Value to check.
|
|
122
109
|
field_name: Field name to check for.
|
|
123
110
|
|
|
124
111
|
Returns:
|
|
125
112
|
bool
|
|
126
113
|
"""
|
|
127
|
-
return is_pydantic_model(
|
|
114
|
+
return is_pydantic_model(obj) and hasattr(obj, field_name)
|
|
128
115
|
|
|
129
116
|
|
|
130
|
-
def is_pydantic_model_without_field(
|
|
117
|
+
def is_pydantic_model_without_field(obj: "Any", field_name: str) -> "TypeGuard[BaseModel]":
|
|
131
118
|
"""Check if a pydantic model does not have a specific field.
|
|
132
119
|
|
|
133
120
|
Args:
|
|
134
|
-
|
|
121
|
+
obj: Value to check.
|
|
135
122
|
field_name: Field name to check for.
|
|
136
123
|
|
|
137
124
|
Returns:
|
|
138
125
|
bool
|
|
139
126
|
"""
|
|
140
|
-
return not
|
|
127
|
+
return is_pydantic_model(obj) and not hasattr(obj, field_name)
|
|
141
128
|
|
|
142
129
|
|
|
143
|
-
def is_msgspec_struct(
|
|
144
|
-
"""Check if a value is a msgspec
|
|
130
|
+
def is_msgspec_struct(obj: "Any") -> "TypeGuard[Struct]":
|
|
131
|
+
"""Check if a value is a msgspec struct.
|
|
145
132
|
|
|
146
133
|
Args:
|
|
147
|
-
|
|
134
|
+
obj: Value to check.
|
|
148
135
|
|
|
149
136
|
Returns:
|
|
150
137
|
bool
|
|
151
138
|
"""
|
|
152
|
-
return MSGSPEC_INSTALLED and isinstance(
|
|
139
|
+
return MSGSPEC_INSTALLED and isinstance(obj, Struct)
|
|
153
140
|
|
|
154
141
|
|
|
155
|
-
def is_msgspec_struct_with_field(
|
|
156
|
-
"""Check if a msgspec
|
|
142
|
+
def is_msgspec_struct_with_field(obj: "Any", field_name: str) -> "TypeGuard[Struct]":
|
|
143
|
+
"""Check if a msgspec struct has a specific field.
|
|
157
144
|
|
|
158
145
|
Args:
|
|
159
|
-
|
|
146
|
+
obj: Value to check.
|
|
160
147
|
field_name: Field name to check for.
|
|
161
148
|
|
|
162
149
|
Returns:
|
|
163
150
|
bool
|
|
164
151
|
"""
|
|
165
|
-
return is_msgspec_struct(
|
|
152
|
+
return is_msgspec_struct(obj) and hasattr(obj, field_name)
|
|
166
153
|
|
|
167
154
|
|
|
168
|
-
def is_msgspec_struct_without_field(
|
|
169
|
-
"""Check if a msgspec
|
|
155
|
+
def is_msgspec_struct_without_field(obj: "Any", field_name: str) -> "TypeGuard[Struct]":
|
|
156
|
+
"""Check if a msgspec struct does not have a specific field.
|
|
170
157
|
|
|
171
158
|
Args:
|
|
172
|
-
|
|
159
|
+
obj: Value to check.
|
|
173
160
|
field_name: Field name to check for.
|
|
174
161
|
|
|
175
162
|
Returns:
|
|
176
163
|
bool
|
|
177
164
|
"""
|
|
178
|
-
return not
|
|
165
|
+
return is_msgspec_struct(obj) and not hasattr(obj, field_name)
|
|
179
166
|
|
|
180
167
|
|
|
181
|
-
def is_dict(
|
|
168
|
+
def is_dict(obj: "Any") -> "TypeGuard[dict[str, Any]]":
|
|
182
169
|
"""Check if a value is a dictionary.
|
|
183
170
|
|
|
184
171
|
Args:
|
|
185
|
-
|
|
172
|
+
obj: Value to check.
|
|
186
173
|
|
|
187
174
|
Returns:
|
|
188
175
|
bool
|
|
189
176
|
"""
|
|
190
|
-
return isinstance(
|
|
177
|
+
return isinstance(obj, dict)
|
|
191
178
|
|
|
192
179
|
|
|
193
|
-
def is_dict_with_field(
|
|
180
|
+
def is_dict_with_field(obj: "Any", field_name: str) -> "TypeGuard[dict[str, Any]]":
|
|
194
181
|
"""Check if a dictionary has a specific field.
|
|
195
182
|
|
|
196
183
|
Args:
|
|
197
|
-
|
|
184
|
+
obj: Value to check.
|
|
198
185
|
field_name: Field name to check for.
|
|
199
186
|
|
|
200
187
|
Returns:
|
|
201
188
|
bool
|
|
202
189
|
"""
|
|
203
|
-
return is_dict(
|
|
190
|
+
return is_dict(obj) and field_name in obj
|
|
204
191
|
|
|
205
192
|
|
|
206
|
-
def is_dict_without_field(
|
|
193
|
+
def is_dict_without_field(obj: "Any", field_name: str) -> "TypeGuard[dict[str, Any]]":
|
|
207
194
|
"""Check if a dictionary does not have a specific field.
|
|
208
195
|
|
|
209
196
|
Args:
|
|
210
|
-
|
|
197
|
+
obj: Value to check.
|
|
211
198
|
field_name: Field name to check for.
|
|
212
199
|
|
|
213
200
|
Returns:
|
|
214
201
|
bool
|
|
215
202
|
"""
|
|
216
|
-
return is_dict(
|
|
203
|
+
return is_dict(obj) and field_name not in obj
|
|
217
204
|
|
|
218
205
|
|
|
219
|
-
def is_schema(
|
|
206
|
+
def is_schema(obj: "Any") -> "TypeGuard[SupportedSchemaModel]":
|
|
220
207
|
"""Check if a value is a msgspec Struct or Pydantic model.
|
|
221
208
|
|
|
222
209
|
Args:
|
|
223
|
-
|
|
210
|
+
obj: Value to check.
|
|
224
211
|
|
|
225
212
|
Returns:
|
|
226
213
|
bool
|
|
227
214
|
"""
|
|
228
|
-
return is_msgspec_struct(
|
|
215
|
+
return is_msgspec_struct(obj) or is_pydantic_model(obj)
|
|
229
216
|
|
|
230
217
|
|
|
231
|
-
def is_schema_or_dict(
|
|
218
|
+
def is_schema_or_dict(obj: "Any") -> "TypeGuard[Union[SupportedSchemaModel, dict[str, Any]]]":
|
|
232
219
|
"""Check if a value is a msgspec Struct, Pydantic model, or dict.
|
|
233
220
|
|
|
234
221
|
Args:
|
|
235
|
-
|
|
222
|
+
obj: Value to check.
|
|
236
223
|
|
|
237
224
|
Returns:
|
|
238
225
|
bool
|
|
239
226
|
"""
|
|
240
|
-
return is_schema(
|
|
227
|
+
return is_schema(obj) or is_dict(obj)
|
|
241
228
|
|
|
242
229
|
|
|
243
|
-
def is_schema_with_field(
|
|
230
|
+
def is_schema_with_field(obj: "Any", field_name: str) -> "TypeGuard[SupportedSchemaModel]":
|
|
244
231
|
"""Check if a value is a msgspec Struct or Pydantic model with a specific field.
|
|
245
232
|
|
|
246
233
|
Args:
|
|
247
|
-
|
|
234
|
+
obj: Value to check.
|
|
248
235
|
field_name: Field name to check for.
|
|
249
236
|
|
|
250
237
|
Returns:
|
|
251
238
|
bool
|
|
252
239
|
"""
|
|
253
|
-
return is_msgspec_struct_with_field(
|
|
240
|
+
return is_msgspec_struct_with_field(obj, field_name) or is_pydantic_model_with_field(obj, field_name)
|
|
254
241
|
|
|
255
242
|
|
|
256
|
-
def is_schema_without_field(
|
|
243
|
+
def is_schema_without_field(obj: "Any", field_name: str) -> "TypeGuard[SupportedSchemaModel]":
|
|
257
244
|
"""Check if a value is a msgspec Struct or Pydantic model without a specific field.
|
|
258
245
|
|
|
259
246
|
Args:
|
|
260
|
-
|
|
247
|
+
obj: Value to check.
|
|
261
248
|
field_name: Field name to check for.
|
|
262
249
|
|
|
263
250
|
Returns:
|
|
264
251
|
bool
|
|
265
252
|
"""
|
|
266
|
-
return not is_schema_with_field(
|
|
253
|
+
return not is_schema_with_field(obj, field_name)
|
|
267
254
|
|
|
268
255
|
|
|
269
|
-
def is_schema_or_dict_with_field(
|
|
256
|
+
def is_schema_or_dict_with_field(
|
|
257
|
+
obj: "Any",
|
|
258
|
+
field_name: str,
|
|
259
|
+
) -> "TypeGuard[Union[SupportedSchemaModel, dict[str, Any]]]":
|
|
270
260
|
"""Check if a value is a msgspec Struct, Pydantic model, or dict with a specific field.
|
|
271
261
|
|
|
272
262
|
Args:
|
|
273
|
-
|
|
263
|
+
obj: Value to check.
|
|
274
264
|
field_name: Field name to check for.
|
|
275
265
|
|
|
276
266
|
Returns:
|
|
277
267
|
bool
|
|
278
268
|
"""
|
|
279
|
-
return is_schema_with_field(
|
|
269
|
+
return is_schema_with_field(obj, field_name) or is_dict_with_field(obj, field_name)
|
|
280
270
|
|
|
281
271
|
|
|
282
|
-
def is_schema_or_dict_without_field(
|
|
272
|
+
def is_schema_or_dict_without_field(
|
|
273
|
+
obj: "Any",
|
|
274
|
+
field_name: str,
|
|
275
|
+
) -> "TypeGuard[Union[SupportedSchemaModel, dict[str, Any]]]":
|
|
283
276
|
"""Check if a value is a msgspec Struct, Pydantic model, or dict without a specific field.
|
|
284
277
|
|
|
285
278
|
Args:
|
|
286
|
-
|
|
279
|
+
obj: Value to check.
|
|
287
280
|
field_name: Field name to check for.
|
|
288
281
|
|
|
289
282
|
Returns:
|
|
290
283
|
bool
|
|
291
284
|
"""
|
|
292
|
-
return not is_schema_or_dict_with_field(
|
|
285
|
+
return not is_schema_or_dict_with_field(obj, field_name)
|
|
293
286
|
|
|
294
287
|
|
|
295
|
-
def is_dataclass(
|
|
296
|
-
"""Check if
|
|
288
|
+
def is_dataclass(obj: "Any") -> "TypeGuard[DataclassProtocol]":
|
|
289
|
+
"""Check if an object is a dataclass."""
|
|
290
|
+
return is_dataclass_instance(obj)
|
|
297
291
|
|
|
298
|
-
Args:
|
|
299
|
-
v: Value to check.
|
|
300
292
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
293
|
+
def is_dataclass_with_field(
|
|
294
|
+
obj: "Any",
|
|
295
|
+
field_name: str,
|
|
296
|
+
) -> "TypeGuard[object]": # Can't specify dataclass type directly
|
|
297
|
+
"""Check if an object is a dataclass and has a specific field."""
|
|
298
|
+
return is_dataclass(obj) and hasattr(obj, field_name)
|
|
305
299
|
|
|
306
300
|
|
|
307
|
-
def
|
|
308
|
-
"""Check if a dataclass
|
|
309
|
-
|
|
310
|
-
Args:
|
|
311
|
-
v: Value to check.
|
|
312
|
-
field_name: Field name to check for.
|
|
313
|
-
|
|
314
|
-
Returns:
|
|
315
|
-
bool
|
|
316
|
-
"""
|
|
317
|
-
return is_dataclass(v) and field_name in v.__dataclass_fields__
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
def is_dataclass_without_field(v: Any, field_name: str) -> TypeGuard[DataclassProtocol]:
|
|
321
|
-
"""Check if a dataclass does not have a specific field.
|
|
322
|
-
|
|
323
|
-
Args:
|
|
324
|
-
v: Value to check.
|
|
325
|
-
field_name: Field name to check for.
|
|
326
|
-
|
|
327
|
-
Returns:
|
|
328
|
-
bool
|
|
329
|
-
"""
|
|
330
|
-
return is_dataclass(v) and field_name not in v.__dataclass_fields__
|
|
301
|
+
def is_dataclass_without_field(obj: "Any", field_name: str) -> "TypeGuard[object]":
|
|
302
|
+
"""Check if an object is a dataclass and does not have a specific field."""
|
|
303
|
+
return is_dataclass(obj) and not hasattr(obj, field_name)
|
|
331
304
|
|
|
332
305
|
|
|
333
306
|
def extract_dataclass_fields(
|
|
334
|
-
dt: DataclassProtocol,
|
|
307
|
+
dt: "DataclassProtocol",
|
|
335
308
|
exclude_none: bool = False,
|
|
336
309
|
exclude_empty: bool = False,
|
|
337
|
-
include: AbstractSet[str]
|
|
338
|
-
exclude: AbstractSet[str]
|
|
339
|
-
) -> tuple[Field[Any], ...]:
|
|
310
|
+
include: "Optional[AbstractSet[str]]" = None,
|
|
311
|
+
exclude: "Optional[AbstractSet[str]]" = None,
|
|
312
|
+
) -> "tuple[Field[Any], ...]":
|
|
340
313
|
"""Extract dataclass fields.
|
|
341
314
|
|
|
342
315
|
Args:
|
|
@@ -371,12 +344,12 @@ def extract_dataclass_fields(
|
|
|
371
344
|
|
|
372
345
|
|
|
373
346
|
def extract_dataclass_items(
|
|
374
|
-
dt: DataclassProtocol,
|
|
347
|
+
dt: "DataclassProtocol",
|
|
375
348
|
exclude_none: bool = False,
|
|
376
349
|
exclude_empty: bool = False,
|
|
377
|
-
include: AbstractSet[str]
|
|
378
|
-
exclude: AbstractSet[str]
|
|
379
|
-
) -> tuple[tuple[str, Any], ...]:
|
|
350
|
+
include: "Optional[AbstractSet[str]]" = None,
|
|
351
|
+
exclude: "Optional[AbstractSet[str]]" = None,
|
|
352
|
+
) -> "tuple[tuple[str, Any], ...]":
|
|
380
353
|
"""Extract dataclass name, value pairs.
|
|
381
354
|
|
|
382
355
|
Unlike the 'asdict' method exports by the stdlib, this function does not pickle values.
|
|
@@ -396,12 +369,12 @@ def extract_dataclass_items(
|
|
|
396
369
|
|
|
397
370
|
|
|
398
371
|
def dataclass_to_dict(
|
|
399
|
-
obj: DataclassProtocol,
|
|
372
|
+
obj: "DataclassProtocol",
|
|
400
373
|
exclude_none: bool = False,
|
|
401
374
|
exclude_empty: bool = False,
|
|
402
375
|
convert_nested: bool = True,
|
|
403
|
-
exclude:
|
|
404
|
-
) -> dict[str, Any]:
|
|
376
|
+
exclude: "Optional[AbstractSet[str]]" = None,
|
|
377
|
+
) -> "dict[str, Any]":
|
|
405
378
|
"""Convert a dataclass to a dictionary.
|
|
406
379
|
|
|
407
380
|
This method has important differences to the standard library version:
|
|
@@ -428,18 +401,18 @@ def dataclass_to_dict(
|
|
|
428
401
|
return cast("dict[str, Any]", ret)
|
|
429
402
|
|
|
430
403
|
|
|
431
|
-
def schema_dump(
|
|
432
|
-
data: dict[str, Any]
|
|
404
|
+
def schema_dump( # noqa: PLR0911
|
|
405
|
+
data: "Union[dict[str, Any], DataclassProtocol, Struct, BaseModel]",
|
|
433
406
|
exclude_unset: bool = True,
|
|
434
|
-
) -> dict[str, Any]:
|
|
407
|
+
) -> "dict[str, Any]":
|
|
435
408
|
"""Dump a data object to a dictionary.
|
|
436
409
|
|
|
437
410
|
Args:
|
|
438
|
-
data: dict[str, Any] |
|
|
411
|
+
data: :type:`dict[str, Any]` | :class:`DataclassProtocol` | :class:`msgspec.Struct` | :class:`pydantic.BaseModel`
|
|
439
412
|
exclude_unset: :type:`bool` Whether to exclude unset values.
|
|
440
413
|
|
|
441
414
|
Returns:
|
|
442
|
-
:type
|
|
415
|
+
:type:`dict[str, Any]`
|
|
443
416
|
"""
|
|
444
417
|
if is_dict(data):
|
|
445
418
|
return data
|
|
@@ -447,14 +420,18 @@ def schema_dump(
|
|
|
447
420
|
return dataclass_to_dict(data, exclude_empty=exclude_unset)
|
|
448
421
|
if is_pydantic_model(data):
|
|
449
422
|
return data.model_dump(exclude_unset=exclude_unset)
|
|
450
|
-
if is_msgspec_struct(data)
|
|
451
|
-
|
|
452
|
-
|
|
423
|
+
if is_msgspec_struct(data):
|
|
424
|
+
if exclude_unset:
|
|
425
|
+
return {f: val for f in data.__struct_fields__ if (val := getattr(data, f, None)) != UNSET}
|
|
453
426
|
return {f: getattr(data, f, None) for f in data.__struct_fields__}
|
|
454
|
-
|
|
427
|
+
|
|
428
|
+
if hasattr(data, "__dict__"):
|
|
429
|
+
return data.__dict__
|
|
430
|
+
return cast("dict[str, Any]", data)
|
|
455
431
|
|
|
456
432
|
|
|
457
433
|
__all__ = (
|
|
434
|
+
"LITESTAR_INSTALLED",
|
|
458
435
|
"MSGSPEC_INSTALLED",
|
|
459
436
|
"PYDANTIC_INSTALLED",
|
|
460
437
|
"PYDANTIC_USE_FAILFAST",
|
|
@@ -488,16 +465,22 @@ __all__ = (
|
|
|
488
465
|
"is_pydantic_model",
|
|
489
466
|
"is_pydantic_model_with_field",
|
|
490
467
|
"is_pydantic_model_without_field",
|
|
468
|
+
"is_schema",
|
|
469
|
+
"is_schema_or_dict",
|
|
470
|
+
"is_schema_or_dict_with_field",
|
|
471
|
+
"is_schema_or_dict_without_field",
|
|
472
|
+
"is_schema_with_field",
|
|
473
|
+
"is_schema_without_field",
|
|
491
474
|
"schema_dump",
|
|
492
475
|
)
|
|
493
476
|
|
|
494
477
|
if TYPE_CHECKING:
|
|
495
478
|
if not PYDANTIC_INSTALLED:
|
|
496
|
-
from ._typing import BaseModel, FailFast, TypeAdapter
|
|
479
|
+
from sqlspec._typing import BaseModel, FailFast, TypeAdapter
|
|
497
480
|
else:
|
|
498
481
|
from pydantic import BaseModel, FailFast, TypeAdapter # noqa: TC004
|
|
499
482
|
|
|
500
483
|
if not MSGSPEC_INSTALLED:
|
|
501
|
-
from ._typing import UNSET, Struct, UnsetType, convert
|
|
484
|
+
from sqlspec._typing import UNSET, Struct, UnsetType, convert
|
|
502
485
|
else:
|
|
503
486
|
from msgspec import UNSET, Struct, UnsetType, convert # noqa: TC004
|
sqlspec/utils/deprecation.py
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
1
|
import inspect
|
|
4
2
|
from functools import wraps
|
|
5
|
-
from typing import Callable, Literal
|
|
3
|
+
from typing import Callable, Literal, Optional
|
|
6
4
|
from warnings import warn
|
|
7
5
|
|
|
8
6
|
from typing_extensions import ParamSpec, TypeVar
|
|
@@ -20,9 +18,9 @@ def warn_deprecation(
|
|
|
20
18
|
deprecated_name: str,
|
|
21
19
|
kind: DeprecatedKind,
|
|
22
20
|
*,
|
|
23
|
-
removal_in: str
|
|
24
|
-
alternative: str
|
|
25
|
-
info: str
|
|
21
|
+
removal_in: Optional[str] = None,
|
|
22
|
+
alternative: Optional[str] = None,
|
|
23
|
+
info: Optional[str] = None,
|
|
26
24
|
pending: bool = False,
|
|
27
25
|
) -> None:
|
|
28
26
|
"""Warn about a call to a (soon to be) deprecated function.
|
|
@@ -71,11 +69,11 @@ def warn_deprecation(
|
|
|
71
69
|
def deprecated(
|
|
72
70
|
version: str,
|
|
73
71
|
*,
|
|
74
|
-
removal_in: str
|
|
75
|
-
alternative: str
|
|
76
|
-
info: str
|
|
72
|
+
removal_in: Optional[str] = None,
|
|
73
|
+
alternative: Optional[str] = None,
|
|
74
|
+
info: Optional[str] = None,
|
|
77
75
|
pending: bool = False,
|
|
78
|
-
kind: Literal["function", "method", "classmethod", "property"]
|
|
76
|
+
kind: Optional[Literal["function", "method", "classmethod", "property"]] = None,
|
|
79
77
|
) -> Callable[[Callable[P, T]], Callable[P, T]]:
|
|
80
78
|
"""Create a decorator wrapping a function, method or property with a warning call about a (pending) deprecation.
|
|
81
79
|
|
sqlspec/utils/fixtures.py
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING, Any
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Union
|
|
4
2
|
|
|
5
3
|
from sqlspec._serialization import decode_json
|
|
6
4
|
from sqlspec.exceptions import MissingDependencyError
|
|
@@ -13,7 +11,7 @@ if TYPE_CHECKING:
|
|
|
13
11
|
__all__ = ("open_fixture", "open_fixture_async")
|
|
14
12
|
|
|
15
13
|
|
|
16
|
-
def open_fixture(fixtures_path: Path
|
|
14
|
+
def open_fixture(fixtures_path: "Union[Path, AsyncPath]", fixture_name: str) -> "Any":
|
|
17
15
|
"""Loads JSON file with the specified fixture name
|
|
18
16
|
|
|
19
17
|
Args:
|
|
@@ -37,7 +35,7 @@ def open_fixture(fixtures_path: Path | AsyncPath, fixture_name: str) -> Any:
|
|
|
37
35
|
raise FileNotFoundError(msg)
|
|
38
36
|
|
|
39
37
|
|
|
40
|
-
async def open_fixture_async(fixtures_path: Path
|
|
38
|
+
async def open_fixture_async(fixtures_path: "Union[Path, AsyncPath]", fixture_name: str) -> "Any":
|
|
41
39
|
"""Loads JSON file with the specified fixture name
|
|
42
40
|
|
|
43
41
|
Args:
|
sqlspec/utils/module_loader.py
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
"""General utility functions."""
|
|
2
2
|
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
3
|
import sys
|
|
6
4
|
from importlib import import_module
|
|
7
5
|
from importlib.util import find_spec
|
|
8
6
|
from pathlib import Path
|
|
9
|
-
from typing import TYPE_CHECKING, Any
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
10
8
|
|
|
11
9
|
if TYPE_CHECKING:
|
|
12
10
|
from types import ModuleType
|
|
@@ -17,7 +15,7 @@ __all__ = (
|
|
|
17
15
|
)
|
|
18
16
|
|
|
19
17
|
|
|
20
|
-
def module_to_os_path(dotted_path: str = "app") -> Path:
|
|
18
|
+
def module_to_os_path(dotted_path: str = "app") -> "Path":
|
|
21
19
|
"""Find Module to OS Path.
|
|
22
20
|
|
|
23
21
|
Return a path to the base directory of the project or the module
|
|
@@ -44,7 +42,7 @@ def module_to_os_path(dotted_path: str = "app") -> Path:
|
|
|
44
42
|
return path.parent if path.is_file() else path
|
|
45
43
|
|
|
46
44
|
|
|
47
|
-
def import_string(dotted_path: str) -> Any:
|
|
45
|
+
def import_string(dotted_path: str) -> "Any":
|
|
48
46
|
"""Dotted Path Import.
|
|
49
47
|
|
|
50
48
|
Import a dotted module path and return the attribute/class designated by the
|
|
@@ -60,7 +58,7 @@ def import_string(dotted_path: str) -> Any:
|
|
|
60
58
|
object: The imported object.
|
|
61
59
|
"""
|
|
62
60
|
|
|
63
|
-
def _is_loaded(module: ModuleType
|
|
61
|
+
def _is_loaded(module: "Optional[ModuleType]") -> bool:
|
|
64
62
|
spec = getattr(module, "__spec__", None)
|
|
65
63
|
initializing = getattr(spec, "_initializing", False)
|
|
66
64
|
return bool(module and spec and not initializing)
|
sqlspec/utils/text.py
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"""General utility functions."""
|
|
2
2
|
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
3
|
import re
|
|
6
4
|
import unicodedata
|
|
5
|
+
from typing import Optional
|
|
7
6
|
|
|
8
7
|
__all__ = (
|
|
9
8
|
"check_email",
|
|
@@ -19,7 +18,7 @@ def check_email(email: str) -> str:
|
|
|
19
18
|
return email.lower()
|
|
20
19
|
|
|
21
20
|
|
|
22
|
-
def slugify(value: str, allow_unicode: bool = False, separator: str
|
|
21
|
+
def slugify(value: str, allow_unicode: bool = False, separator: "Optional[str]" = None) -> str:
|
|
23
22
|
"""Slugify.
|
|
24
23
|
|
|
25
24
|
Convert to ASCII if ``allow_unicode`` is ``False``. Convert spaces or repeated
|