Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/validators/nullable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::tools::SchemaDict;

use super::ValidationState;
use super::{build_validator, BuildValidator, CombinedValidator, DefinitionsBuilder, Validator};
use crate::errors::{ErrorType, ValError, ValLineError};

#[derive(Debug)]
pub struct NullableValidator {
Expand Down Expand Up @@ -41,7 +42,17 @@ impl Validator for NullableValidator {
) -> ValResult<Py<PyAny>> {
match input.is_none() {
true => Ok(py.None()),
false => self.validator.validate(py, input, state),
false => {
let val_res = self.validator.validate(py, input, state);
match val_res {
Ok(obj) => Ok(obj),
Err(ValError::LineErrors(mut lines)) => {
lines.push(ValLineError::new(ErrorType::NoneRequired { context: None }, input));
Err(ValError::from(lines))
}
Err(err) => Err(err),
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/benchmarks/test_complete_benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def test_complete_invalid():
lax_validator = SchemaValidator(lax_schema)
with pytest.raises(ValidationError) as exc_info:
lax_validator.validate_python(input_data_wrong())
assert len(exc_info.value.errors(include_url=False)) == 739
assert len(exc_info.value.errors(include_url=False)) == 841


@pytest.mark.benchmark(group='complete')
Expand Down
22 changes: 14 additions & 8 deletions tests/test_hypothesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,20 @@ def test_definition_cycles(definition_schema, data):
try:
assert definition_schema.validate_python(data) == data
except ValidationError as exc:
assert exc.errors(include_url=False) == [
{
'type': 'recursion_loop',
'loc': IsTuple(length=(1, None)),
'msg': 'Recursion error - cyclic reference detected',
'input': AnyThing(),
}
]
errors = exc.errors(include_url=False)

# 1st error-line should be the 'recursion-loop' error
assert errors[0] == {
'type': 'recursion_loop',
'loc': IsTuple(length=(1, None)),
'msg': 'Recursion error - cyclic reference detected',
'input': AnyThing(),
}

# There is one 'none-required' error per sub-branch location
assert all(e['type'] == 'none_required' for e in errors[1:])
nb_sub_branch_locs = len(data) - 1
assert nb_sub_branch_locs == len(errors[:1])


def test_definition_broken(definition_schema):
Expand Down
106 changes: 101 additions & 5 deletions tests/validators/test_definitions_recursive.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,13 @@ def test_recursion_branch():
'loc': ('branch',),
'msg': 'Recursion error - cyclic reference detected',
'input': {'name': 'recursive', 'branch': IsPartialDict(name='recursive')},
}
},
{
'type': 'none_required',
'loc': ('branch',),
'msg': 'Input should be None',
'input': {'name': 'recursive', 'branch': IsPartialDict(name='recursive')},
},
]


Expand Down Expand Up @@ -375,7 +381,13 @@ def test_recursion_branch_from_attributes():
'loc': ('branch',),
'msg': 'Recursion error - cyclic reference detected',
'input': HasAttributes(name='root', branch=AnyThing()),
}
},
{
'type': 'none_required',
'loc': ('branch',),
'msg': 'Input should be None',
'input': HasAttributes(name='root', branch=AnyThing()),
},
]


Expand Down Expand Up @@ -475,12 +487,30 @@ def test_multiple_tuple_recursion(multiple_tuple_schema: SchemaValidator):
'msg': 'Recursion error - cyclic reference detected',
'input': [1, IsList(length=2)],
},
{
'type': 'none_required',
'loc': ('f1', 1),
'msg': 'Input should be None',
'input': [1, IsList(length=2)],
},
{
'type': 'recursion_loop',
'loc': ('f2', 1),
'msg': 'Recursion error - cyclic reference detected',
'input': [1, IsList(length=2)],
},
{
'type': 'none_required',
'loc': ('f2', 1),
'msg': 'Input should be None',
'input': [1, IsList(length=2)],
},
{
'type': 'none_required',
'loc': ('f2',),
'msg': 'Input should be None',
'input': [1, IsList(length=2)],
},
]


Expand All @@ -497,12 +527,30 @@ def test_multiple_tuple_recursion_once(multiple_tuple_schema: SchemaValidator):
'msg': 'Recursion error - cyclic reference detected',
'input': [1, IsList(length=2)],
},
{
'type': 'none_required',
'loc': ('f1', 1),
'msg': 'Input should be None',
'input': [1, IsList(length=2)],
},
{
'type': 'recursion_loop',
'loc': ('f2', 1),
'msg': 'Recursion error - cyclic reference detected',
'input': [1, IsList(length=2)],
},
{
'type': 'none_required',
'loc': ('f2', 1),
'msg': 'Input should be None',
'input': [1, IsList(length=2)],
},
{
'type': 'none_required',
'loc': ('f2',),
'msg': 'Input should be None',
'input': [1, IsList(length=2)],
},
]


Expand Down Expand Up @@ -539,7 +587,13 @@ def wrap_func(input_value, validator, info):
'loc': (1,),
'msg': 'Recursion error - cyclic reference detected',
'input': IsList(positions={0: 1}, length=2),
}
},
{
'type': 'none_required',
'loc': (1,),
'msg': 'Input should be None',
'input': IsList(positions={0: 1}, length=2),
},
]


Expand Down Expand Up @@ -927,7 +981,19 @@ def test_cyclic_data() -> None:
'loc': ('b', 'a'),
'msg': 'Recursion error - cyclic reference detected',
'input': cyclic_data,
}
},
{
'type': 'none_required',
'loc': ('b', 'a'),
'msg': 'Input should be None',
'input': cyclic_data,
},
{
'type': 'none_required',
'loc': ('b',),
'msg': 'Input should be None',
'input': cyclic_data['b'],
},
]


Expand Down Expand Up @@ -977,7 +1043,25 @@ def test_cyclic_data_threeway() -> None:
'loc': ('b', 'c', 'a'),
'msg': 'Recursion error - cyclic reference detected',
'input': cyclic_data,
}
},
{
'type': 'none_required',
'loc': ('b', 'c', 'a'),
'msg': 'Input should be None',
'input': cyclic_data,
},
{
'type': 'none_required',
'loc': ('b', 'c'),
'msg': 'Input should be None',
'input': cyclic_data['b']['c'],
},
{
'type': 'none_required',
'loc': ('b',),
'msg': 'Input should be None',
'input': cyclic_data['b'],
},
]


Expand Down Expand Up @@ -1051,6 +1135,12 @@ def test_complex_recursive_type() -> None:
'msg': 'Input should be a valid boolean',
'input': datetime.date(1992, 12, 11),
},
{
'type': 'none_required',
'loc': ('dict[str,...]', 'a'),
'msg': 'Input should be None',
'input': datetime.date(1992, 12, 11),
},
{
'type': 'string_type',
'loc': ('str',),
Expand All @@ -1075,6 +1165,12 @@ def test_complex_recursive_type() -> None:
'msg': 'Input should be a valid boolean',
'input': {'a': datetime.date(1992, 12, 11)},
},
{
'type': 'none_required',
'loc': (),
'msg': 'Input should be None',
'input': {'a': datetime.date(1992, 12, 11)},
},
]


Expand Down
8 changes: 7 additions & 1 deletion tests/validators/test_nullable.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ def test_nullable():
'loc': (),
'msg': 'Input should be a valid integer, unable to parse string as an integer',
'input': 'hello',
}
},
{
'type': 'none_required',
'loc': (),
'msg': 'Input should be None',
'input': 'hello',
},
]


Expand Down
Loading