marshmallow 3.21.3__py3-none-any.whl → 3.23.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.
- marshmallow/class_registry.py +1 -1
- marshmallow/decorators.py +13 -11
- marshmallow/fields.py +14 -10
- marshmallow/schema.py +55 -61
- marshmallow/types.py +0 -1
- {marshmallow-3.21.3.dist-info → marshmallow-3.23.0.dist-info}/METADATA +35 -20
- {marshmallow-3.21.3.dist-info → marshmallow-3.23.0.dist-info}/RECORD +9 -9
- {marshmallow-3.21.3.dist-info → marshmallow-3.23.0.dist-info}/LICENSE +0 -0
- {marshmallow-3.21.3.dist-info → marshmallow-3.23.0.dist-info}/WHEEL +0 -0
marshmallow/class_registry.py
CHANGED
marshmallow/decorators.py
CHANGED
|
@@ -68,6 +68,7 @@ Example: ::
|
|
|
68
68
|
from __future__ import annotations
|
|
69
69
|
|
|
70
70
|
import functools
|
|
71
|
+
from collections import defaultdict
|
|
71
72
|
from typing import Any, Callable, cast
|
|
72
73
|
|
|
73
74
|
PRE_DUMP = "pre_dump"
|
|
@@ -79,7 +80,7 @@ VALIDATES_SCHEMA = "validates_schema"
|
|
|
79
80
|
|
|
80
81
|
|
|
81
82
|
class MarshmallowHook:
|
|
82
|
-
__marshmallow_hook__: dict[
|
|
83
|
+
__marshmallow_hook__: dict[str, list[tuple[bool, Any]]] | None = None
|
|
83
84
|
|
|
84
85
|
|
|
85
86
|
def validates(field_name: str) -> Callable[..., Any]:
|
|
@@ -117,7 +118,8 @@ def validates_schema(
|
|
|
117
118
|
"""
|
|
118
119
|
return set_hook(
|
|
119
120
|
fn,
|
|
120
|
-
|
|
121
|
+
VALIDATES_SCHEMA,
|
|
122
|
+
many=pass_many,
|
|
121
123
|
pass_original=pass_original,
|
|
122
124
|
skip_on_field_errors=skip_on_field_errors,
|
|
123
125
|
)
|
|
@@ -136,7 +138,7 @@ def pre_dump(
|
|
|
136
138
|
.. versionchanged:: 3.0.0
|
|
137
139
|
``many`` is always passed as a keyword arguments to the decorated method.
|
|
138
140
|
"""
|
|
139
|
-
return set_hook(fn,
|
|
141
|
+
return set_hook(fn, PRE_DUMP, many=pass_many)
|
|
140
142
|
|
|
141
143
|
|
|
142
144
|
def post_dump(
|
|
@@ -157,7 +159,7 @@ def post_dump(
|
|
|
157
159
|
.. versionchanged:: 3.0.0
|
|
158
160
|
``many`` is always passed as a keyword arguments to the decorated method.
|
|
159
161
|
"""
|
|
160
|
-
return set_hook(fn,
|
|
162
|
+
return set_hook(fn, POST_DUMP, many=pass_many, pass_original=pass_original)
|
|
161
163
|
|
|
162
164
|
|
|
163
165
|
def pre_load(
|
|
@@ -174,7 +176,7 @@ def pre_load(
|
|
|
174
176
|
``partial`` and ``many`` are always passed as keyword arguments to
|
|
175
177
|
the decorated method.
|
|
176
178
|
"""
|
|
177
|
-
return set_hook(fn,
|
|
179
|
+
return set_hook(fn, PRE_LOAD, many=pass_many)
|
|
178
180
|
|
|
179
181
|
|
|
180
182
|
def post_load(
|
|
@@ -196,11 +198,11 @@ def post_load(
|
|
|
196
198
|
``partial`` and ``many`` are always passed as keyword arguments to
|
|
197
199
|
the decorated method.
|
|
198
200
|
"""
|
|
199
|
-
return set_hook(fn,
|
|
201
|
+
return set_hook(fn, POST_LOAD, many=pass_many, pass_original=pass_original)
|
|
200
202
|
|
|
201
203
|
|
|
202
204
|
def set_hook(
|
|
203
|
-
fn: Callable[..., Any] | None,
|
|
205
|
+
fn: Callable[..., Any] | None, tag: str, many: bool = False, **kwargs: Any
|
|
204
206
|
) -> Callable[..., Any]:
|
|
205
207
|
"""Mark decorated function as a hook to be picked up later.
|
|
206
208
|
You should not need to use this method directly.
|
|
@@ -214,7 +216,7 @@ def set_hook(
|
|
|
214
216
|
"""
|
|
215
217
|
# Allow using this as either a decorator or a decorator factory.
|
|
216
218
|
if fn is None:
|
|
217
|
-
return functools.partial(set_hook,
|
|
219
|
+
return functools.partial(set_hook, tag=tag, many=many, **kwargs)
|
|
218
220
|
|
|
219
221
|
# Set a __marshmallow_hook__ attribute instead of wrapping in some class,
|
|
220
222
|
# because I still want this to end up as a normal (unbound) method.
|
|
@@ -222,10 +224,10 @@ def set_hook(
|
|
|
222
224
|
try:
|
|
223
225
|
hook_config = function.__marshmallow_hook__
|
|
224
226
|
except AttributeError:
|
|
225
|
-
function.__marshmallow_hook__ = hook_config =
|
|
227
|
+
function.__marshmallow_hook__ = hook_config = defaultdict(list)
|
|
226
228
|
# Also save the kwargs for the tagged function on
|
|
227
|
-
# __marshmallow_hook__, keyed by
|
|
229
|
+
# __marshmallow_hook__, keyed by <tag>
|
|
228
230
|
if hook_config is not None:
|
|
229
|
-
hook_config[
|
|
231
|
+
hook_config[tag].append((many, kwargs))
|
|
230
232
|
|
|
231
233
|
return fn
|
marshmallow/fields.py
CHANGED
|
@@ -33,6 +33,10 @@ from marshmallow.utils import (
|
|
|
33
33
|
from marshmallow.validate import And, Length
|
|
34
34
|
from marshmallow.warnings import RemovedInMarshmallow4Warning
|
|
35
35
|
|
|
36
|
+
if typing.TYPE_CHECKING:
|
|
37
|
+
from marshmallow.schema import SchemaMeta
|
|
38
|
+
|
|
39
|
+
|
|
36
40
|
__all__ = [
|
|
37
41
|
"Field",
|
|
38
42
|
"Raw",
|
|
@@ -535,10 +539,10 @@ class Nested(Field):
|
|
|
535
539
|
def __init__(
|
|
536
540
|
self,
|
|
537
541
|
nested: SchemaABC
|
|
538
|
-
|
|
|
542
|
+
| SchemaMeta
|
|
539
543
|
| str
|
|
540
|
-
| dict[str, Field | type]
|
|
541
|
-
| typing.Callable[[], SchemaABC |
|
|
544
|
+
| dict[str, Field | type[Field]]
|
|
545
|
+
| typing.Callable[[], SchemaABC | SchemaMeta | dict[str, Field | type[Field]]],
|
|
542
546
|
*,
|
|
543
547
|
dump_default: typing.Any = missing_,
|
|
544
548
|
default: typing.Any = missing_,
|
|
@@ -700,7 +704,7 @@ class Pluck(Nested):
|
|
|
700
704
|
|
|
701
705
|
def __init__(
|
|
702
706
|
self,
|
|
703
|
-
nested: SchemaABC |
|
|
707
|
+
nested: SchemaABC | SchemaMeta | str | typing.Callable[[], SchemaABC],
|
|
704
708
|
field_name: str,
|
|
705
709
|
**kwargs,
|
|
706
710
|
):
|
|
@@ -751,7 +755,7 @@ class List(Field):
|
|
|
751
755
|
#: Default error messages.
|
|
752
756
|
default_error_messages = {"invalid": "Not a valid list."}
|
|
753
757
|
|
|
754
|
-
def __init__(self, cls_or_instance: Field | type, **kwargs):
|
|
758
|
+
def __init__(self, cls_or_instance: Field | type[Field], **kwargs):
|
|
755
759
|
super().__init__(**kwargs)
|
|
756
760
|
try:
|
|
757
761
|
self.inner = resolve_field_instance(cls_or_instance)
|
|
@@ -1236,7 +1240,7 @@ class DateTime(Field):
|
|
|
1236
1240
|
"rfc822": utils.rfcformat,
|
|
1237
1241
|
"timestamp": utils.timestamp,
|
|
1238
1242
|
"timestamp_ms": utils.timestamp_ms,
|
|
1239
|
-
} # type:
|
|
1243
|
+
} # type: dict[str, typing.Callable[[typing.Any], str | float]]
|
|
1240
1244
|
|
|
1241
1245
|
DESERIALIZATION_FUNCS = {
|
|
1242
1246
|
"iso": utils.from_iso_datetime,
|
|
@@ -1245,7 +1249,7 @@ class DateTime(Field):
|
|
|
1245
1249
|
"rfc822": utils.from_rfc,
|
|
1246
1250
|
"timestamp": utils.from_timestamp,
|
|
1247
1251
|
"timestamp_ms": utils.from_timestamp_ms,
|
|
1248
|
-
} # type:
|
|
1252
|
+
} # type: dict[str, typing.Callable[[str], typing.Any]]
|
|
1249
1253
|
|
|
1250
1254
|
DEFAULT_FORMAT = "iso"
|
|
1251
1255
|
|
|
@@ -1555,8 +1559,8 @@ class Mapping(Field):
|
|
|
1555
1559
|
|
|
1556
1560
|
def __init__(
|
|
1557
1561
|
self,
|
|
1558
|
-
keys: Field | type | None = None,
|
|
1559
|
-
values: Field | type | None = None,
|
|
1562
|
+
keys: Field | type[Field] | None = None,
|
|
1563
|
+
values: Field | type[Field] | None = None,
|
|
1560
1564
|
**kwargs,
|
|
1561
1565
|
):
|
|
1562
1566
|
super().__init__(**kwargs)
|
|
@@ -1878,7 +1882,7 @@ class Enum(Field):
|
|
|
1878
1882
|
self,
|
|
1879
1883
|
enum: type[EnumType],
|
|
1880
1884
|
*,
|
|
1881
|
-
by_value: bool | Field | type = False,
|
|
1885
|
+
by_value: bool | Field | type[Field] = False,
|
|
1882
1886
|
**kwargs,
|
|
1883
1887
|
):
|
|
1884
1888
|
super().__init__(**kwargs)
|
marshmallow/schema.py
CHANGED
|
@@ -40,8 +40,6 @@ from marshmallow.utils import (
|
|
|
40
40
|
)
|
|
41
41
|
from marshmallow.warnings import RemovedInMarshmallow4Warning
|
|
42
42
|
|
|
43
|
-
_T = typing.TypeVar("_T")
|
|
44
|
-
|
|
45
43
|
|
|
46
44
|
def _get_fields(attrs):
|
|
47
45
|
"""Get fields from a class
|
|
@@ -57,7 +55,7 @@ def _get_fields(attrs):
|
|
|
57
55
|
|
|
58
56
|
# This function allows Schemas to inherit from non-Schema classes and ensures
|
|
59
57
|
# inheritance according to the MRO
|
|
60
|
-
def _get_fields_by_mro(klass):
|
|
58
|
+
def _get_fields_by_mro(klass: SchemaMeta):
|
|
61
59
|
"""Collect fields from a class, following its method resolution order. The
|
|
62
60
|
class itself is excluded from the search; only its parents are checked. Get
|
|
63
61
|
fields from ``_declared_fields`` if available, else use ``__dict__``.
|
|
@@ -125,10 +123,10 @@ class SchemaMeta(ABCMeta):
|
|
|
125
123
|
@classmethod
|
|
126
124
|
def get_declared_fields(
|
|
127
125
|
mcs,
|
|
128
|
-
klass:
|
|
126
|
+
klass: SchemaMeta,
|
|
129
127
|
cls_fields: list,
|
|
130
128
|
inherited_fields: list,
|
|
131
|
-
dict_cls: type = dict,
|
|
129
|
+
dict_cls: type[dict] = dict,
|
|
132
130
|
):
|
|
133
131
|
"""Returns a dictionary of field_name => `Field` pairs declared on the class.
|
|
134
132
|
This is exposed mainly so that plugins can add additional fields, e.g. fields
|
|
@@ -148,7 +146,7 @@ class SchemaMeta(ABCMeta):
|
|
|
148
146
|
class_registry.register(name, cls)
|
|
149
147
|
cls._hooks = cls.resolve_hooks()
|
|
150
148
|
|
|
151
|
-
def resolve_hooks(cls) -> dict[
|
|
149
|
+
def resolve_hooks(cls) -> dict[str, list[tuple[str, bool, dict]]]:
|
|
152
150
|
"""Add in the decorated processors
|
|
153
151
|
|
|
154
152
|
By doing this after constructing the class, we let standard inheritance
|
|
@@ -156,7 +154,7 @@ class SchemaMeta(ABCMeta):
|
|
|
156
154
|
"""
|
|
157
155
|
mro = inspect.getmro(cls)
|
|
158
156
|
|
|
159
|
-
hooks = defaultdict(list) # type:
|
|
157
|
+
hooks = defaultdict(list) # type: dict[str, list[tuple[str, bool, dict]]]
|
|
160
158
|
|
|
161
159
|
for attr_name in dir(cls):
|
|
162
160
|
# Need to look up the actual descriptor, not whatever might be
|
|
@@ -176,14 +174,16 @@ class SchemaMeta(ABCMeta):
|
|
|
176
174
|
continue
|
|
177
175
|
|
|
178
176
|
try:
|
|
179
|
-
hook_config = attr.__marshmallow_hook__
|
|
177
|
+
hook_config = attr.__marshmallow_hook__ # type: dict[str, list[tuple[bool, dict]]]
|
|
180
178
|
except AttributeError:
|
|
181
179
|
pass
|
|
182
180
|
else:
|
|
183
|
-
for
|
|
181
|
+
for tag, config in hook_config.items():
|
|
184
182
|
# Use name here so we can get the bound method later, in
|
|
185
183
|
# case the processor was a descriptor or something.
|
|
186
|
-
hooks[
|
|
184
|
+
hooks[tag].extend(
|
|
185
|
+
(attr_name, many, kwargs) for many, kwargs in config
|
|
186
|
+
)
|
|
187
187
|
|
|
188
188
|
return hooks
|
|
189
189
|
|
|
@@ -226,6 +226,7 @@ class SchemaOpts:
|
|
|
226
226
|
self.dump_only = getattr(meta, "dump_only", ())
|
|
227
227
|
self.unknown = validate_unknown_parameter_value(getattr(meta, "unknown", RAISE))
|
|
228
228
|
self.register = getattr(meta, "register", True)
|
|
229
|
+
self.many = getattr(meta, "many", False)
|
|
229
230
|
|
|
230
231
|
|
|
231
232
|
class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
@@ -303,14 +304,14 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
303
304
|
dt.date: ma_fields.Date,
|
|
304
305
|
dt.timedelta: ma_fields.TimeDelta,
|
|
305
306
|
decimal.Decimal: ma_fields.Decimal,
|
|
306
|
-
} # type:
|
|
307
|
+
} # type: dict[type, typing.Type[ma_fields.Field]]
|
|
307
308
|
#: Overrides for default schema-level error messages
|
|
308
|
-
error_messages = {} # type:
|
|
309
|
+
error_messages = {} # type: dict[str, str]
|
|
309
310
|
|
|
310
311
|
_default_error_messages = {
|
|
311
312
|
"type": "Invalid input type.",
|
|
312
313
|
"unknown": "Unknown field.",
|
|
313
|
-
} # type:
|
|
314
|
+
} # type: dict[str, str]
|
|
314
315
|
|
|
315
316
|
OPTIONS_CLASS = SchemaOpts # type: type
|
|
316
317
|
|
|
@@ -318,8 +319,8 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
318
319
|
|
|
319
320
|
# These get set by SchemaMeta
|
|
320
321
|
opts = None # type: SchemaOpts
|
|
321
|
-
_declared_fields = {} # type:
|
|
322
|
-
_hooks = {} # type:
|
|
322
|
+
_declared_fields = {} # type: dict[str, ma_fields.Field]
|
|
323
|
+
_hooks = {} # type: dict[str, list[tuple[str, bool, dict]]]
|
|
323
324
|
|
|
324
325
|
class Meta:
|
|
325
326
|
"""Options object for a Schema.
|
|
@@ -342,6 +343,7 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
342
343
|
`OrderedDict`.
|
|
343
344
|
- ``exclude``: Tuple or list of fields to exclude in the serialized result.
|
|
344
345
|
Nested fields can be represented with dot delimiters.
|
|
346
|
+
- ``many``: Whether the data is a collection by default.
|
|
345
347
|
- ``dateformat``: Default format for `Date <fields.Date>` fields.
|
|
346
348
|
- ``datetimeformat``: Default format for `DateTime <fields.DateTime>` fields.
|
|
347
349
|
- ``timeformat``: Default format for `Time <fields.Time>` fields.
|
|
@@ -365,7 +367,7 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
365
367
|
*,
|
|
366
368
|
only: types.StrSequenceOrSet | None = None,
|
|
367
369
|
exclude: types.StrSequenceOrSet = (),
|
|
368
|
-
many: bool =
|
|
370
|
+
many: bool | None = None,
|
|
369
371
|
context: dict | None = None,
|
|
370
372
|
load_only: types.StrSequenceOrSet = (),
|
|
371
373
|
dump_only: types.StrSequenceOrSet = (),
|
|
@@ -379,7 +381,7 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
379
381
|
raise StringNotCollectionError('"exclude" should be a list of strings')
|
|
380
382
|
# copy declared fields from metaclass
|
|
381
383
|
self.declared_fields = copy.deepcopy(self._declared_fields)
|
|
382
|
-
self.many = many
|
|
384
|
+
self.many = self.opts.many if many is None else many
|
|
383
385
|
self.only = only
|
|
384
386
|
self.exclude: set[typing.Any] | typing.MutableSet[typing.Any] = set(
|
|
385
387
|
self.opts.exclude
|
|
@@ -396,9 +398,9 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
396
398
|
self.context = context or {}
|
|
397
399
|
self._normalize_nested_options()
|
|
398
400
|
#: Dictionary mapping field_names -> :class:`Field` objects
|
|
399
|
-
self.fields = {} # type:
|
|
400
|
-
self.load_fields = {} # type:
|
|
401
|
-
self.dump_fields = {} # type:
|
|
401
|
+
self.fields = {} # type: dict[str, ma_fields.Field]
|
|
402
|
+
self.load_fields = {} # type: dict[str, ma_fields.Field]
|
|
403
|
+
self.dump_fields = {} # type: dict[str, ma_fields.Field]
|
|
402
404
|
self._init_fields()
|
|
403
405
|
messages = {}
|
|
404
406
|
messages.update(self._default_error_messages)
|
|
@@ -411,16 +413,19 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
411
413
|
return f"<{self.__class__.__name__}(many={self.many})>"
|
|
412
414
|
|
|
413
415
|
@property
|
|
414
|
-
def dict_class(self) -> type:
|
|
415
|
-
|
|
416
|
+
def dict_class(self) -> type[dict]:
|
|
417
|
+
if self.ordered:
|
|
418
|
+
return OrderedDict
|
|
419
|
+
else:
|
|
420
|
+
return dict
|
|
416
421
|
|
|
417
422
|
@classmethod
|
|
418
423
|
def from_dict(
|
|
419
424
|
cls,
|
|
420
|
-
fields: dict[str, ma_fields.Field | type],
|
|
425
|
+
fields: dict[str, ma_fields.Field | type[ma_fields.Field]],
|
|
421
426
|
*,
|
|
422
427
|
name: str = "GeneratedSchema",
|
|
423
|
-
) -> type:
|
|
428
|
+
) -> type[Schema]:
|
|
424
429
|
"""Generate a `Schema` class given a dictionary of fields.
|
|
425
430
|
|
|
426
431
|
.. code-block:: python
|
|
@@ -497,7 +502,7 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
497
502
|
return error.valid_data or missing
|
|
498
503
|
return value
|
|
499
504
|
|
|
500
|
-
def _serialize(self, obj:
|
|
505
|
+
def _serialize(self, obj: typing.Any, *, many: bool = False):
|
|
501
506
|
"""Serialize ``obj``.
|
|
502
507
|
|
|
503
508
|
:param obj: The object(s) to serialize.
|
|
@@ -508,10 +513,7 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
508
513
|
Renamed from ``marshal``.
|
|
509
514
|
"""
|
|
510
515
|
if many and obj is not None:
|
|
511
|
-
return [
|
|
512
|
-
self._serialize(d, many=False)
|
|
513
|
-
for d in typing.cast(typing.Iterable[_T], obj)
|
|
514
|
-
]
|
|
516
|
+
return [self._serialize(d, many=False) for d in obj]
|
|
515
517
|
ret = self.dict_class()
|
|
516
518
|
for attr_name, field_obj in self.dump_fields.items():
|
|
517
519
|
value = field_obj.serialize(attr_name, obj, accessor=self.get_attribute)
|
|
@@ -539,7 +541,7 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
539
541
|
Validation no longer occurs upon serialization.
|
|
540
542
|
"""
|
|
541
543
|
many = self.many if many is None else bool(many)
|
|
542
|
-
if self.
|
|
544
|
+
if self._hooks[PRE_DUMP]:
|
|
543
545
|
processed_obj = self._invoke_dump_processors(
|
|
544
546
|
PRE_DUMP, obj, many=many, original_data=obj
|
|
545
547
|
)
|
|
@@ -548,7 +550,7 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
548
550
|
|
|
549
551
|
result = self._serialize(processed_obj, many=many)
|
|
550
552
|
|
|
551
|
-
if self.
|
|
553
|
+
if self._hooks[POST_DUMP]:
|
|
552
554
|
result = self._invoke_dump_processors(
|
|
553
555
|
POST_DUMP, result, many=many, original_data=obj
|
|
554
556
|
)
|
|
@@ -584,7 +586,7 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
584
586
|
partial=None,
|
|
585
587
|
unknown=RAISE,
|
|
586
588
|
index=None,
|
|
587
|
-
) ->
|
|
589
|
+
) -> typing.Any | list[typing.Any]:
|
|
588
590
|
"""Deserialize ``data``.
|
|
589
591
|
|
|
590
592
|
:param dict data: The data to deserialize.
|
|
@@ -598,26 +600,24 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
598
600
|
fields in the data. Use `EXCLUDE`, `INCLUDE` or `RAISE`.
|
|
599
601
|
:param int index: Index of the item being serialized (for storing errors) if
|
|
600
602
|
serializing a collection, otherwise `None`.
|
|
601
|
-
:return:
|
|
603
|
+
:return: The deserialized data as `dict_class` instance or list of `dict_class`
|
|
604
|
+
instances if `many` is `True`.
|
|
602
605
|
"""
|
|
603
606
|
index_errors = self.opts.index_errors
|
|
604
607
|
index = index if index_errors else None
|
|
605
608
|
if many:
|
|
606
609
|
if not is_collection(data):
|
|
607
610
|
error_store.store_error([self.error_messages["type"]], index=index)
|
|
608
|
-
ret_l = []
|
|
611
|
+
ret_l = []
|
|
609
612
|
else:
|
|
610
613
|
ret_l = [
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
unknown=unknown,
|
|
619
|
-
index=idx,
|
|
620
|
-
),
|
|
614
|
+
self._deserialize(
|
|
615
|
+
typing.cast(dict, d),
|
|
616
|
+
error_store=error_store,
|
|
617
|
+
many=False,
|
|
618
|
+
partial=partial,
|
|
619
|
+
unknown=unknown,
|
|
620
|
+
index=idx,
|
|
621
621
|
)
|
|
622
622
|
for idx, d in enumerate(data)
|
|
623
623
|
]
|
|
@@ -802,7 +802,7 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
802
802
|
try:
|
|
803
803
|
self._do_load(data, many=many, partial=partial, postprocess=False)
|
|
804
804
|
except ValidationError as exc:
|
|
805
|
-
return typing.cast(
|
|
805
|
+
return typing.cast(dict[str, list[str]], exc.messages)
|
|
806
806
|
return {}
|
|
807
807
|
|
|
808
808
|
##### Private Helpers #####
|
|
@@ -846,7 +846,7 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
846
846
|
if partial is None:
|
|
847
847
|
partial = self.partial
|
|
848
848
|
# Run preprocessors
|
|
849
|
-
if self.
|
|
849
|
+
if self._hooks[PRE_LOAD]:
|
|
850
850
|
try:
|
|
851
851
|
processed_data = self._invoke_load_processors(
|
|
852
852
|
PRE_LOAD, data, many=many, original_data=data, partial=partial
|
|
@@ -870,7 +870,7 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
870
870
|
error_store=error_store, data=result, many=many
|
|
871
871
|
)
|
|
872
872
|
# Run schema-level validation
|
|
873
|
-
if self.
|
|
873
|
+
if self._hooks[VALIDATES_SCHEMA]:
|
|
874
874
|
field_errors = bool(error_store.errors)
|
|
875
875
|
self._invoke_schema_validators(
|
|
876
876
|
error_store=error_store,
|
|
@@ -892,7 +892,7 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
892
892
|
)
|
|
893
893
|
errors = error_store.errors
|
|
894
894
|
# Run post processors
|
|
895
|
-
if not errors and postprocess and self.
|
|
895
|
+
if not errors and postprocess and self._hooks[POST_LOAD]:
|
|
896
896
|
try:
|
|
897
897
|
result = self._invoke_load_processors(
|
|
898
898
|
POST_LOAD,
|
|
@@ -1055,9 +1055,6 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
1055
1055
|
raise error
|
|
1056
1056
|
self.on_bind_field(field_name, field_obj)
|
|
1057
1057
|
|
|
1058
|
-
def _has_processors(self, tag) -> bool:
|
|
1059
|
-
return bool(self._hooks[(tag, True)] or self._hooks[(tag, False)])
|
|
1060
|
-
|
|
1061
1058
|
def _invoke_dump_processors(
|
|
1062
1059
|
self, tag: str, data, *, many: bool, original_data=None
|
|
1063
1060
|
):
|
|
@@ -1102,9 +1099,8 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
1102
1099
|
return data
|
|
1103
1100
|
|
|
1104
1101
|
def _invoke_field_validators(self, *, error_store: ErrorStore, data, many: bool):
|
|
1105
|
-
for attr_name in self._hooks[VALIDATES]:
|
|
1102
|
+
for attr_name, _, validator_kwargs in self._hooks[VALIDATES]:
|
|
1106
1103
|
validator = getattr(self, attr_name)
|
|
1107
|
-
validator_kwargs = validator.__marshmallow_hook__[VALIDATES]
|
|
1108
1104
|
field_name = validator_kwargs["field_name"]
|
|
1109
1105
|
|
|
1110
1106
|
try:
|
|
@@ -1159,11 +1155,10 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
1159
1155
|
partial: bool | types.StrSequenceOrSet | None,
|
|
1160
1156
|
field_errors: bool = False,
|
|
1161
1157
|
):
|
|
1162
|
-
for attr_name in self._hooks[
|
|
1158
|
+
for attr_name, hook_many, validator_kwargs in self._hooks[VALIDATES_SCHEMA]:
|
|
1159
|
+
if hook_many != pass_many:
|
|
1160
|
+
continue
|
|
1163
1161
|
validator = getattr(self, attr_name)
|
|
1164
|
-
validator_kwargs = validator.__marshmallow_hook__[
|
|
1165
|
-
(VALIDATES_SCHEMA, pass_many)
|
|
1166
|
-
]
|
|
1167
1162
|
if field_errors and validator_kwargs["skip_on_field_errors"]:
|
|
1168
1163
|
continue
|
|
1169
1164
|
pass_original = validator_kwargs.get("pass_original", False)
|
|
@@ -1201,12 +1196,11 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
|
|
|
1201
1196
|
original_data=None,
|
|
1202
1197
|
**kwargs,
|
|
1203
1198
|
):
|
|
1204
|
-
|
|
1205
|
-
|
|
1199
|
+
for attr_name, hook_many, processor_kwargs in self._hooks[tag]:
|
|
1200
|
+
if hook_many != pass_many:
|
|
1201
|
+
continue
|
|
1206
1202
|
# This will be a bound method.
|
|
1207
1203
|
processor = getattr(self, attr_name)
|
|
1208
|
-
|
|
1209
|
-
processor_kwargs = processor.__marshmallow_hook__[key]
|
|
1210
1204
|
pass_original = processor_kwargs.get("pass_original", False)
|
|
1211
1205
|
|
|
1212
1206
|
if many and not pass_many:
|
marshmallow/types.py
CHANGED
|
@@ -1,31 +1,30 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: marshmallow
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.23.0
|
|
4
4
|
Summary: A lightweight library for converting complex datatypes to and from native Python datatypes.
|
|
5
5
|
Author-email: Steven Loria <sloria1@gmail.com>
|
|
6
6
|
Maintainer-email: Steven Loria <sloria1@gmail.com>, Jérôme Lafréchoux <jerome@jolimont.fr>, Jared Deckard <jared@shademaps.com>
|
|
7
|
-
Requires-Python: >=3.
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
8
|
Description-Content-Type: text/x-rst
|
|
9
9
|
Classifier: Development Status :: 5 - Production/Stable
|
|
10
10
|
Classifier: Intended Audience :: Developers
|
|
11
11
|
Classifier: License :: OSI Approved :: MIT License
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.9
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
18
|
Requires-Dist: packaging>=17.0
|
|
19
19
|
Requires-Dist: marshmallow[tests] ; extra == "dev"
|
|
20
20
|
Requires-Dist: tox ; extra == "dev"
|
|
21
|
-
Requires-Dist: pre-commit
|
|
22
|
-
Requires-Dist: sphinx==
|
|
23
|
-
Requires-Dist: sphinx-issues==
|
|
24
|
-
Requires-Dist: alabaster==0.
|
|
21
|
+
Requires-Dist: pre-commit>=3.5,<5.0 ; extra == "dev"
|
|
22
|
+
Requires-Dist: sphinx==8.1.3 ; extra == "docs"
|
|
23
|
+
Requires-Dist: sphinx-issues==5.0.0 ; extra == "docs"
|
|
24
|
+
Requires-Dist: alabaster==1.0.0 ; extra == "docs"
|
|
25
25
|
Requires-Dist: sphinx-version-warning==1.1.2 ; extra == "docs"
|
|
26
|
-
Requires-Dist: autodocsumm==0.2.
|
|
26
|
+
Requires-Dist: autodocsumm==0.2.13 ; extra == "docs"
|
|
27
27
|
Requires-Dist: pytest ; extra == "tests"
|
|
28
|
-
Requires-Dist: pytz ; extra == "tests"
|
|
29
28
|
Requires-Dist: simplejson ; extra == "tests"
|
|
30
29
|
Project-URL: Changelog, https://marshmallow.readthedocs.io/en/latest/changelog.html
|
|
31
30
|
Project-URL: Funding, https://opencollective.com/marshmallow
|
|
@@ -40,24 +39,39 @@ Provides-Extra: tests
|
|
|
40
39
|
marshmallow: simplified object serialization
|
|
41
40
|
********************************************
|
|
42
41
|
|
|
43
|
-
|
|
42
|
+
|pypi| |build-status| |pre-commit| |docs|
|
|
43
|
+
|
|
44
|
+
.. |pypi| image:: https://badgen.net/pypi/v/marshmallow
|
|
44
45
|
:target: https://pypi.org/project/marshmallow/
|
|
45
46
|
:alt: Latest version
|
|
46
47
|
|
|
47
|
-
.. image:: https://github.com/marshmallow-code/marshmallow/actions/workflows/build-release.yml/badge.svg
|
|
48
|
+
.. |build-status| image:: https://github.com/marshmallow-code/marshmallow/actions/workflows/build-release.yml/badge.svg
|
|
48
49
|
:target: https://github.com/marshmallow-code/marshmallow/actions/workflows/build-release.yml
|
|
49
50
|
:alt: Build status
|
|
50
51
|
|
|
51
|
-
.. image:: https://results.pre-commit.ci/badge/github/marshmallow-code/marshmallow/dev.svg
|
|
52
|
+
.. |pre-commit| image:: https://results.pre-commit.ci/badge/github/marshmallow-code/marshmallow/dev.svg
|
|
52
53
|
:target: https://results.pre-commit.ci/latest/github/marshmallow-code/marshmallow/dev
|
|
53
54
|
:alt: pre-commit.ci status
|
|
54
55
|
|
|
55
|
-
.. image:: https://readthedocs.org/projects/marshmallow/badge/
|
|
56
|
+
.. |docs| image:: https://readthedocs.org/projects/marshmallow/badge/
|
|
56
57
|
:target: https://marshmallow.readthedocs.io/
|
|
57
58
|
:alt: Documentation
|
|
58
59
|
|
|
59
60
|
**marshmallow** is an ORM/ODM/framework-agnostic library for converting complex datatypes, such as objects, to and from native Python datatypes.
|
|
60
61
|
|
|
62
|
+
Sponsor Message
|
|
63
|
+
===============
|
|
64
|
+
|
|
65
|
+
Input an OpenAPI spec to generate API docs that look as good as Stripe's. `Request a preview <https://form.typeform.com/to/bShdJw7z>`_ of your docs on Fern.
|
|
66
|
+
|
|
67
|
+
.. image:: https://github.com/user-attachments/assets/69916225-0d61-4bd7-b3b9-e378557673cb
|
|
68
|
+
:target: https://form.typeform.com/to/bShdJw7z
|
|
69
|
+
:align: center
|
|
70
|
+
:alt: Fern logo
|
|
71
|
+
|
|
72
|
+
Example
|
|
73
|
+
=======
|
|
74
|
+
|
|
61
75
|
.. code-block:: python
|
|
62
76
|
|
|
63
77
|
from datetime import date
|
|
@@ -109,7 +123,7 @@ Full documentation is available at https://marshmallow.readthedocs.io/ .
|
|
|
109
123
|
Requirements
|
|
110
124
|
============
|
|
111
125
|
|
|
112
|
-
- Python >= 3.
|
|
126
|
+
- Python >= 3.9
|
|
113
127
|
|
|
114
128
|
Ecosystem
|
|
115
129
|
=========
|
|
@@ -152,15 +166,16 @@ Thank you to all our backers! [`Become a backer`_]
|
|
|
152
166
|
Sponsors
|
|
153
167
|
--------
|
|
154
168
|
|
|
155
|
-
|
|
156
|
-
Your logo will show up here with a link to your website. [`Become a sponsor`_]
|
|
169
|
+
marshmallow is sponsored by `Route4Me <https://route4me.com>`_.
|
|
157
170
|
|
|
158
|
-
..
|
|
171
|
+
.. image:: https://github.com/user-attachments/assets/018c2e23-032e-4a11-98da-8b6dc25b9054
|
|
172
|
+
:target: https://route4me.com
|
|
173
|
+
:alt: Routing Planner
|
|
159
174
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
:alt: Become a sponsor
|
|
175
|
+
Support this project by becoming a sponsor (or ask your company to support this project by becoming a sponsor).
|
|
176
|
+
Your logo will be displayed here with a link to your website. [`Become a sponsor`_]
|
|
163
177
|
|
|
178
|
+
.. _`Become a sponsor`: https://opencollective.com/marshmallow#sponsor
|
|
164
179
|
|
|
165
180
|
Professional Support
|
|
166
181
|
====================
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
marshmallow/__init__.py,sha256=C-zbaQJ9dlJLJxotIqTa5OOaD6ojGNRqW8moGrMsGr8,2387
|
|
2
2
|
marshmallow/base.py,sha256=jZ68DZxxSCvRg2GTcxQcf2JjTxqEn-xFNrBEMK3CinU,1346
|
|
3
|
-
marshmallow/class_registry.py,sha256=
|
|
4
|
-
marshmallow/decorators.py,sha256=
|
|
3
|
+
marshmallow/class_registry.py,sha256=kT_kv9KT0EUclIluLD5734ms9P0e65t5aky8y3lipFI,2804
|
|
4
|
+
marshmallow/decorators.py,sha256=vmQFgBgdV0s1Fw8ySyZyQKvjKBTNf5JB3SCldEIl29o,8385
|
|
5
5
|
marshmallow/error_store.py,sha256=A7AxgLMw9ffSmaxRH4x3wcBWibx-DuGH4LwSDpVn50I,2223
|
|
6
6
|
marshmallow/exceptions.py,sha256=DuARdOcirCdJxmlp16V97hQKAXOokvdW12jXtYOlGyk,2326
|
|
7
|
-
marshmallow/fields.py,sha256=
|
|
7
|
+
marshmallow/fields.py,sha256=6Cit4Z6AE_HDQBvspibHR8UgtwBkp_oNRaCIqjPR64s,73114
|
|
8
8
|
marshmallow/orderedset.py,sha256=C2aAG6w1faIL1phinbAltbe3AUAnF5MN6n7fzESNDhI,2922
|
|
9
9
|
marshmallow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
marshmallow/schema.py,sha256=
|
|
11
|
-
marshmallow/types.py,sha256=
|
|
10
|
+
marshmallow/schema.py,sha256=C4BsYkDBQbdgDA6w39oSqVlsDx4NfbkT_XtSIKcqxIo,48812
|
|
11
|
+
marshmallow/types.py,sha256=RDS4IfasIehvH2rGWh9e4RTBtsMp-JFFtjApajV22zc,283
|
|
12
12
|
marshmallow/utils.py,sha256=sWciesZ6tS08uX9Z9fzu2lbuut5eh8TKABU-TwgqSms,11886
|
|
13
13
|
marshmallow/validate.py,sha256=hS7fYC6byDHK9A7A4is0McDMZEzu6GkKke-7unLt2hE,23857
|
|
14
14
|
marshmallow/warnings.py,sha256=vHQu7AluuWqLhvlw5noXtWWbya13zDXY6JMaVSUzmDs,65
|
|
15
|
-
marshmallow-3.
|
|
16
|
-
marshmallow-3.
|
|
17
|
-
marshmallow-3.
|
|
18
|
-
marshmallow-3.
|
|
15
|
+
marshmallow-3.23.0.dist-info/LICENSE,sha256=kGtdkFHkJhRMsXOtkRZnuOvQWpxYTCwmwTWzKj7RIAE,1064
|
|
16
|
+
marshmallow-3.23.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
|
17
|
+
marshmallow-3.23.0.dist-info/METADATA,sha256=kKdIlUdvaVt3ZOQbuGFgfX65m2Yv8FrmPt3766XiBmU,7582
|
|
18
|
+
marshmallow-3.23.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|