diff --git a/lollipop/types.py b/lollipop/types.py index 21d6959..781b2d7 100644 --- a/lollipop/types.py +++ b/lollipop/types.py @@ -164,6 +164,11 @@ class Any(Type): class Number(Type): """Any number type (integer/float). + :param bool strict: If True, it will allow to perform type casting + from string representation to numeric. If False, it will raise + :exc:`~lollipop.errors.ValidationError` for strint input during + deserialization. + Error message keys: * invalid - invalid value type. Interpolation data: * data - actual value @@ -173,6 +178,10 @@ class Number(Type): 'invalid': 'Value should be number', } + def __init__(self, strict=True, *args, **kwargs): + super(Number, self).__init__(**kwargs) + self.strict = strict + def _normalize(self, value): try: return self.num_type(value) @@ -183,7 +192,7 @@ def load(self, data, *args, **kwargs): if data is MISSING or data is None: self._fail('required') - if isinstance(data, string_types): + if self.strict and isinstance(data, string_types): self._fail('invalid') return super(Number, self).load(self._normalize(data), *args, **kwargs) diff --git a/tests/test_types.py b/tests/test_types.py index a33b131..1fe7192 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -214,6 +214,9 @@ def test_loading_integer(self): def test_loading_float_value(self): assert Number().load(1.23) == 1.23 + def test_loading_non_strict_integer(self): + assert Number(strict=False).load("123") == 123 + def test_loading_numeric_as_string(self): with pytest.raises(ValidationError) as exc_info: Number().load("123")