structtype 0.3.0__cp315-cp315-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- structtype/__init__.py +17 -0
- structtype/__init__.pyi +350 -0
- structtype/_adapter.py +128 -0
- structtype/_core.cp315-win_amd64.pyd +0 -0
- structtype/_inspect.py +1183 -0
- structtype/_json_schema.py +532 -0
- structtype/_utils.py +410 -0
- structtype/_version.py +24 -0
- structtype/py.typed +0 -0
- structtype-0.3.0.dist-info/METADATA +80 -0
- structtype-0.3.0.dist-info/RECORD +14 -0
- structtype-0.3.0.dist-info/WHEEL +5 -0
- structtype-0.3.0.dist-info/licenses/LICENSE +27 -0
- structtype-0.3.0.dist-info/top_level.txt +1 -0
structtype/__init__.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from ._adapter import StrAdapter, StructAdapter
|
|
2
|
+
from ._core import (
|
|
3
|
+
NODEFAULT,
|
|
4
|
+
UNSET,
|
|
5
|
+
DecodeError,
|
|
6
|
+
EncodeError,
|
|
7
|
+
Field,
|
|
8
|
+
Raw,
|
|
9
|
+
Struct,
|
|
10
|
+
StructConfig,
|
|
11
|
+
StructMeta,
|
|
12
|
+
UnsetType,
|
|
13
|
+
ValidationError,
|
|
14
|
+
)
|
|
15
|
+
from ._inspect import FieldInfo, fields
|
|
16
|
+
from ._json_schema import json_schema, json_schema_components, json_schema_dump
|
|
17
|
+
from ._version import __version__
|
structtype/__init__.pyi
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import enum
|
|
2
|
+
from collections.abc import Callable, Iterable, Iterator, Mapping
|
|
3
|
+
from inspect import Signature
|
|
4
|
+
from typing import Any, ClassVar, Final, Literal, TypeAlias, TypeVar, final, overload
|
|
5
|
+
|
|
6
|
+
from typing_extensions import Buffer, Self, dataclass_transform
|
|
7
|
+
|
|
8
|
+
from . import StructConfig
|
|
9
|
+
|
|
10
|
+
# PEP 673 explicitly rejects using Self in metaclass definitions:
|
|
11
|
+
# https://peps.python.org/pep-0673/#valid-locations-for-self
|
|
12
|
+
#
|
|
13
|
+
# Typeshed works around this by using a type variable as well:
|
|
14
|
+
# https://github.com/python/typeshed/blob/17bde1bd5e556de001adde3c2f340ba1c3581bd2/stdlib/abc.pyi#L14-L19
|
|
15
|
+
_SM = TypeVar("_SM", bound="StructMeta")
|
|
16
|
+
|
|
17
|
+
class StructMeta(type):
|
|
18
|
+
__struct_fields__: ClassVar[tuple[str, ...]]
|
|
19
|
+
__struct_defaults__: ClassVar[tuple[Any, ...]]
|
|
20
|
+
__struct_encode_fields__: ClassVar[tuple[str, ...]]
|
|
21
|
+
__match_args__: ClassVar[tuple[str, ...]]
|
|
22
|
+
@property
|
|
23
|
+
def __signature__(self) -> Signature: ...
|
|
24
|
+
@property
|
|
25
|
+
def __struct_config__(self) -> StructConfig: ...
|
|
26
|
+
def __new__(
|
|
27
|
+
mcls: type[_SM],
|
|
28
|
+
name: str,
|
|
29
|
+
bases: tuple[type, ...],
|
|
30
|
+
namespace: dict[str, Any],
|
|
31
|
+
/,
|
|
32
|
+
*,
|
|
33
|
+
tag: bool | str | int | Callable[[str], str | int] | None = None,
|
|
34
|
+
tag_field: str | None = None,
|
|
35
|
+
rename: (
|
|
36
|
+
None
|
|
37
|
+
| Literal["lower", "upper", "camel", "pascal", "kebab"]
|
|
38
|
+
| Callable[[str], str | None]
|
|
39
|
+
| Mapping[str, str]
|
|
40
|
+
) = None,
|
|
41
|
+
omit_defaults: bool = False,
|
|
42
|
+
forbid_unknown_fields: bool = False,
|
|
43
|
+
frozen: bool = False,
|
|
44
|
+
eq: bool = True,
|
|
45
|
+
order: bool = False,
|
|
46
|
+
kw_only: bool = False,
|
|
47
|
+
repr_omit_defaults: bool = False,
|
|
48
|
+
array_like: bool = False,
|
|
49
|
+
gc: bool = True,
|
|
50
|
+
weakref: bool = False,
|
|
51
|
+
dict: bool = False,
|
|
52
|
+
cache_hash: bool = False,
|
|
53
|
+
validate_on_init: bool = False,
|
|
54
|
+
) -> _SM: ...
|
|
55
|
+
|
|
56
|
+
_T = TypeVar("_T")
|
|
57
|
+
|
|
58
|
+
@final
|
|
59
|
+
class UnsetType(enum.Enum):
|
|
60
|
+
UNSET = "UNSET"
|
|
61
|
+
def __bool__(self) -> Literal[False]: ...
|
|
62
|
+
|
|
63
|
+
UNSET: Final = UnsetType.UNSET
|
|
64
|
+
|
|
65
|
+
@final
|
|
66
|
+
class _NoDefault(enum.Enum):
|
|
67
|
+
NODEFAULT = "NODEFAULT"
|
|
68
|
+
|
|
69
|
+
NODEFAULT: Final = _NoDefault.NODEFAULT
|
|
70
|
+
|
|
71
|
+
@dataclass_transform(field_specifiers=(Field,))
|
|
72
|
+
class Struct(metaclass=StructMeta):
|
|
73
|
+
__struct_fields__: ClassVar[tuple[str, ...]]
|
|
74
|
+
__struct_config__: ClassVar[StructConfig]
|
|
75
|
+
__struct_encode_fields__: ClassVar[tuple[str, ...]]
|
|
76
|
+
__struct_defaults__: ClassVar[tuple[Any, ...]]
|
|
77
|
+
__match_args__: ClassVar[tuple[str, ...]]
|
|
78
|
+
# A default __init__ so that Structs with unknown field types
|
|
79
|
+
# won't error on every call to `__init__`
|
|
80
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
|
|
81
|
+
def __init_subclass__(
|
|
82
|
+
cls,
|
|
83
|
+
tag: bool | str | int | Callable[[str], str | int] | None = None,
|
|
84
|
+
tag_field: str | None = None,
|
|
85
|
+
rename: (
|
|
86
|
+
None
|
|
87
|
+
| Literal["lower", "upper", "camel", "pascal", "kebab"]
|
|
88
|
+
| Callable[[str], str | None]
|
|
89
|
+
| Mapping[str, str]
|
|
90
|
+
) = None,
|
|
91
|
+
omit_defaults: bool = False,
|
|
92
|
+
forbid_unknown_fields: bool = False,
|
|
93
|
+
frozen: bool = False,
|
|
94
|
+
eq: bool = True,
|
|
95
|
+
order: bool = False,
|
|
96
|
+
kw_only: bool = False,
|
|
97
|
+
repr_omit_defaults: bool = False,
|
|
98
|
+
array_like: bool = False,
|
|
99
|
+
gc: bool = True,
|
|
100
|
+
weakref: bool = False,
|
|
101
|
+
dict: bool = False,
|
|
102
|
+
cache_hash: bool = False,
|
|
103
|
+
validate_on_init: bool = False,
|
|
104
|
+
) -> None: ...
|
|
105
|
+
def __rich_repr__(self) -> list[tuple[str, Any]]: ...
|
|
106
|
+
def __copy__(self) -> Self: ...
|
|
107
|
+
def __reduce__(self) -> tuple: ...
|
|
108
|
+
def __replace__(self, **changes: Any) -> Self: ...
|
|
109
|
+
def __iter__(self) -> Iterator[tuple[str, Any]]: ...
|
|
110
|
+
def struct_dump_json(
|
|
111
|
+
self,
|
|
112
|
+
*,
|
|
113
|
+
enc_hook: Callable[[Any], Any] | None = None,
|
|
114
|
+
decimal_format: Literal["string", "number"]
|
|
115
|
+
| Callable[[Any], Any]
|
|
116
|
+
| None = None,
|
|
117
|
+
uuid_format: Literal["canonical", "hex"] | None = None,
|
|
118
|
+
order: Literal["deterministic", "sorted"] | None = None,
|
|
119
|
+
) -> bytes: ...
|
|
120
|
+
def struct_dump(
|
|
121
|
+
self,
|
|
122
|
+
*,
|
|
123
|
+
enc_hook: Callable[[Any], Any] | None = None,
|
|
124
|
+
order: Literal["deterministic", "sorted"] | None = None,
|
|
125
|
+
str_keys: bool = False,
|
|
126
|
+
builtin_types: Iterable[type] | None = None,
|
|
127
|
+
) -> dict[str, Any] | list[Any]: ...
|
|
128
|
+
def struct_force_setattr(self, name: str, value: Any) -> None: ...
|
|
129
|
+
def struct_validate_self(self) -> None: ...
|
|
130
|
+
@classmethod
|
|
131
|
+
def struct_validate_json(
|
|
132
|
+
cls: type[_T],
|
|
133
|
+
buf: str | Buffer,
|
|
134
|
+
*,
|
|
135
|
+
strict: bool = True,
|
|
136
|
+
dec_hook: Callable[[type[Any], Any], Any] | None = None,
|
|
137
|
+
) -> _T: ...
|
|
138
|
+
@classmethod
|
|
139
|
+
def struct_validate(
|
|
140
|
+
cls: type[_T],
|
|
141
|
+
obj: Any,
|
|
142
|
+
*,
|
|
143
|
+
strict: bool = True,
|
|
144
|
+
from_attributes: bool = False,
|
|
145
|
+
dec_hook: Callable[[type[Any], Any], Any] | None = None,
|
|
146
|
+
) -> _T: ...
|
|
147
|
+
|
|
148
|
+
# Lie and say `Raw` is a subclass of `bytes`, so mypy will accept it in most
|
|
149
|
+
# places where an object that implements the buffer protocol is valid
|
|
150
|
+
@final
|
|
151
|
+
class Raw(bytes):
|
|
152
|
+
@overload
|
|
153
|
+
def __new__(cls) -> "Raw": ...
|
|
154
|
+
@overload
|
|
155
|
+
def __new__(cls, msg: Buffer | str) -> "Raw": ...
|
|
156
|
+
def copy(self) -> "Raw": ...
|
|
157
|
+
|
|
158
|
+
#: We can't represent this in types, only via a name:
|
|
159
|
+
_NonNegativeInt: TypeAlias = int
|
|
160
|
+
|
|
161
|
+
@final
|
|
162
|
+
class Field:
|
|
163
|
+
# Numeric:
|
|
164
|
+
@overload
|
|
165
|
+
def __init__(
|
|
166
|
+
self,
|
|
167
|
+
*,
|
|
168
|
+
gt: int | float | None = None,
|
|
169
|
+
lt: int | float | None = None,
|
|
170
|
+
multiple_of: int | float | None = None,
|
|
171
|
+
default: Any = NODEFAULT,
|
|
172
|
+
default_factory: Callable[[], Any] | None = None,
|
|
173
|
+
alias: str | None = None,
|
|
174
|
+
title: str | None = None,
|
|
175
|
+
description: str | None = None,
|
|
176
|
+
json_schema_extra: dict[str, Any] | None = None,
|
|
177
|
+
examples: list[Any] | None = None,
|
|
178
|
+
) -> None: ...
|
|
179
|
+
@overload
|
|
180
|
+
def __init__(
|
|
181
|
+
self,
|
|
182
|
+
*,
|
|
183
|
+
gt: int | float | None = None,
|
|
184
|
+
le: int | float | None = None,
|
|
185
|
+
multiple_of: int | float | None = None,
|
|
186
|
+
default: Any = NODEFAULT,
|
|
187
|
+
default_factory: Callable[[], Any] | None = None,
|
|
188
|
+
alias: str | None = None,
|
|
189
|
+
title: str | None = None,
|
|
190
|
+
description: str | None = None,
|
|
191
|
+
json_schema_extra: dict[str, Any] | None = None,
|
|
192
|
+
examples: list[Any] | None = None,
|
|
193
|
+
) -> None: ...
|
|
194
|
+
@overload
|
|
195
|
+
def __init__(
|
|
196
|
+
self,
|
|
197
|
+
*,
|
|
198
|
+
ge: int | float | None = None,
|
|
199
|
+
lt: int | float | None = None,
|
|
200
|
+
multiple_of: int | float | None = None,
|
|
201
|
+
default: Any = NODEFAULT,
|
|
202
|
+
default_factory: Callable[[], Any] | None = None,
|
|
203
|
+
alias: str | None = None,
|
|
204
|
+
title: str | None = None,
|
|
205
|
+
description: str | None = None,
|
|
206
|
+
json_schema_extra: dict[str, Any] | None = None,
|
|
207
|
+
examples: list[Any] | None = None,
|
|
208
|
+
) -> None: ...
|
|
209
|
+
@overload
|
|
210
|
+
def __init__(
|
|
211
|
+
self,
|
|
212
|
+
*,
|
|
213
|
+
ge: int | float | None = None,
|
|
214
|
+
le: int | float | None = None,
|
|
215
|
+
multiple_of: int | float | None = None,
|
|
216
|
+
default: Any = NODEFAULT,
|
|
217
|
+
default_factory: Callable[[], Any] | None = None,
|
|
218
|
+
alias: str | None = None,
|
|
219
|
+
title: str | None = None,
|
|
220
|
+
description: str | None = None,
|
|
221
|
+
json_schema_extra: dict[str, Any] | None = None,
|
|
222
|
+
examples: list[Any] | None = None,
|
|
223
|
+
) -> None: ...
|
|
224
|
+
# Other (string/datetime):
|
|
225
|
+
@overload
|
|
226
|
+
def __init__(
|
|
227
|
+
self,
|
|
228
|
+
*,
|
|
229
|
+
pattern: str | None = None,
|
|
230
|
+
min_length: _NonNegativeInt | None = None,
|
|
231
|
+
max_length: _NonNegativeInt | None = None,
|
|
232
|
+
tz: bool | None = None,
|
|
233
|
+
default: Any = NODEFAULT,
|
|
234
|
+
default_factory: Callable[[], Any] | None = None,
|
|
235
|
+
alias: str | None = None,
|
|
236
|
+
title: str | None = None,
|
|
237
|
+
description: str | None = None,
|
|
238
|
+
json_schema_extra: dict[str, Any] | None = None,
|
|
239
|
+
examples: list[Any] | None = None,
|
|
240
|
+
) -> None: ...
|
|
241
|
+
default: Final[Any]
|
|
242
|
+
default_factory: Final[Callable[[], Any] | None]
|
|
243
|
+
alias: Final[str | None]
|
|
244
|
+
gt: Final[int | float | None]
|
|
245
|
+
ge: Final[int | float | None]
|
|
246
|
+
lt: Final[int | float | None]
|
|
247
|
+
le: Final[int | float | None]
|
|
248
|
+
multiple_of: Final[int | float | None]
|
|
249
|
+
pattern: Final[str | None]
|
|
250
|
+
min_length: Final[int | None]
|
|
251
|
+
max_length: Final[int | None]
|
|
252
|
+
tz: Final[int | None]
|
|
253
|
+
title: Final[str | None]
|
|
254
|
+
description: Final[str | None]
|
|
255
|
+
examples: Final[list[Any] | None]
|
|
256
|
+
json_schema_extra: Final[dict[str, Any] | None]
|
|
257
|
+
def __rich_repr__(self) -> list[tuple[str, Any]]: ...
|
|
258
|
+
|
|
259
|
+
class StructConfig:
|
|
260
|
+
frozen: bool
|
|
261
|
+
eq: bool
|
|
262
|
+
order: bool
|
|
263
|
+
array_like: bool
|
|
264
|
+
gc: bool
|
|
265
|
+
repr_omit_defaults: bool
|
|
266
|
+
omit_defaults: bool
|
|
267
|
+
forbid_unknown_fields: bool
|
|
268
|
+
validate_on_init: bool
|
|
269
|
+
weakref: bool
|
|
270
|
+
dict: bool
|
|
271
|
+
cache_hash: bool
|
|
272
|
+
tag: str | int | None
|
|
273
|
+
tag_field: str | None
|
|
274
|
+
|
|
275
|
+
class FieldInfo(Struct):
|
|
276
|
+
name: str
|
|
277
|
+
encode_name: str
|
|
278
|
+
type: Any
|
|
279
|
+
default: Any = NODEFAULT
|
|
280
|
+
default_factory: Any = NODEFAULT
|
|
281
|
+
|
|
282
|
+
@property
|
|
283
|
+
def required(self) -> bool: ...
|
|
284
|
+
|
|
285
|
+
def fields(type_or_instance: Struct | type[Struct]) -> tuple[FieldInfo, ...]: ...
|
|
286
|
+
def json_schema(
|
|
287
|
+
type: Any,
|
|
288
|
+
*,
|
|
289
|
+
schema_hook: Callable[[type[Any]], dict[str, Any]] | None = None,
|
|
290
|
+
ref_template: str = "#/$defs/{name}",
|
|
291
|
+
) -> dict[str, Any]: ...
|
|
292
|
+
def json_schema_dump(
|
|
293
|
+
type: Any,
|
|
294
|
+
*,
|
|
295
|
+
schema_hook: Callable[[type[Any]], dict[str, Any]] | None = None,
|
|
296
|
+
ref_template: str = "#/$defs/{name}",
|
|
297
|
+
) -> bytes: ...
|
|
298
|
+
def json_schema_components(
|
|
299
|
+
types: Iterable[Any],
|
|
300
|
+
*,
|
|
301
|
+
schema_hook: Callable[[type[Any]], dict[str, Any]] | None = None,
|
|
302
|
+
ref_template: str = "#/$defs/{name}",
|
|
303
|
+
) -> tuple[tuple[dict[str, Any], ...], dict[str, Any]]: ...
|
|
304
|
+
|
|
305
|
+
class StructAdapter:
|
|
306
|
+
def __init__(self, type: Any): ...
|
|
307
|
+
def struct_validate_json(
|
|
308
|
+
self,
|
|
309
|
+
buf: str | Buffer,
|
|
310
|
+
*,
|
|
311
|
+
strict: bool = True,
|
|
312
|
+
dec_hook: Callable[[type[Any], Any], Any] | None = None,
|
|
313
|
+
) -> Any: ...
|
|
314
|
+
def struct_dump_json(
|
|
315
|
+
self,
|
|
316
|
+
obj: Any,
|
|
317
|
+
*,
|
|
318
|
+
enc_hook: Callable[[Any], Any] | None = None,
|
|
319
|
+
decimal_format: Literal["string", "number"]
|
|
320
|
+
| Callable[[Any], Any]
|
|
321
|
+
| None = None,
|
|
322
|
+
uuid_format: Literal["canonical", "hex"] | None = None,
|
|
323
|
+
order: Literal["deterministic", "sorted"] | None = None,
|
|
324
|
+
) -> bytes: ...
|
|
325
|
+
def struct_validate(
|
|
326
|
+
self,
|
|
327
|
+
obj: Any,
|
|
328
|
+
*,
|
|
329
|
+
strict: bool = True,
|
|
330
|
+
dec_hook: Callable[[type[Any], Any], Any] | None = None,
|
|
331
|
+
from_attributes: bool = False,
|
|
332
|
+
) -> Any: ...
|
|
333
|
+
def struct_dump(
|
|
334
|
+
self,
|
|
335
|
+
obj: Any,
|
|
336
|
+
*,
|
|
337
|
+
enc_hook: Callable[[Any], Any] | None = None,
|
|
338
|
+
order: Literal["deterministic", "sorted"] | None = None,
|
|
339
|
+
str_keys: bool = False,
|
|
340
|
+
builtin_types: Iterable[type] | None = None,
|
|
341
|
+
) -> Any: ...
|
|
342
|
+
|
|
343
|
+
class StrAdapter:
|
|
344
|
+
def __new__(cls, type: type[Any]) -> type[str]: ...
|
|
345
|
+
|
|
346
|
+
class EncodeError(ValueError): ...
|
|
347
|
+
class DecodeError(ValueError): ...
|
|
348
|
+
class ValidationError(ValueError): ...
|
|
349
|
+
|
|
350
|
+
__version__: str
|
structtype/_adapter.py
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from ._core import _dump, _json_decode, _json_encode, _validate
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class StructAdapter:
|
|
7
|
+
"""Adapter for validating and serializing types without subclassing ``Struct``.
|
|
8
|
+
|
|
9
|
+
Useful when you want to validate or serialize plain Python types
|
|
10
|
+
(e.g. ``list[int]``) without defining a full ``Struct`` subclass.
|
|
11
|
+
|
|
12
|
+
>>> from structtype import StructAdapter
|
|
13
|
+
>>> adapter = StructAdapter(list[int])
|
|
14
|
+
>>> adapter.struct_validate_json(b"[1, 2, 3]")
|
|
15
|
+
[1, 2, 3]
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
__slots__ = ("_type",)
|
|
19
|
+
|
|
20
|
+
def __init__(self, type: Any):
|
|
21
|
+
self._type = type
|
|
22
|
+
|
|
23
|
+
def struct_validate_json(self, buf, *, strict=True, dec_hook=None):
|
|
24
|
+
"""Validate JSON bytes and decode into the adapter's type.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
buf : str or bytes
|
|
29
|
+
The JSON message to decode.
|
|
30
|
+
strict : bool, optional
|
|
31
|
+
If True (default), unmatched fields cause an error.
|
|
32
|
+
dec_hook : callable, optional
|
|
33
|
+
A callback for customizing decoding of specific types.
|
|
34
|
+
"""
|
|
35
|
+
return _json_decode(buf, type=self._type, strict=strict, dec_hook=dec_hook)
|
|
36
|
+
|
|
37
|
+
def struct_dump_json(
|
|
38
|
+
self, obj, *, enc_hook=None, decimal_format=None, uuid_format=None, order=None
|
|
39
|
+
):
|
|
40
|
+
"""Encode a validated object to JSON bytes.
|
|
41
|
+
|
|
42
|
+
Parameters
|
|
43
|
+
----------
|
|
44
|
+
obj : Any
|
|
45
|
+
A value to encode. Must match the adapter's type.
|
|
46
|
+
enc_hook : callable, optional
|
|
47
|
+
A callback for customizing encoding of specific types.
|
|
48
|
+
decimal_format : str or callable, optional
|
|
49
|
+
Controls how ``Decimal`` values are encoded.
|
|
50
|
+
uuid_format : str, optional
|
|
51
|
+
Controls how ``UUID`` values are encoded.
|
|
52
|
+
order : str, optional
|
|
53
|
+
Determines key ordering in JSON objects.
|
|
54
|
+
"""
|
|
55
|
+
return _json_encode(
|
|
56
|
+
obj,
|
|
57
|
+
enc_hook=enc_hook,
|
|
58
|
+
decimal_format=decimal_format,
|
|
59
|
+
uuid_format=uuid_format,
|
|
60
|
+
order=order,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
def struct_validate(
|
|
64
|
+
self, obj, *, strict=True, dec_hook=None, from_attributes=False
|
|
65
|
+
):
|
|
66
|
+
"""Validate a Python object against the adapter's type.
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
obj : Any
|
|
71
|
+
A Python object to validate and convert.
|
|
72
|
+
strict : bool, optional
|
|
73
|
+
If True (default), unmatched fields cause an error.
|
|
74
|
+
dec_hook : callable, optional
|
|
75
|
+
A callback for customizing decoding of specific types.
|
|
76
|
+
from_attributes : bool, optional
|
|
77
|
+
If True, accept objects with attributes instead of dict keys.
|
|
78
|
+
"""
|
|
79
|
+
return _validate(
|
|
80
|
+
obj,
|
|
81
|
+
self._type,
|
|
82
|
+
strict=strict,
|
|
83
|
+
dec_hook=dec_hook,
|
|
84
|
+
from_attributes=from_attributes,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def struct_dump(
|
|
88
|
+
self, obj, *, enc_hook=None, order=None, str_keys=False, builtin_types=None
|
|
89
|
+
):
|
|
90
|
+
"""Convert a validated object to built-in Python types (``dict``, ``list``, etc.)."""
|
|
91
|
+
return _dump(
|
|
92
|
+
obj,
|
|
93
|
+
builtin_types=builtin_types,
|
|
94
|
+
str_keys=str_keys,
|
|
95
|
+
enc_hook=enc_hook,
|
|
96
|
+
order=order,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class StrAdapter:
|
|
101
|
+
"""Create a ``str`` subclass wrapper for validating a type during
|
|
102
|
+
structtype serialization.
|
|
103
|
+
|
|
104
|
+
Wraps a type that has a single-argument string constructor
|
|
105
|
+
(e.g. ``HttpUrl``, ``EmailStr``, ``IPv4Address``) into a ``str``
|
|
106
|
+
subclass. The wrapped value is stored as a string but validated by
|
|
107
|
+
calling ``typ(value)`` on construction. During structtype
|
|
108
|
+
validation and serialization, the wrapper is treated as a native
|
|
109
|
+
``str``.
|
|
110
|
+
|
|
111
|
+
>>> from structtype import StrAdapter, Struct
|
|
112
|
+
>>> from ipaddress import IPv4Address
|
|
113
|
+
>>>
|
|
114
|
+
>>> class Config(Struct):
|
|
115
|
+
... ip: StrAdapter(IPv4Address)
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
__slots__ = ()
|
|
119
|
+
|
|
120
|
+
def __new__(cls, typ):
|
|
121
|
+
return type(
|
|
122
|
+
f"_Wrapped_{typ.__name__}",
|
|
123
|
+
(str,),
|
|
124
|
+
{
|
|
125
|
+
"__slots__": (),
|
|
126
|
+
"__new__": lambda self, v: str.__new__(self, str(typ(v))),
|
|
127
|
+
},
|
|
128
|
+
)
|
|
Binary file
|