75
75
"Pluck" ,
76
76
]
77
77
78
- _T = typing .TypeVar ("_T" )
79
-
80
78
81
79
class Field (FieldABC ):
82
80
"""Basic field from which other fields should extend. It applies no
@@ -132,7 +130,7 @@ class Field(FieldABC):
132
130
#: Default error messages for various kinds of errors. The keys in this dictionary
133
131
#: are passed to `Field.make_error`. The values are error messages passed to
134
132
#: :exc:`marshmallow.exceptions.ValidationError`.
135
- default_error_messages = {
133
+ default_error_messages : dict [ str , str ] = {
136
134
"required" : "Missing data for required field." ,
137
135
"null" : "Field may not be null." ,
138
136
"validator_failed" : "Invalid value." ,
@@ -224,6 +222,10 @@ def __init__(
224
222
messages .update (error_messages or {})
225
223
self .error_messages = messages
226
224
225
+ self .parent : Field | Schema | None = None
226
+ self .name : str | None = None
227
+ self .root : Schema | None = None
228
+
227
229
def __repr__ (self ) -> str :
228
230
return (
229
231
f"<fields.{ self .__class__ .__name__ } (dump_default={ self .dump_default !r} , "
@@ -237,7 +239,15 @@ def __repr__(self) -> str:
237
239
def __deepcopy__ (self , memo ):
238
240
return copy .copy (self )
239
241
240
- def get_value (self , obj , attr , accessor = None, default = missing_ ):
242
+ def get_value (
243
+ self ,
244
+ obj : typing .Any ,
245
+ attr : str ,
246
+ accessor : (
247
+ typing .Callable [[typing .Any , str , typing .Any ], typing .Any ] | None
248
+ ) = None ,
249
+ default : typing .Any = missing_ ,
250
+ ):
241
251
"""Return the value for a given key from an object.
242
252
243
253
:param object obj: The object to get the value from.
@@ -249,14 +259,14 @@ def get_value(self, obj, attr, accessor=None, default=missing_):
249
259
check_key = attr if self .attribute is None else self .attribute
250
260
return accessor_func (obj , check_key , default )
251
261
252
- def _validate (self , value ):
262
+ def _validate (self , value : typing . Any ):
253
263
"""Perform validation on ``value``. Raise a :exc:`ValidationError` if validation
254
264
does not succeed.
255
265
"""
256
266
self ._validate_all (value )
257
267
258
268
@property
259
- def _validate_all (self ):
269
+ def _validate_all (self ) -> typing . Callable [[ typing . Any ], None ] :
260
270
return And (* self .validators , error = self .error_messages ["validator_failed" ])
261
271
262
272
def make_error (self , key : str , ** kwargs ) -> ValidationError :
@@ -290,7 +300,7 @@ def fail(self, key: str, **kwargs):
290
300
)
291
301
raise self .make_error (key = key , ** kwargs )
292
302
293
- def _validate_missing (self , value ) :
303
+ def _validate_missing (self , value : typing . Any ) -> None :
294
304
"""Validate missing values. Raise a :exc:`ValidationError` if
295
305
`value` should be considered missing.
296
306
"""
@@ -357,7 +367,7 @@ def deserialize(
357
367
358
368
# Methods for concrete classes to override.
359
369
360
- def _bind_to_schema (self , field_name , schema ) :
370
+ def _bind_to_schema (self , field_name : str , schema : Schema ) -> None :
361
371
"""Update field with values from its parent schema. Called by
362
372
:meth:`Schema._bind_field <marshmallow.Schema._bind_field>`.
363
373
@@ -372,7 +382,7 @@ def _bind_to_schema(self, field_name, schema):
372
382
373
383
def _serialize (
374
384
self , value : typing .Any , attr : str | None , obj : typing .Any , ** kwargs
375
- ):
385
+ ) -> typing . Any :
376
386
"""Serializes ``value`` to a basic Python datatype. Noop by default.
377
387
Concrete :class:`Field` classes should implement this method.
378
388
@@ -398,7 +408,7 @@ def _deserialize(
398
408
attr : str | None ,
399
409
data : typing .Mapping [str , typing .Any ] | None ,
400
410
** kwargs ,
401
- ):
411
+ ) -> typing . Any :
402
412
"""Deserialize value. Concrete :class:`Field` classes should implement this method.
403
413
404
414
:param value: The value to be deserialized.
@@ -416,9 +426,11 @@ def _deserialize(
416
426
# Properties
417
427
418
428
@property
419
- def context (self ):
429
+ def context (self ) -> dict | None :
420
430
"""The context dictionary for the parent :class:`Schema`."""
421
- return self .parent .context
431
+ if self .parent :
432
+ return self .parent .context
433
+ return None
422
434
423
435
# the default and missing properties are provided for compatibility and
424
436
# emit warnings when they are accessed and set
@@ -630,12 +642,14 @@ def _serialize(self, nested_obj, attr, obj, **kwargs):
630
642
many = schema .many or self .many
631
643
return schema .dump (nested_obj , many = many )
632
644
633
- def _test_collection (self , value ) :
645
+ def _test_collection (self , value : typing . Any ) -> None :
634
646
many = self .schema .many or self .many
635
647
if many and not utils .is_collection (value ):
636
648
raise self .make_error ("type" , input = value , type = value .__class__ .__name__ )
637
649
638
- def _load (self , value , data , partial = None ):
650
+ def _load (
651
+ self , value : typing .Any , partial : bool | types .StrSequenceOrSet | None = None
652
+ ):
639
653
try :
640
654
valid_data = self .schema .load (value , unknown = self .unknown , partial = partial )
641
655
except ValidationError as error :
@@ -644,7 +658,14 @@ def _load(self, value, data, partial=None):
644
658
) from error
645
659
return valid_data
646
660
647
- def _deserialize (self , value , attr , data , partial = None , ** kwargs ):
661
+ def _deserialize (
662
+ self ,
663
+ value : typing .Any ,
664
+ attr : str | None ,
665
+ data : typing .Mapping [str , typing .Any ] | None = None ,
666
+ partial : bool | types .StrSequenceOrSet | None = None ,
667
+ ** kwargs ,
668
+ ) -> typing .Any :
648
669
"""Same as :meth:`Field._deserialize` with additional ``partial`` argument.
649
670
650
671
:param bool|tuple partial: For nested schemas, the ``partial``
@@ -654,7 +675,7 @@ def _deserialize(self, value, attr, data, partial=None, **kwargs):
654
675
Add ``partial`` parameter.
655
676
"""
656
677
self ._test_collection (value )
657
- return self ._load (value , data , partial = partial )
678
+ return self ._load (value , partial = partial )
658
679
659
680
660
681
class Pluck (Nested ):
@@ -694,7 +715,7 @@ def __init__(
694
715
self .field_name = field_name
695
716
696
717
@property
697
- def _field_data_key (self ):
718
+ def _field_data_key (self ) -> str :
698
719
only_field = self .schema .fields [self .field_name ]
699
720
return only_field .data_key or self .field_name
700
721
@@ -712,7 +733,7 @@ def _deserialize(self, value, attr, data, partial=None, **kwargs):
712
733
value = [{self ._field_data_key : v } for v in value ]
713
734
else :
714
735
value = {self ._field_data_key : value }
715
- return self ._load (value , data , partial = partial )
736
+ return self ._load (value , partial = partial )
716
737
717
738
718
739
class List (Field ):
@@ -746,7 +767,7 @@ def __init__(self, cls_or_instance: Field | type[Field], **kwargs):
746
767
self .only = self .inner .only
747
768
self .exclude = self .inner .exclude
748
769
749
- def _bind_to_schema (self , field_name , schema ) :
770
+ def _bind_to_schema (self , field_name : str , schema : Schema ) -> None :
750
771
super ()._bind_to_schema (field_name , schema )
751
772
self .inner = copy .deepcopy (self .inner )
752
773
self .inner ._bind_to_schema (field_name , self )
@@ -790,7 +811,7 @@ class Tuple(Field):
790
811
`typing.NamedTuple`, using a Schema within a Nested field for them is
791
812
more appropriate than using a `Tuple` field.
792
813
793
- :param Iterable[Field] tuple_fields: An iterable of field classes or
814
+ :param tuple_fields: An iterable of field classes or
794
815
instances.
795
816
:param kwargs: The same keyword arguments that :class:`Field` receives.
796
817
@@ -800,7 +821,7 @@ class Tuple(Field):
800
821
#: Default error messages.
801
822
default_error_messages = {"invalid" : "Not a valid tuple." }
802
823
803
- def __init__ (self , tuple_fields , * args , ** kwargs ):
824
+ def __init__ (self , tuple_fields : typing . Iterable [ Field ] , * args , ** kwargs ):
804
825
super ().__init__ (* args , ** kwargs )
805
826
if not utils .is_collection (tuple_fields ):
806
827
raise ValueError (
@@ -820,7 +841,7 @@ def __init__(self, tuple_fields, *args, **kwargs):
820
841
821
842
self .validate_length = Length (equal = len (self .tuple_fields ))
822
843
823
- def _bind_to_schema (self , field_name , schema ) :
844
+ def _bind_to_schema (self , field_name : str , schema : Schema ) -> None :
824
845
super ()._bind_to_schema (field_name , schema )
825
846
new_tuple_fields = []
826
847
for field in self .tuple_fields :
@@ -910,7 +931,10 @@ def _deserialize(self, value, attr, data, **kwargs) -> uuid.UUID | None:
910
931
return self ._validated (value )
911
932
912
933
913
- class Number (Field ):
934
+ _NumType = typing .TypeVar ("_NumType" )
935
+
936
+
937
+ class Number (Field , typing .Generic [_NumType ]):
914
938
"""Base class for number fields.
915
939
916
940
:param bool as_string: If `True`, format the serialized value as a string.
@@ -929,14 +953,12 @@ def __init__(self, *, as_string: bool = False, **kwargs):
929
953
self .as_string = as_string
930
954
super ().__init__ (** kwargs )
931
955
932
- def _format_num (self , value ) -> typing . Any :
956
+ def _format_num (self , value ) -> _NumType :
933
957
"""Return the number value for value, given this field's `num_type`."""
934
958
return self .num_type (value )
935
959
936
- def _validated (self , value ) -> _T | None :
960
+ def _validated (self , value : typing . Any ) -> _NumType :
937
961
"""Format the value or raise a :exc:`ValidationError` if an error occurs."""
938
- if value is None :
939
- return None
940
962
# (value is True or value is False) is ~5x faster than isinstance(value, bool)
941
963
if value is True
10000
or value is False :
942
964
raise self .make_error ("invalid" , input = value )
@@ -947,21 +969,21 @@ def _validated(self, value) -> _T | None:
947
969
except OverflowError as error :
948
970
raise self .make_error ("too_large" , input = value ) from error
949
971
950
- def _to_string (self , value ) -> str :
972
+ def _to_string (self , value : _NumType ) -> str :
951
973
return str (value )
952
974
953
- def _serialize (self , value , attr , obj , ** kwargs ) -> str | _T | None :
975
+ def _serialize (self , value , attr , obj , ** kwargs ) -> str | _NumType | None :
954
976
"""Return a string if `self.as_string=True`, otherwise return this field's `num_type`."""
955
977
if value is None :
956
978
return None
957
- ret : _T = self ._format_num (value )
979
+ ret : _NumType = self ._format_num (value )
958
980
return self ._to_string (ret ) if self .as_string else ret
959
981
960
- def _deserialize (self , value , attr , data , ** kwargs ) -> _T | None :
982
+ def _deserialize (self , value , attr , data , ** kwargs ) -> _NumType | None :
961
983
return self ._validated (value )
962
984
963
985
964
- class Integer (Number ):
986
+ class Integer (Number [ int ] ):
965
987
"""An integer field.
966
988
967
989
:param strict: If `True`, only integer types are valid.
@@ -979,13 +1001,13 @@ def __init__(self, *, strict: bool = False, **kwargs):
979
1001
super ().__init__ (** kwargs )
980
1002
981
1003
# override Number
982
- def _validated (self , value ) :
1004
+ def _validated (self , value : typing . Any ) -> int :
983
1005
if self .strict and not isinstance (value , numbers .Integral ):
984
1006
raise self .make_error ("invalid" , input = value )
985
1007
return super ()._validated (value )
986
1008
987
1009
988
- class Float (Number ):
1010
+ class Float (Number [ float ] ):
989
1011
"""A double as an IEEE-754 double precision string.
990
1012
991
1013
:param bool allow_nan: If `True`, `NaN`, `Infinity` and `-Infinity` are allowed,
@@ -1005,15 +1027,15 @@ def __init__(self, *, allow_nan: bool = False, as_string: bool = False, **kwargs
1005
1027
self .allow_nan = allow_nan
1006
1028
super ().__init__ (as_string = as_string , ** kwargs )
1007
1029
1008
- def _validated (self , value ) :
1030
+ def _validated (self , value : typing . Any ) -> float :
1009
1031
num = super ()._validated (value )
1010
1032
if self .allow_nan is False :
1011
1033
if math .isnan (num ) or num == float ("inf" ) or num == float ("-inf" ):
1012
1034
raise self .make_error ("special" )
1013
1035
return num
1014
1036
1015
1037
1016
- class Decimal (Number ):
1038
+ class Decimal (Number [ decimal . Decimal ] ):
1017
1039
"""A field that (de)serializes to the Python ``decimal.Decimal`` type.
1018
1040
It's safe to use when dealing with money values, percentages, ratios
1019
1041
or other numbers where precision is critical.
@@ -1084,7 +1106,7 @@ def _format_num(self, value):
1084
1106
return num
1085
1107
1086
1108
# override Number
1087
- def _validated (self , value ) :
1109
+ def _validated (self , value : typing . Any ) -> decimal . Decimal :
1088
1110
try :
1089
1111
num = super ()._validated (value )
1090
1112
except decimal .InvalidOperation as error :
@@ -1094,7 +1116,7 @@ def _validated(self, value):
1094
1116
return num
1095
1117
1096
1118
# override Number
1097
- def _to_string (self , value ) :
1119
+ def _to_string (self , value : decimal . Decimal ) -> str :
1098
1120
return format (value , "f" )
1099
1121
1100
1122
@@ -1168,7 +1190,9 @@ def __init__(
1168
1190
if falsy is not None :
1169
1191
self .falsy = set (falsy )
1170
1192
1171
- def _serialize (self , value , attr , obj , ** kwargs ):
1193
+ def _serialize (
1194
+ self , value : typing .Any , attr : str | None , obj : typing .Any , ** kwargs
1195
+ ):
1172
1196
if value is None :
1173
1197
return None
1174
1198
0 commit comments