Is it possible to set a lower / upper bound for a filds.Int
in marshmallow
?
What I want to do is
from marshmallow import Schema, fields
class User(Schema):
age = fields.Int()
u = User()
data = u.load({'age': -1})
>>> data
{'age': 0}
In the case, I want to set 0 as a lower-bound value for age.
It does not seem like you can set a bound that will alter your input value upon deserialization using Marshmallow
's api; and it might be for good reason: it would be very confusing to see something like data = u.load({'age': -1})
and getting {'age': 0}
back.
What you can do is pass a function to fields.Int
's validate
parameter that would allow you to catch values you don't want. Example usage:
class User(Schema):
age = fields.Int(validate=lambda x: x > 0) # don't let anything <0 in
u = User()
data = u.load({'age': -1}
Output:
marshmallow.exceptions.ValidationError: {'age': ['Invalid value.']}
With this information in mind, you can handle this exception as you please, e.g.:
try:
data = u.load({'age': -1})
except marshmallow.exceptions.ValidationError:
data = u.load({'age': 0})
If you feel that you must create some bounds for your fields.Int
usage, then you can extend fields.Int
in the following manner:
import typing
from marshmallow import fields, Schema
_T = typing.TypeVar("_T")
class BoundedInt(fields.Int):
def __init__(self, *a, bounds, **kw):
self._bounds: typing.Tuple[int] = bounds # bounds=(0, 10)
super().__init__(*a, **kw)
def _validated(self, value) -> typing.Optional[_T]:
if value < self._bounds[0]:
value = self._bounds[0]
elif value > self._bounds[1]:
value = self._bounds[1]
return super()._validated(value)
class User(Schema):
age = BoundedInt(bounds=(0, 10))
Usage:
>>> u = User()
>>> data = u.load({'age': -1})
>>> data
{'age': 0}