mirror of
https://github.com/kennethreitz/pydantic.git
synced 2026-06-05 23:00:18 +00:00
31683f8dc4
* 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
254 lines
5.9 KiB
Python
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]))
|