Strict validation of list, set and tuple (#86) (#200)

* Strict validation of `list`, `set` and `tuple` (#86)

* review fixes
This commit is contained in:
Nikita Grishko
2018-06-13 21:11:01 +03:00
committed by Samuel Colvin
parent 7e44bcaf7a
commit 4f19d2b94a
3 changed files with 68 additions and 21 deletions
+4
View File
@@ -3,6 +3,10 @@
History
-------
v0.10.1 (2018-xx-xx)
....................
* make ``list``, ``tuple`` and ``set`` types stricter #86
v0.10.0 (2018-06-11)
....................
* add ``Config.allow_population_by_alias`` #160, thanks @bendemaree
+10 -6
View File
@@ -1,3 +1,4 @@
import inspect
from collections import OrderedDict
from datetime import date, datetime, time, timedelta
from decimal import Decimal, DecimalException
@@ -133,25 +134,28 @@ def dict_validator(v) -> dict:
def list_validator(v) -> list:
if isinstance(v, list):
return v
with change_exception(errors.ListError, TypeError):
elif isinstance(v, (tuple, set)) or inspect.isgenerator(v):
return list(v)
else:
raise errors.ListError()
def tuple_validator(v) -> tuple:
if isinstance(v, tuple):
return v
with change_exception(errors.TupleError, TypeError):
elif isinstance(v, (list, set)) or inspect.isgenerator(v):
return tuple(v)
else:
raise errors.TupleError()
def set_validator(v) -> set:
if isinstance(v, set):
return v
with change_exception(errors.SetError, TypeError):
elif isinstance(v, (list, tuple)) or inspect.isgenerator(v):
return set(v)
else:
raise errors.SetError()
def enum_validator(v, field, config, **kwargs) -> Enum:
+54 -15
View File
@@ -428,16 +428,29 @@ def test_dict():
]
def test_list():
@pytest.mark.parametrize('value,result', (
([1, 2, '3'], [1, 2, '3']),
((1, 2, '3'), [1, 2, '3']),
({1, 2, '3'}, [1, 2, '3']),
((i**2 for i in range(5)), [0, 1, 4, 9, 16]),
))
def test_list_success(value, result):
class Model(BaseModel):
v: list
assert Model(v=[1, 2, '3']).v == [1, 2, '3']
assert Model(v='xyz').v == ['x', 'y', 'z']
assert Model(v=(i**2 for i in range(5))).v == [0, 1, 4, 9, 16]
assert Model(v=value).v == result
@pytest.mark.parametrize('value', (
123,
'123',
))
def test_list_fails(value):
class Model(BaseModel):
v: list
with pytest.raises(ValidationError) as exc_info:
Model(v=1)
Model(v=value)
assert exc_info.value.errors() == [
{
'loc': ('v',),
@@ -466,16 +479,29 @@ def test_ordered_dict():
]
def test_tuple():
@pytest.mark.parametrize('value,result', (
([1, 2, '3'], (1, 2, '3')),
((1, 2, '3'), (1, 2, '3')),
({1, 2, '3'}, (1, 2, '3')),
((i**2 for i in range(5)), (0, 1, 4, 9, 16)),
))
def test_tuple_success(value, result):
class Model(BaseModel):
v: tuple
assert Model(v=(1, 2, '3')).v == (1, 2, '3')
assert Model(v='xyz').v == ('x', 'y', 'z')
assert Model(v=(i**2 for i in range(5))).v == (0, 1, 4, 9, 16)
assert Model(v=value).v == result
@pytest.mark.parametrize('value', (
123,
'123',
))
def test_tuple_fails(value):
class Model(BaseModel):
v: tuple
with pytest.raises(ValidationError) as exc_info:
Model(v=1)
Model(v=value)
assert exc_info.value.errors() == [
{
'loc': ('v',),
@@ -485,16 +511,29 @@ def test_tuple():
]
def test_set():
@pytest.mark.parametrize('value,result', (
({1, 2, 2, '3'}, {1, 2, '3'}),
((1, 2, 2, '3'), {1, 2, '3'}),
([1, 2, 2, '3'], {1, 2, '3'}),
({i**2 for i in range(5)}, {0, 1, 4, 9, 16}),
))
def test_set_success(value, result):
class Model(BaseModel):
v: set
assert Model(v={1, 2, 2, '3'}).v == {1, 2, '3'}
assert Model(v='xyzxyz').v == {'x', 'y', 'z'}
assert Model(v={i**2 for i in range(5)}).v == {0, 1, 4, 9, 16}
assert Model(v=value).v == result
@pytest.mark.parametrize('value', (
123,
'123',
))
def test_set_fails(value):
class Model(BaseModel):
v: set
with pytest.raises(ValidationError) as exc_info:
Model(v=1)
Model(v=value)
assert exc_info.value.errors() == [
{
'loc': ('v',),