Quickstart
Installation
CleanChausie requires Python 3.8+.
To install, run python3 -m pip install cleanchausie.
Declaring a Schema
Declarative schemas inherit from cleanchausie.Schema. In its simplest form:
import datetime
from typing import Optional
from cleanchausie import Schema, clean, serialize
class JobApplication(Schema):
name: str
middle_initial: Optional[str] = None
referrer: Optional[str]
timestamp: datetime.datetime
external_data = {
'name': 'John Doe',
'referrer': None,
'timestamp': '2020-01-01T00:00:00Z',
}
validation_result = clean(JobApplication, external_data)
print(serialize(validation_result))
"""
{
'name': 'John Doe',
'middle_initial': None,
'referrer': None,
'timestamp': '2020-01-01T00:00:00+00:00'
}
"""
What's going on here? Let's break it down:
- Inheriting from
Schemagives us a few things:- A
cleanclassmethod, which takes in a dictionary and returns aSchemainstance if validation passes, or aValidationErrorif validation fails. - A
serializemethod, which returns a dictionary representation of the schema instance.
- A
nameis annotated asstr. CleanChausie automatically turns this into aStringField, which will only accept string values.middle_initialis an not required, and if omitted is set toNone.referreris required, but is also nullable. Omitting it will result in a validation error, but an explicitNoneis completely valid.timestampis our first non-string field. It's adatetimeand is required. Datetime-ey strings are turned intodatetimeobjects.
If validation fails, instead of returning an instance of JobApplication, we
get a ValidationError instance instead.
external_data = {
'name': 5,
'timestamp': 'The first monday after Jan 1 1970',
}
validation_result = clean(JobApplication, external_data)
print(serialize(validation_result))
"""
{
'errors': [
{
'field': ('timestamp',),
'msg': "Could not parse datetime from 'The first monday after Jan 1 1970'"
},
{'field': ('referrer',), 'msg': 'This field is required.'},
{'field': ('name',), 'msg': "Expected a string, got 'int'."}
]
}
"""
But why CleanChausie?
Types
CleanChausie operates on/with type-checked objects that have good IDE/autocomplete support. Simple fields can be declared with just annotations.
Errors are returned instead of raised, which means mypy will help you
catch validation errors.
Composable
Fields and field validation logic are composable and reusable. The declarative
Schema class is a wrapper around a more functional core, which leans into
composition over inheritance. It's easy to write and reuse custom fields which
compose and extend existing fields.
Context
Validation supports (but does not require) passing around an explicit context
to any field validation function that requests it. It's only used within
validation logic, is not stored with validated data. Contexts are commonly used
to avoid global state, or for explicit session management on database lookups.
Nullable vs Omitted
Presence validation and value validation are treated as distinct first-class
citizens. Fields can be required, required and nullable, omittable (with an
omitted singleton default), or omittable with a different default value.
Cleanchausie understands Union[OMITTED, str] annotations, and can
automatically parse all the above scenarios.
Intra-schema dependencies
Fields within a schema can depend on the validated value of other fields in the same schema. Validated values are passed to dependent fields as args (using dependency injection), and the field validation order is handled automatically.