structtype 0.6.0__tar.gz → 0.8.0__tar.gz
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-0.6.0 → structtype-0.8.0}/Makefile +5 -1
- {structtype-0.6.0/src/structtype.egg-info → structtype-0.8.0}/PKG-INFO +1 -1
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype/__init__.py +15 -1
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype/__init__.pyi +81 -141
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype/_adapter.py +15 -14
- structtype-0.8.0/src/structtype/_config.py +31 -0
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype/_core.c +2983 -825
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype/_inspect.py +36 -27
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype/_json_schema.py +3 -1
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype/_utils.py +26 -0
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype/_version.py +2 -2
- {structtype-0.6.0 → structtype-0.8.0/src/structtype.egg-info}/PKG-INFO +1 -1
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype.egg-info/SOURCES.txt +2 -0
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_adapter.py +29 -16
- structtype-0.8.0/tests/test_annotations.py +1770 -0
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_check.py +108 -7
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_constraints.py +220 -146
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_free_threading.py +30 -0
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_inspect.py +25 -29
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_json.py +131 -109
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_memory.py +3 -1
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_schema.py +51 -34
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_struct.py +250 -157
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_struct_meta.py +175 -39
- {structtype-0.6.0 → structtype-0.8.0}/tests/typecheck/api.py +1 -1
- {structtype-0.6.0 → structtype-0.8.0}/tests/typecheck/basic.py +11 -4
- {structtype-0.6.0 → structtype-0.8.0}/tests/typecheck/fields.py +17 -8
- {structtype-0.6.0 → structtype-0.8.0}/tests/typecheck/types.py +5 -3
- {structtype-0.6.0 → structtype-0.8.0}/.opencode/opencode.json +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/.opencode/plugins/graphify.js +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/AGENTS.md +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/LICENSE +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/MANIFEST.in +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/README.md +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/pyproject.toml +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/setup.cfg +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/setup.py +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype/atof.h +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype/atof_consts.h +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype/common.h +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype/itoa.h +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype/py.typed +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype/ryu.h +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype.egg-info/dependency_links.txt +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/src/structtype.egg-info/top_level.txt +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/tests/__init__.py +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/tests/conftest.py +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_JSONTestSuite.py +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_attrs.py +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_cpylint.py +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_msgspec.py +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_pydantic.py +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_raw.py +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_typecheck.py +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/tests/test_utils.py +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/tests/utils.py +0 -0
- {structtype-0.6.0 → structtype-0.8.0}/uv.lock +0 -0
|
@@ -93,7 +93,11 @@ format: ## Format files using ruff format
|
|
|
93
93
|
##@ Benchmark
|
|
94
94
|
.PHONY: bench
|
|
95
95
|
bench: ## run benchmarks
|
|
96
|
-
uv run benchmarks/bench_libs.py
|
|
96
|
+
uv run -p 3.15 benchmarks/bench_libs.py
|
|
97
|
+
|
|
98
|
+
.PHONY: bench-validators
|
|
99
|
+
bench-validators: ## run Serializer/Validator benchmarks
|
|
100
|
+
uv run -p 3.15 benchmarks/bench_validators.py
|
|
97
101
|
|
|
98
102
|
##@ Utility
|
|
99
103
|
.PHONY: clean
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
from ._adapter import StructAdapter
|
|
2
|
+
from ._config import StructConfig
|
|
2
3
|
from ._core import ( # type: ignore
|
|
3
4
|
ALL_BUILTIN_TYPES,
|
|
4
5
|
NODEFAULT,
|
|
5
6
|
UNSET,
|
|
7
|
+
BytesValidator,
|
|
8
|
+
CollectionValidator,
|
|
6
9
|
DecodeError,
|
|
7
10
|
EncodeError,
|
|
8
11
|
Factory,
|
|
9
12
|
Field,
|
|
13
|
+
NumericValidator,
|
|
10
14
|
Raw,
|
|
15
|
+
Serializer,
|
|
11
16
|
Struct,
|
|
12
|
-
StructConfig,
|
|
13
17
|
StructMeta,
|
|
18
|
+
StrValidator,
|
|
19
|
+
TimezoneValidator,
|
|
14
20
|
UnsetType,
|
|
15
21
|
ValidationError,
|
|
22
|
+
Validator,
|
|
16
23
|
)
|
|
17
24
|
from ._inspect import FieldInfo, fields
|
|
18
25
|
from ._json_schema import json_schema, json_schema_components, json_schema_dump
|
|
@@ -22,18 +29,25 @@ __all__ = [
|
|
|
22
29
|
"ALL_BUILTIN_TYPES",
|
|
23
30
|
"NODEFAULT",
|
|
24
31
|
"UNSET",
|
|
32
|
+
"BytesValidator",
|
|
33
|
+
"CollectionValidator",
|
|
25
34
|
"DecodeError",
|
|
26
35
|
"EncodeError",
|
|
27
36
|
"Factory",
|
|
28
37
|
"Field",
|
|
29
38
|
"FieldInfo",
|
|
39
|
+
"NumericValidator",
|
|
30
40
|
"Raw",
|
|
41
|
+
"Serializer",
|
|
42
|
+
"StrValidator",
|
|
31
43
|
"Struct",
|
|
32
44
|
"StructAdapter",
|
|
33
45
|
"StructConfig",
|
|
34
46
|
"StructMeta",
|
|
47
|
+
"TimezoneValidator",
|
|
35
48
|
"UnsetType",
|
|
36
49
|
"ValidationError",
|
|
50
|
+
"Validator",
|
|
37
51
|
"__version__",
|
|
38
52
|
"fields",
|
|
39
53
|
"json_schema",
|
|
@@ -8,17 +8,31 @@ from typing import (
|
|
|
8
8
|
Final,
|
|
9
9
|
Literal,
|
|
10
10
|
TypeAlias,
|
|
11
|
-
|
|
11
|
+
TypedDict,
|
|
12
12
|
final,
|
|
13
13
|
overload,
|
|
14
14
|
)
|
|
15
15
|
|
|
16
16
|
from typing_extensions import Buffer, Self, dataclass_transform
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
@final
|
|
19
|
+
class UnsetType(enum.Enum):
|
|
20
|
+
UNSET = "UNSET"
|
|
21
|
+
def __bool__(self) -> Literal[False]: ...
|
|
22
|
+
|
|
23
|
+
UNSET: Final = UnsetType.UNSET
|
|
24
|
+
|
|
25
|
+
@final
|
|
26
|
+
class _NoDefault(enum.Enum):
|
|
27
|
+
NODEFAULT = "NODEFAULT"
|
|
28
|
+
|
|
29
|
+
NODEFAULT: Final = _NoDefault.NODEFAULT
|
|
30
|
+
|
|
31
|
+
class StructConfig(TypedDict, total=False):
|
|
19
32
|
frozen: bool
|
|
20
33
|
eq: bool
|
|
21
34
|
order: bool
|
|
35
|
+
kw_only: bool
|
|
22
36
|
array_like: bool
|
|
23
37
|
repr_omit_defaults: bool
|
|
24
38
|
omit_defaults: bool
|
|
@@ -27,15 +41,14 @@ class StructConfig:
|
|
|
27
41
|
weakref: bool
|
|
28
42
|
dict: bool
|
|
29
43
|
cache_hash: bool
|
|
30
|
-
tag: str | int | None
|
|
44
|
+
tag: bool | str | int | Callable[[str], str | int] | None
|
|
31
45
|
tag_field: str | None
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
_SM = TypeVar("_SM", bound="StructMeta")
|
|
46
|
+
rename: (
|
|
47
|
+
None
|
|
48
|
+
| Literal["lower", "upper", "camel", "pascal", "kebab"]
|
|
49
|
+
| Callable[[str], str | None]
|
|
50
|
+
| Mapping[str, str]
|
|
51
|
+
)
|
|
39
52
|
|
|
40
53
|
class StructMeta(type):
|
|
41
54
|
__struct_fields__: ClassVar[tuple[str, ...]]
|
|
@@ -46,81 +59,20 @@ class StructMeta(type):
|
|
|
46
59
|
def __signature__(self) -> Signature: ...
|
|
47
60
|
@property
|
|
48
61
|
def __struct_config__(self) -> StructConfig: ...
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
name: str,
|
|
52
|
-
bases: tuple[type, ...],
|
|
53
|
-
namespace: dict[str, Any],
|
|
54
|
-
/,
|
|
55
|
-
*,
|
|
56
|
-
tag: bool | str | int | Callable[[str], str | int] | None = None,
|
|
57
|
-
tag_field: str | None = None,
|
|
58
|
-
rename: (
|
|
59
|
-
None
|
|
60
|
-
| Literal["lower", "upper", "camel", "pascal", "kebab"]
|
|
61
|
-
| Callable[[str], str | None]
|
|
62
|
-
| Mapping[str, str]
|
|
63
|
-
) = None,
|
|
64
|
-
omit_defaults: bool = False,
|
|
65
|
-
forbid_unknown_fields: bool = False,
|
|
66
|
-
frozen: bool = False,
|
|
67
|
-
eq: bool = True,
|
|
68
|
-
order: bool = False,
|
|
69
|
-
kw_only: bool = False,
|
|
70
|
-
repr_omit_defaults: bool = False,
|
|
71
|
-
array_like: bool = False,
|
|
72
|
-
weakref: bool = False,
|
|
73
|
-
dict: bool = False,
|
|
74
|
-
cache_hash: bool = False,
|
|
75
|
-
validate_on_init: bool = False,
|
|
76
|
-
) -> _SM: ...
|
|
77
|
-
|
|
78
|
-
@final
|
|
79
|
-
class UnsetType(enum.Enum):
|
|
80
|
-
UNSET = "UNSET"
|
|
81
|
-
def __bool__(self) -> Literal[False]: ...
|
|
82
|
-
|
|
83
|
-
UNSET: Final = UnsetType.UNSET
|
|
84
|
-
|
|
85
|
-
@final
|
|
86
|
-
class _NoDefault(enum.Enum):
|
|
87
|
-
NODEFAULT = "NODEFAULT"
|
|
88
|
-
|
|
89
|
-
NODEFAULT: Final = _NoDefault.NODEFAULT
|
|
62
|
+
@property
|
|
63
|
+
def struct_config(self) -> StructConfig: ...
|
|
90
64
|
|
|
91
65
|
@dataclass_transform(field_specifiers=("Field",)) # type: ignore
|
|
92
66
|
class Struct(metaclass=StructMeta):
|
|
93
67
|
__struct_fields__: ClassVar[tuple[str, ...]]
|
|
94
68
|
__struct_config__: ClassVar[StructConfig]
|
|
69
|
+
struct_config: ClassVar[StructConfig]
|
|
95
70
|
__struct_alias_fields__: ClassVar[tuple[str, ...]]
|
|
96
71
|
__struct_defaults__: ClassVar[tuple[Any, ...]]
|
|
97
72
|
__match_args__: ClassVar[tuple[str, ...]] = ...
|
|
98
73
|
# A default __init__ so that Structs with unknown field types
|
|
99
74
|
# won't error on every call to `__init__`
|
|
100
75
|
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
|
|
101
|
-
def __init_subclass__(
|
|
102
|
-
cls,
|
|
103
|
-
tag: bool | str | int | Callable[[str], str | int] | None = None,
|
|
104
|
-
tag_field: str | None = None,
|
|
105
|
-
rename: (
|
|
106
|
-
None
|
|
107
|
-
| Literal["lower", "upper", "camel", "pascal", "kebab"]
|
|
108
|
-
| Callable[[str], str | None]
|
|
109
|
-
| Mapping[str, str]
|
|
110
|
-
) = None,
|
|
111
|
-
omit_defaults: bool = False,
|
|
112
|
-
forbid_unknown_fields: bool = False,
|
|
113
|
-
frozen: bool = False,
|
|
114
|
-
eq: bool = True,
|
|
115
|
-
order: bool = False,
|
|
116
|
-
kw_only: bool = False,
|
|
117
|
-
repr_omit_defaults: bool = False,
|
|
118
|
-
array_like: bool = False,
|
|
119
|
-
weakref: bool = False,
|
|
120
|
-
dict: bool = False,
|
|
121
|
-
cache_hash: bool = False,
|
|
122
|
-
validate_on_init: bool = False,
|
|
123
|
-
) -> None: ...
|
|
124
76
|
def __rich_repr__(self) -> list[tuple[str, Any]]: ...
|
|
125
77
|
def __copy__(self) -> Self: ...
|
|
126
78
|
def __reduce__(self) -> tuple: ...
|
|
@@ -179,107 +131,95 @@ class Factory:
|
|
|
179
131
|
|
|
180
132
|
@final
|
|
181
133
|
class Field:
|
|
182
|
-
# Numeric:
|
|
183
|
-
@overload
|
|
184
134
|
def __init__(
|
|
185
135
|
self,
|
|
186
136
|
*,
|
|
187
|
-
gt: int | float | None = None,
|
|
188
|
-
lt: int | float | None = None,
|
|
189
|
-
multiple_of: int | float | None = None,
|
|
190
137
|
alias: str | None = None,
|
|
191
138
|
title: str | None = None,
|
|
192
139
|
description: str | None = None,
|
|
193
140
|
json_schema_extra: dict[str, Any] | None = None,
|
|
194
141
|
examples: list[Any] | None = None,
|
|
195
142
|
deprecated: bool | None = None,
|
|
196
|
-
dump: Callable[[Any], Any] | None = None,
|
|
197
|
-
validate: Callable[[Any], Any] | None = None,
|
|
198
143
|
) -> None: ...
|
|
199
|
-
|
|
144
|
+
alias: Final[str | None]
|
|
145
|
+
title: Final[str | None]
|
|
146
|
+
description: Final[str | None]
|
|
147
|
+
examples: Final[list[Any] | None]
|
|
148
|
+
deprecated: Final[bool | None]
|
|
149
|
+
json_schema_extra: Final[dict[str, Any] | None]
|
|
150
|
+
def __rich_repr__(self) -> list[tuple[str, Any]]: ...
|
|
151
|
+
|
|
152
|
+
@final
|
|
153
|
+
class Serializer:
|
|
200
154
|
def __init__(
|
|
201
155
|
self,
|
|
202
156
|
*,
|
|
203
|
-
|
|
204
|
-
le: int | float | None = None,
|
|
205
|
-
multiple_of: int | float | None = None,
|
|
206
|
-
alias: str | None = None,
|
|
207
|
-
title: str | None = None,
|
|
208
|
-
description: str | None = None,
|
|
209
|
-
json_schema_extra: dict[str, Any] | None = None,
|
|
210
|
-
examples: list[Any] | None = None,
|
|
211
|
-
deprecated: bool | None = None,
|
|
157
|
+
load: Callable[[Any], Any] | None = None,
|
|
212
158
|
dump: Callable[[Any], Any] | None = None,
|
|
213
|
-
validate: Callable[[Any], Any] | None = None,
|
|
214
159
|
) -> None: ...
|
|
215
|
-
|
|
160
|
+
load: Final[Callable[[Any], Any] | None]
|
|
161
|
+
dump: Final[Callable[[Any], Any] | None]
|
|
162
|
+
|
|
163
|
+
class Validator:
|
|
164
|
+
def __init__(self, fn: Callable[[Any], Any] | None = None) -> None: ...
|
|
165
|
+
def __call__(self, value: Any) -> None: ...
|
|
166
|
+
|
|
167
|
+
@final
|
|
168
|
+
class NumericValidator(Validator):
|
|
216
169
|
def __init__(
|
|
217
170
|
self,
|
|
218
171
|
*,
|
|
172
|
+
gt: int | float | None = None,
|
|
219
173
|
ge: int | float | None = None,
|
|
220
174
|
lt: int | float | None = None,
|
|
175
|
+
le: int | float | None = None,
|
|
221
176
|
multiple_of: int | float | None = None,
|
|
222
|
-
alias: str | None = None,
|
|
223
|
-
title: str | None = None,
|
|
224
|
-
description: str | None = None,
|
|
225
|
-
json_schema_extra: dict[str, Any] | None = None,
|
|
226
|
-
examples: list[Any] | None = None,
|
|
227
|
-
deprecated: bool | None = None,
|
|
228
|
-
dump: Callable[[Any], Any] | None = None,
|
|
229
|
-
validate: Callable[[Any], Any] | None = None,
|
|
230
177
|
) -> None: ...
|
|
231
|
-
|
|
178
|
+
gt: Final[int | float | None]
|
|
179
|
+
ge: Final[int | float | None]
|
|
180
|
+
lt: Final[int | float | None]
|
|
181
|
+
le: Final[int | float | None]
|
|
182
|
+
multiple_of: Final[int | float | None]
|
|
183
|
+
|
|
184
|
+
@final
|
|
185
|
+
class StrValidator(Validator):
|
|
232
186
|
def __init__(
|
|
233
187
|
self,
|
|
234
188
|
*,
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
alias: str | None = None,
|
|
239
|
-
title: str | None = None,
|
|
240
|
-
description: str | None = None,
|
|
241
|
-
json_schema_extra: dict[str, Any] | None = None,
|
|
242
|
-
examples: list[Any] | None = None,
|
|
243
|
-
deprecated: bool | None = None,
|
|
244
|
-
dump: Callable[[Any], Any] | None = None,
|
|
245
|
-
validate: Callable[[Any], Any] | None = None,
|
|
189
|
+
pattern: str | None = None,
|
|
190
|
+
min_length: _NonNegativeInt | None = None,
|
|
191
|
+
max_length: _NonNegativeInt | None = None,
|
|
246
192
|
) -> None: ...
|
|
247
|
-
|
|
248
|
-
|
|
193
|
+
pattern: Final[str | None]
|
|
194
|
+
min_length: Final[int | None]
|
|
195
|
+
max_length: Final[int | None]
|
|
196
|
+
|
|
197
|
+
@final
|
|
198
|
+
class BytesValidator(Validator):
|
|
249
199
|
def __init__(
|
|
250
200
|
self,
|
|
251
201
|
*,
|
|
252
|
-
pattern: str | None = None,
|
|
253
202
|
min_length: _NonNegativeInt | None = None,
|
|
254
203
|
max_length: _NonNegativeInt | None = None,
|
|
255
|
-
tz: bool | None = None,
|
|
256
|
-
alias: str | None = None,
|
|
257
|
-
title: str | None = None,
|
|
258
|
-
description: str | None = None,
|
|
259
|
-
json_schema_extra: dict[str, Any] | None = None,
|
|
260
|
-
examples: list[Any] | None = None,
|
|
261
|
-
deprecated: bool | None = None,
|
|
262
|
-
dump: Callable[[Any], Any] | None = None,
|
|
263
|
-
validate: Callable[[Any], Any] | None = None,
|
|
264
204
|
) -> None: ...
|
|
265
|
-
alias: Final[str | None]
|
|
266
|
-
gt: Final[int | float | None]
|
|
267
|
-
ge: Final[int | float | None]
|
|
268
|
-
lt: Final[int | float | None]
|
|
269
|
-
le: Final[int | float | None]
|
|
270
|
-
multiple_of: Final[int | float | None]
|
|
271
|
-
pattern: Final[str | None]
|
|
272
205
|
min_length: Final[int | None]
|
|
273
206
|
max_length: Final[int | None]
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
207
|
+
|
|
208
|
+
@final
|
|
209
|
+
class CollectionValidator(Validator):
|
|
210
|
+
def __init__(
|
|
211
|
+
self,
|
|
212
|
+
*,
|
|
213
|
+
min_length: _NonNegativeInt | None = None,
|
|
214
|
+
max_length: _NonNegativeInt | None = None,
|
|
215
|
+
) -> None: ...
|
|
216
|
+
min_length: Final[int | None]
|
|
217
|
+
max_length: Final[int | None]
|
|
218
|
+
|
|
219
|
+
@final
|
|
220
|
+
class TimezoneValidator(Validator):
|
|
221
|
+
def __init__(self, *, tz: bool) -> None: ...
|
|
222
|
+
tz: Final[bool]
|
|
283
223
|
|
|
284
224
|
class FieldInfo(Struct):
|
|
285
225
|
name: str
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import Any, get_args
|
|
2
2
|
|
|
3
3
|
from ._core import ( # type: ignore
|
|
4
|
-
|
|
4
|
+
Serializer as _Serializer,
|
|
5
5
|
)
|
|
6
6
|
from ._core import ( # type: ignore
|
|
7
7
|
_dump,
|
|
@@ -11,22 +11,22 @@ from ._core import ( # type: ignore
|
|
|
11
11
|
)
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
def
|
|
15
|
-
"""True if the annotation carries a ``
|
|
14
|
+
def _has_serializer(ann):
|
|
15
|
+
"""True if the annotation carries a ``Serializer`` with ``load``/``dump``."""
|
|
16
16
|
metadata = getattr(ann, "__metadata__", None)
|
|
17
17
|
if metadata is not None:
|
|
18
18
|
for meta in metadata:
|
|
19
|
-
if isinstance(meta,
|
|
20
|
-
meta.
|
|
19
|
+
if isinstance(meta, _Serializer) and (
|
|
20
|
+
meta.load is not None or meta.dump is not None
|
|
21
21
|
):
|
|
22
22
|
return True
|
|
23
23
|
supertype = getattr(ann, "__supertype__", None) # NewType
|
|
24
|
-
if supertype is not None and
|
|
24
|
+
if supertype is not None and _has_serializer(supertype):
|
|
25
25
|
return True
|
|
26
26
|
value = getattr(ann, "__value__", None) # PEP 695 type alias
|
|
27
|
-
if value is not None and
|
|
27
|
+
if value is not None and _has_serializer(value):
|
|
28
28
|
return True
|
|
29
|
-
return any(
|
|
29
|
+
return any(_has_serializer(arg) for arg in get_args(ann))
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
class StructAdapter:
|
|
@@ -35,8 +35,8 @@ class StructAdapter:
|
|
|
35
35
|
Useful when you want to validate or serialize plain Python types
|
|
36
36
|
(e.g. ``list[int]``) without defining a full ``Struct`` subclass.
|
|
37
37
|
|
|
38
|
-
``
|
|
39
|
-
``StructAdapter`` — annotations carrying one are rejected. Implement the
|
|
38
|
+
``Serializer(load=...)`` / ``Serializer(dump=...)`` codecs are not supported
|
|
39
|
+
on ``StructAdapter`` — annotations carrying one are rejected. Implement the
|
|
40
40
|
``struct_dump`` / ``struct_validate`` protocol methods on the custom type,
|
|
41
41
|
or use a ``Struct``.
|
|
42
42
|
|
|
@@ -49,11 +49,12 @@ class StructAdapter:
|
|
|
49
49
|
__slots__ = ("_type",)
|
|
50
50
|
|
|
51
51
|
def __init__(self, type: Any):
|
|
52
|
-
if
|
|
52
|
+
if _has_serializer(type):
|
|
53
53
|
raise TypeError(
|
|
54
|
-
"`
|
|
55
|
-
"on StructAdapter; define `struct_dump
|
|
56
|
-
"on the custom type, or use a
|
|
54
|
+
"`Serializer(load=...)`/`Serializer(dump=...)` codecs are not "
|
|
55
|
+
"supported on StructAdapter; define `struct_dump`/"
|
|
56
|
+
"`struct_validate` methods on the custom type, or use a "
|
|
57
|
+
"`Struct` instead"
|
|
57
58
|
)
|
|
58
59
|
self._type = type
|
|
59
60
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from collections.abc import Callable, Mapping
|
|
2
|
+
from typing import Literal, TypedDict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class StructConfig(TypedDict, total=False):
|
|
6
|
+
"""Configuration for a Struct type, mirroring the Struct config options.
|
|
7
|
+
|
|
8
|
+
Used as a class-body ``struct_config`` attribute. Keys not present inherit
|
|
9
|
+
from the base class; ``__struct_config__`` returns the fully-resolved dict.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
frozen: bool
|
|
13
|
+
eq: bool
|
|
14
|
+
order: bool
|
|
15
|
+
kw_only: bool
|
|
16
|
+
repr_omit_defaults: bool
|
|
17
|
+
array_like: bool
|
|
18
|
+
omit_defaults: bool
|
|
19
|
+
forbid_unknown_fields: bool
|
|
20
|
+
validate_on_init: bool
|
|
21
|
+
weakref: bool
|
|
22
|
+
dict: bool
|
|
23
|
+
cache_hash: bool
|
|
24
|
+
tag: bool | str | int | Callable[[str], str | int] | None
|
|
25
|
+
tag_field: str | None
|
|
26
|
+
rename: (
|
|
27
|
+
None
|
|
28
|
+
| Literal["lower", "upper", "camel", "pascal", "kebab"]
|
|
29
|
+
| Callable[[str], str | None]
|
|
30
|
+
| Mapping[str, str]
|
|
31
|
+
)
|