Merge pull request #676 from dmontagu/type-in-validation-error

Add type name to ValidationError error message
This commit is contained in:
Samuel Colvin
2019-08-05 10:50:30 +01:00
committed by GitHub
5 changed files with 46 additions and 14 deletions
+6
View File
@@ -3,6 +3,11 @@
History
-------
v0.32 (unreleased)
..................
* add model name to ``ValidationError`` error message, #676 by @dmontagu
v0.31.1 (2019-07-31)
....................
* fix json generation for ``EnumError``, #697 by @dmontagu
@@ -20,6 +25,7 @@ v0.31 (2019-07-24)
* add ``Config.keep_untouched`` for custom descriptors support, #679 by @MrMrRobat
* use ``inspect.cleandoc`` internally to get model description, #657 by @tiangolo
* add ``Color`` to schema generation, by @euri10
* add documentation for Literal type, #651 by @dmontagu
v0.30.1 (2019-07-15)
....................
+1 -1
View File
@@ -44,7 +44,7 @@ def setattr_validate_assignment(self: 'DataclassType', name: str, value: Any) ->
d.pop(name)
value, error_ = self.__pydantic_model__.__fields__[name].validate(value, d, loc=name, cls=self.__class__)
if error_:
raise ValidationError([error_])
raise ValidationError([error_], type(self))
object.__setattr__(self, name, value)
+7 -3
View File
@@ -49,10 +49,11 @@ ErrorList = Union[Sequence[Any], ErrorWrapper]
class ValidationError(ValueError):
__slots__ = ('raw_errors',)
__slots__ = ('raw_errors', 'model')
def __init__(self, errors: Sequence[ErrorList]) -> None:
def __init__(self, errors: Sequence[ErrorList], model: Type[Any]) -> None:
self.raw_errors = errors
self.model = model
@lru_cache()
def errors(self) -> List[Dict[str, Any]]:
@@ -64,7 +65,10 @@ class ValidationError(ValueError):
def __str__(self) -> str:
errors = self.errors()
no_errors = len(errors)
return f'{no_errors} validation error{"" if no_errors == 1 else "s"}\n{display_errors(errors)}'
return (
f'{no_errors} validation error{"" if no_errors == 1 else "s"} for {self.model.__name__}\n'
f'{display_errors(errors)}'
)
def display_errors(errors: List[Dict[str, Any]]) -> str:
+13 -7
View File
@@ -293,7 +293,7 @@ class BaseModel(metaclass=MetaModel):
elif self.__config__.validate_assignment:
value_, error_ = self.fields[name].validate(value, self.dict(exclude={name}), loc=name)
if error_:
raise ValidationError([error_])
raise ValidationError([error_], type(self))
else:
self.__values__[name] = value_
self.__fields_set__.add(name)
@@ -372,7 +372,7 @@ class BaseModel(metaclass=MetaModel):
obj = dict(obj)
except (TypeError, ValueError) as e:
exc = TypeError(f'{cls.__name__} expected dict not {type(obj).__name__}')
raise ValidationError([ErrorWrapper(exc, loc='__obj__')]) from e
raise ValidationError([ErrorWrapper(exc, loc='__obj__')], cls) from e
return cls(**obj)
@classmethod
@@ -390,7 +390,7 @@ class BaseModel(metaclass=MetaModel):
b, proto=proto, content_type=content_type, encoding=encoding, allow_pickle=allow_pickle
)
except (ValueError, TypeError, UnicodeDecodeError) as e:
raise ValidationError([ErrorWrapper(e, loc='__obj__')])
raise ValidationError([ErrorWrapper(e, loc='__obj__')], cls)
return cls.parse_obj(obj)
@classmethod
@@ -783,9 +783,15 @@ def validate_model( # noqa: C901 (ignore complexity)
for f in sorted(extra):
errors.append(ErrorWrapper(ExtraError(), loc=f, config=config))
if not raise_exc:
return values, fields_set, ValidationError(errors) if errors else None
err = None
if errors:
raise ValidationError(errors)
model_type = model if isinstance(model, type) else type(model)
err = ValidationError(errors, model_type)
if not raise_exc:
return values, fields_set, err
if err:
raise err
return values, fields_set, None
+19 -3
View File
@@ -135,7 +135,7 @@ from pydantic.error_wrappers import ValidationError, flatten_errors, get_exc_typ
(
'__str__',
"""\
11 validation errors
11 validation errors for Model
a
value is not a valid integer (type=type_error.integer)
b -> x
@@ -227,7 +227,7 @@ def test_single_error():
Model(x='x')
expected = """\
1 validation error
1 validation error for Model
x
value is not a valid integer (type=type_error.integer)"""
assert str(exc_info.value) == expected
@@ -239,7 +239,7 @@ x
assert (
str(exc_info.value)
== """\
1 validation error
1 validation error for Model
x
field required (type=value_error.missing)"""
)
@@ -261,3 +261,19 @@ def test_nested_error():
expected = [{'loc': ('data1', 0, 'data2', 0, 'x'), 'msg': 'field required', 'type': 'value_error.missing'}]
assert exc_info.value.errors() == expected
def test_validate_assignment_error():
class Model(BaseModel):
x: int
class Config:
validate_assignment = True
model = Model(x=1)
with pytest.raises(ValidationError) as exc_info:
model.x = 'a'
assert (
str(exc_info.value)
== '1 validation error for Model\nx\n value is not a valid integer (type=type_error.integer)'
)