Lightweight, extensible schema and data validation tool for Python dictionaries.
Cerberus provides a comprehensive error handling system with detailed error representation, organization, and customizable formatting. The system captures precise validation failures with context and supports custom error handlers for different output formats.
Detailed representation of individual validation failures.
class ValidationError:
def __init__(self, document_path, schema_path, code, rule, constraint, value, info):
"""
Create a validation error.
Parameters:
- document_path: Path to field within document (tuple)
- schema_path: Path to rule within schema (tuple)
- code: Error identifier code (int)
- rule: Rule that failed validation (str)
- constraint: Constraint that failed
- value: Value that caused failure
- info: Additional error details (tuple)
"""
@property
def document_path(self) -> tuple:
"""Path to the field within the document that caused the error"""
@property
def schema_path(self) -> tuple:
"""Path to the rule within the schema that caused the error"""
@property
def code(self) -> int:
"""Error identifier code"""
@property
def rule(self) -> str:
"""Rule that failed validation"""
@property
def constraint(self):
"""Constraint that failed"""
@property
def value(self):
"""Value that caused the failure"""
@property
def info(self) -> tuple:
"""Additional error information"""
@property
def field(self):
"""Field name from document path"""
@property
def child_errors(self):
"""List of individual errors for bulk validation errors"""
@property
def definitions_errors(self):
"""Errors mapped to definition indices for *of-rules"""
@property
def is_group_error(self) -> bool:
"""True for bulk validation errors"""
@property
def is_logic_error(self) -> bool:
"""True for *of-rule validation errors"""
@property
def is_normalization_error(self) -> bool:
"""True for normalization errors"""Specialized collections for organizing validation errors.
class ErrorList(list):
"""
List of ValidationError instances with queryable interface.
Supports 'in' keyword for ErrorDefinition instances.
"""Hierarchical organization of validation errors.
class ErrorTree:
"""Base class for organizing errors in tree structures"""
def add(self, error):
"""
Add ValidationError to tree.
Parameters:
- error: ValidationError to add
"""
def fetch_errors_from(self, path):
"""
Get all errors for a given path.
Parameters:
- path: Path to fetch errors for (tuple)
Returns:
list: Errors at the specified path
"""
def fetch_node_from(self, path):
"""
Get tree node for a given path.
Parameters:
- path: Path to fetch node for (tuple)
Returns:
Tree node at the specified path
"""
class DocumentErrorTree(ErrorTree):
"""Error tree following document field structure"""
class SchemaErrorTree(ErrorTree):
"""Error tree following schema rule structure"""Customizable error formatting and output.
class BaseErrorHandler:
"""Abstract base class for all error handlers"""
def __call__(self, errors):
"""
Format errors for output.
Parameters:
- errors: Errors to format
Returns:
Formatted error output
"""
def add(self, error):
"""
Add error to handler.
Parameters:
- error: ValidationError to add
"""
def extend(self, errors):
"""
Add multiple errors.
Parameters:
- errors: Iterable of ValidationError instances
"""
def emit(self, error):
"""
Optionally emit error to stream.
Parameters:
- error: ValidationError to emit
"""
def start(self, validator):
"""
Called when validation starts.
Parameters:
- validator: Validator instance starting validation
"""
def end(self, validator):
"""
Called when validation ends.
Parameters:
- validator: Validator instance ending validation
"""
class BasicErrorHandler(BaseErrorHandler):
"""Default error handler that returns errors as nested dict"""
@property
def messages(self) -> dict:
"""Error code to message template mapping"""
@property
def tree(self):
"""Raw error tree structure"""
@property
def pretty_tree(self):
"""Cleaned error tree for display"""
class ToyErrorHandler(BaseErrorHandler):
"""Minimal error handler for child validators"""
class SchemaErrorHandler(BaseErrorHandler):
"""Specialized error handler for schema validation errors"""Pre-defined error codes and types for different validation failures.
# Existence Errors
CUSTOM: ErrorDefinition # Custom validation errors (0x00)
DOCUMENT_MISSING: str # Document is missing
REQUIRED_FIELD: ErrorDefinition # Required field missing (0x02)
UNKNOWN_FIELD: ErrorDefinition # Unknown field present (0x03)
DEPENDENCIES_FIELD: ErrorDefinition # Field dependency failed (0x04)
DEPENDENCIES_FIELD_VALUE: ErrorDefinition # Field dependency value failed (0x05)
EXCLUDES_FIELD: ErrorDefinition # Field exclusion failed (0x06)
# Shape Errors
DOCUMENT_FORMAT: str # Document format invalid
EMPTY_NOT_ALLOWED: ErrorDefinition # Empty value not allowed (0x22)
NOT_NULLABLE: ErrorDefinition # Null value not allowed (0x23)
BAD_TYPE: ErrorDefinition # Type constraint failed (0x24)
BAD_TYPE_FOR_SCHEMA: ErrorDefinition # Schema type constraint failed (0x25)
ITEMS_LENGTH: ErrorDefinition # Items length constraint failed (0x26)
MIN_LENGTH: ErrorDefinition # Minimum length constraint failed (0x27)
MAX_LENGTH: ErrorDefinition # Maximum length constraint failed (0x28)
# Value Errors
REGEX_MISMATCH: ErrorDefinition # Regex pattern match failed (0x41)
MIN_VALUE: ErrorDefinition # Minimum value constraint failed (0x42)
MAX_VALUE: ErrorDefinition # Maximum value constraint failed (0x43)
UNALLOWED_VALUE: ErrorDefinition # Value not in allowed list (0x44)
UNALLOWED_VALUES: ErrorDefinition # Values not in allowed list (0x45)
FORBIDDEN_VALUE: ErrorDefinition # Value in forbidden list (0x46)
FORBIDDEN_VALUES: ErrorDefinition # Values in forbidden list (0x47)
MISSING_MEMBERS: ErrorDefinition # Required members missing (0x48)
# Processing Errors
NORMALIZATION: ErrorDefinition # Normalization failed (0x60)
COERCION_FAILED: ErrorDefinition # Type coercion failed (0x61)
RENAMING_FAILED: ErrorDefinition # Field renaming failed (0x62)
READONLY_FIELD: ErrorDefinition # Readonly field modified (0x63)
SETTING_DEFAULT_FAILED: ErrorDefinition # Default value setting failed (0x64)
# Group Errors
ERROR_GROUP: ErrorDefinition # Error group container (0x80)
MAPPING_SCHEMA: ErrorDefinition # Mapping schema failed (0x81)
SEQUENCE_SCHEMA: ErrorDefinition # Sequence schema failed (0x82)
KEYSRULES: ErrorDefinition # Keys rules failed (0x83)
VALUESRULES: ErrorDefinition # Values rules failed (0x84)
BAD_ITEMS: ErrorDefinition # Items constraint failed (0x8F)
# Logical Errors
LOGICAL: ErrorDefinition # Logical constraint failed (0x90)
NONEOF: ErrorDefinition # None-of constraint failed (0x91)
ONEOF: ErrorDefinition # One-of constraint failed (0x92)
ANYOF: ErrorDefinition # Any-of constraint failed (0x93)
ALLOF: ErrorDefinition # All-of constraint failed (0x94)ErrorDefinition = namedtuple('ErrorDefinition', 'code rule')
"""Defines error types with unique code and associated rule"""from cerberus import Validator
schema = {
'name': {'type': 'string', 'minlength': 2},
'age': {'type': 'integer', 'min': 0, 'max': 150},
'email': {'type': 'string', 'required': True}
}
v = Validator(schema)
# Invalid document
document = {
'name': 'A', # Too short
'age': -5, # Below minimum
# 'email' missing # Required field missing
}
if not v.validate(document):
print("Validation failed!")
print("Errors:", v.errors)
# Output: {
# 'name': ['min length is 2'],
# 'age': ['min value is 0'],
# 'email': ['required field']
# }from cerberus import Validator
v = Validator({'name': {'type': 'string'}})
v.validate({'name': 123})
# Access error tree for detailed information
error_tree = v.document_error_tree
print(error_tree.errors)
# Access individual validation errors
for error in error_tree.errors:
print(f"Field: {error.field}")
print(f"Rule: {error.rule}")
print(f"Code: {error.code}")
print(f"Value: {error.value}")
print(f"Path: {error.document_path}")from cerberus import Validator
from cerberus.errors import BaseErrorHandler
class CustomErrorHandler(BaseErrorHandler):
def __call__(self, errors):
"""Return simple list of error messages"""
messages = []
for field_errors in errors.values():
messages.extend(field_errors)
return messages
# Use custom handler
v = Validator({'name': {'type': 'string'}}, error_handler=CustomErrorHandler)
v.validate({'name': 123})
print(v.errors) # ['must be of string type']from cerberus import Validator
from cerberus.errors import BasicErrorHandler
# Pass handler as tuple with initialization arguments
error_handler_config = (BasicErrorHandler, {'some_option': 'value'})
v = Validator(schema, error_handler=error_handler_config)from cerberus import Validator
schema = {
'user': {
'type': 'dict',
'schema': {
'name': {'type': 'string'},
'contacts': {
'type': 'list',
'schema': {
'type': 'dict',
'schema': {
'type': {'type': 'string', 'allowed': ['email', 'phone']},
'value': {'type': 'string'}
}
}
}
}
}
}
document = {
'user': {
'name': 123, # Invalid type
'contacts': [
{'type': 'invalid', 'value': 'test@example.com'}, # Invalid type
{'type': 'email'} # Missing value
]
}
}
v = Validator(schema)
v.validate(document)
# Navigate error tree
error_tree = v.document_error_tree
# Get errors for specific paths
name_errors = error_tree.fetch_errors_from(('user', 'name'))
contact_errors = error_tree.fetch_errors_from(('user', 'contacts', 0, 'type'))
print("Name errors:", name_errors)
print("Contact type errors:", contact_errors)from cerberus import Validator
from cerberus.errors import BAD_TYPE, REQUIRED_FIELD
v = Validator({'name': {'type': 'string', 'required': True}})
v.validate({'name': 123})
# Check if specific error types occurred
error_tree = v.document_error_tree
errors = error_tree.errors
for error in errors:
if error.code == BAD_TYPE.code:
print(f"Type error in field {error.field}: expected string, got {type(error.value).__name__}")
elif error.code == REQUIRED_FIELD.code:
print(f"Missing required field: {error.field}")from cerberus import Validator
from cerberus.errors import BaseErrorHandler
import sys
class StreamingErrorHandler(BaseErrorHandler):
def emit(self, error):
"""Emit errors to stderr as they occur"""
print(f"Validation error: {error.field} - {error.rule}", file=sys.stderr)
def __call__(self, errors):
"""Return standard error format"""
return errors
v = Validator({'name': {'type': 'string'}}, error_handler=StreamingErrorHandler)
# Errors will be printed to stderr during validation
v.validate({'name': 123})from cerberus import Validator
from cerberus.errors import BasicErrorHandler
v = Validator({'user': {'type': 'dict', 'schema': {'name': {'type': 'string'}}}})
v.validate({'user': {'name': 123}})
# Access pretty-formatted error tree
if hasattr(v.error_handler, 'pretty_tree'):
pretty_errors = v.error_handler.pretty_tree
print("Pretty errors:", pretty_errors)Install with Tessl CLI
npx tessl i tessl/pypi-cerberus