Validation Errors
"Expected" errors (as a result of validation not passing) in CleanChausie aren't handled with exceptions, they're returned. This gives us a few things:
- We can easily detect when our validation routine isn't working how it's expected to (because exceptions are the result of unexpected scenarios, and aren't used for control flow)
- We can easily return structured information about these errors (like which field they're for)
- We can easily handle multiple errors in the same round trip, returned at the same time.
- We can employ type-checking static analysis to ensure that we're handling errors correctly wherever they may occur.
Errors are returned as a flat list, which simplifies handling nested fields.
Each Error
has a field
tuple, which allows individual errors to reference
fields deeply nested inside of embedded objects or lists.
Let's start with a simple example:
from cleanchausie import ValidationError, Error, Schema, clean
class PerFieldErrorExampleSchema(Schema):
first_name: str
last_name: str
result = clean(PerFieldErrorExampleSchema, {})
assert isinstance(result, ValidationError)
assert result.errors == [
Error(msg='This field is required.', field=('last_name',)),
Error(msg='This field is required.', field=('first_name',))
]
Now let's add some nesting:
from typing import List
from cleanchausie import ValidationError, Error, Schema, clean
class PhoneSchema(Schema):
country_code: str
number: str
class AddressSchema(Schema):
street_name: str
street_number: str
zip: str
class UserSchema(Schema):
email: str
phone: PhoneSchema
addresses: List[AddressSchema]
result = clean(
UserSchema,
{
"phone": {"number": "1234567890"},
"addresses": [{"street_name": "High St", "street_number": "1337"}],
}
)
assert isinstance(result, ValidationError)
assert sorted(result.errors, key=lambda e: e.field) == [
Error(msg="This field is required.", field=("addresses", 0, "zip")),
Error(msg="This field is required.", field=("email",)),
Error(msg="This field is required.", field=("phone", "country_code")),
]