Files
pydantic/tests/test_exceptions.py
T
Nikita Grishko 31683f8dc4 Errors format (#179)
* Get rid of `track` in errors

* Move `display_as_type` func into utils module

* Get rid of error as `namedtuple`

* Renamed `Error.index` to `Error.loc`

* New way to get error type

* New way to get error message

* New errors format

* Renamed `flatten_errors` property to `flat_errors`

* `__slots__` for `Error` and `ValidationError`

* `loc` as `tuple`

* Tests

* Review fixes

* `flatten_errors` as generator
2018-05-23 14:50:04 +01:00

254 lines
5.9 KiB
Python

from typing import Dict, List, Union
from uuid import UUID
import pytest
from pydantic import BaseModel
from pydantic.exceptions import ValidationError, flatten_errors
@pytest.mark.parametrize('result,expected', (
(
'display_errors',
"""\
a
invalid literal for int() with base 10: 'not_int' (type=value_error)
b -> x
field required (type=value_error.missing)
b -> z
field required (type=value_error.missing)
c -> 0 -> x
invalid literal for int() with base 10: 'not_int' (type=value_error)
d
invalid literal for int() with base 10: 'string' (type=value_error)
d
badly formed hexadecimal UUID string (type=value_error)
e -> __key__
invalid literal for int() with base 10: 'not_int' (type=value_error)
f -> 0
int() argument must be a string, a bytes-like object or a number, not 'NoneType' (type=type_error)
f -> 0
None is not an allow value (type=type_error)""",
),
(
'flatten_errors',
[
{
'loc': (
'a',
),
'msg': 'invalid literal for int() with base 10: \'not_int\'',
'type': 'value_error',
},
{
'loc': (
'b',
'x',
),
'msg': 'field required',
'type': 'value_error.missing',
},
{
'loc': (
'b',
'z',
),
'msg': 'field required',
'type': 'value_error.missing',
},
{
'loc': (
'c',
0,
'x',
),
'msg': 'invalid literal for int() with base 10: \'not_int\'',
'type': 'value_error',
},
{
'loc': (
'd',
),
'msg': 'invalid literal for int() with base 10: \'string\'',
'type': 'value_error',
},
{
'loc': (
'd',
),
'msg': 'badly formed hexadecimal UUID string',
'type': 'value_error',
},
{
'loc': (
'e',
'__key__',
),
'msg': 'invalid literal for int() with base 10: \'not_int\'',
'type': 'value_error',
},
{
'loc': (
'f',
0,
),
'msg': 'int() argument must be a string, a bytes-like object or a number, not \'NoneType\'',
'type': 'type_error',
},
{
'loc': (
'f',
0,
),
'msg': 'None is not an allow value',
'type': 'type_error',
},
],
),
(
'json',
"""\
[
{
"loc": [
"a"
],
"msg": "invalid literal for int() with base 10: 'not_int'",
"type": "value_error"
},
{
"loc": [
"b",
"x"
],
"msg": "field required",
"type": "value_error.missing"
},
{
"loc": [
"b",
"z"
],
"msg": "field required",
"type": "value_error.missing"
},
{
"loc": [
"c",
0,
"x"
],
"msg": "invalid literal for int() with base 10: 'not_int'",
"type": "value_error"
},
{
"loc": [
"d"
],
"msg": "invalid literal for int() with base 10: 'string'",
"type": "value_error"
},
{
"loc": [
"d"
],
"msg": "badly formed hexadecimal UUID string",
"type": "value_error"
},
{
"loc": [
"e",
"__key__"
],
"msg": "invalid literal for int() with base 10: 'not_int'",
"type": "value_error"
},
{
"loc": [
"f",
0
],
"msg": "int() argument must be a string, a bytes-like object or a number, not 'NoneType'",
"type": "type_error"
},
{
"loc": [
"f",
0
],
"msg": "None is not an allow value",
"type": "type_error"
}
]"""
),
(
'__str__',
"""\
validation errors
a
invalid literal for int() with base 10: 'not_int' (type=value_error)
b -> x
field required (type=value_error.missing)
b -> z
field required (type=value_error.missing)
c -> 0 -> x
invalid literal for int() with base 10: 'not_int' (type=value_error)
d
invalid literal for int() with base 10: 'string' (type=value_error)
d
badly formed hexadecimal UUID string (type=value_error)
e -> __key__
invalid literal for int() with base 10: 'not_int' (type=value_error)
f -> 0
int() argument must be a string, a bytes-like object or a number, not 'NoneType' (type=type_error)
f -> 0
None is not an allow value (type=type_error)"""
),
))
def test_validation_error(result, expected):
class SubModel(BaseModel):
x: int
y: int
z: str
class Model(BaseModel):
a: int
b: SubModel
c: List[SubModel]
d: Union[int, UUID]
e: Dict[int, str]
f: List[Union[int, str]]
with pytest.raises(ValidationError) as exc_info:
Model.parse_obj({
'a': 'not_int',
'b': {
'y': 42,
},
'c': [
{
'x': 'not_int',
'y': 42,
'z': 'string',
},
],
'd': 'string',
'e': {
'not_int': 'string',
},
'f': [
None,
],
})
result = getattr(exc_info.value, result)
if callable(result):
result = result()
assert result == expected
def test_flatten_errors_unknown_error_object():
with pytest.raises(RuntimeError):
list(flatten_errors([object]))