CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-schematics

Python Data Structures for Humans - a library for data validation and transformation using structured models

Pending
Overview
Eval results
Files

exceptions.mddocs/

Exception System

Comprehensive exception hierarchy for handling validation errors, conversion failures, and data processing issues in Schematics. The exception system provides detailed error information with field-level granularity and supports error aggregation for complex data structures.

Capabilities

Base Exception Classes

Foundation exception classes providing common error handling functionality.

class BaseError(Exception):
    """
    Base class for all Schematics errors with error aggregation.
    
    Provides immutable error storage and primitive representation
    for machine-readable error processing.
    """
    
    def __init__(self, errors):
        """
        Initialize base error.
        
        Args:
            errors: Error data (dict/list/string)
        """
    
    @property
    def errors(self):
        """
        Get immutable error data.
        
        Returns:
            Frozen error structure
        """
    
    def to_primitive(self):
        """
        Convert errors to primitive representation.
        
        Returns:
            dict: JSON-serializable error structure
        """

class ErrorMessage:
    """
    Error message container with internationalization support.
    
    Wraps error messages with metadata for display and localization.
    """
    
    def __init__(self, message, **kwargs):
        """
        Initialize error message.
        
        Args:
            message (str): Error message text
            **kwargs: Additional message metadata
        """

Field-Level Exceptions

Exceptions for individual field validation and conversion errors.

class FieldError(BaseError):
    """
    Base class for field-specific errors.
    
    Associates errors with specific model fields and provides
    context for field-level error handling.
    """

class ConversionError(FieldError):
    """
    Raised during data type conversion failures.
    
    Occurs when input data cannot be converted to the field's
    expected type (e.g., string to integer conversion failure).
    """
    
    def __init__(self, message, **kwargs):
        """
        Initialize conversion error.
        
        Args:
            message (str): Conversion error description
            **kwargs: Additional conversion context
        """

class ValidationError(FieldError):
    """
    Raised during field validation failures.
    
    Occurs when converted data fails field validation rules
    (e.g., string length, numeric range, regex pattern).
    """
    
    def __init__(self, message, **kwargs):
        """
        Initialize validation error.
        
        Args:
            message (str): Validation error description
            **kwargs: Additional validation context
        """

class StopValidationError(FieldError):
    """
    Stops validation chain without raising an error.
    
    Used internally to halt validation processing without
    treating the condition as an error state.
    """

Model-Level Exceptions

Exceptions for model-wide validation and data processing errors.

class CompoundError(BaseError):
    """
    Container for multiple field errors.
    
    Aggregates validation errors from multiple fields into a
    single exception with structured error information.
    """
    
    def __init__(self, errors, **kwargs):
        """
        Initialize compound error.
        
        Args:
            errors (dict): Field name to error mapping
            **kwargs: Additional error context
        """

class DataError(BaseError):
    """
    Model data errors with partial data preservation.
    
    Raised when model validation fails but allows access to
    partial data that was successfully processed.
    """
    
    def __init__(self, errors, partial_data=None, **kwargs):
        """
        Initialize data error.
        
        Args:
            errors: Validation errors
            partial_data (dict, optional): Successfully processed data
            **kwargs: Additional error context
        """
    
    @property
    def partial_data(self):
        """
        Get partial data that was successfully processed.
        
        Returns:
            dict: Partial model data
        """

Utility Exceptions

Specialized exceptions for specific error conditions.

class MockCreationError(BaseError):
    """
    Errors during mock data generation.
    
    Raised when mock object creation fails due to field
    constraints or generation limitations.
    """

class UndefinedValueError(BaseError):
    """
    Raised when accessing undefined field values.
    
    Occurs when attempting to access a field value that
    has not been set and has no default value.
    """

class UnknownFieldError(BaseError):
    """
    Raised when accessing nonexistent fields.
    
    Occurs when attempting to access a field that is not
    defined in the model schema.
    """

Usage Examples

Basic Error Handling

from schematics.models import Model
from schematics.types import StringType, IntType
from schematics.exceptions import ValidationError, ConversionError, DataError

class Product(Model):
    name = StringType(required=True, max_length=50)
    price = IntType(min_value=0, required=True)
    category = StringType(choices=['electronics', 'books', 'clothing'])

# Validation error handling
try:
    product = Product({
        'name': 'A very long product name that exceeds the maximum length limit',
        'price': -10,  # Negative price
        'category': 'invalid_category'
    })
    product.validate()
except ValidationError as e:
    print(f"Validation failed: {e}")
    print(f"Error details: {e.to_primitive()}")

Multiple Field Errors

# DataError with multiple field validation failures
try:
    invalid_product = Product({
        'name': '',        # Required field empty
        'price': 'abc',    # Cannot convert to int
        'category': 'toys' # Not in choices
    })
    invalid_product.validate()
except DataError as e:
    print("Multiple validation errors occurred:")
    for field, error in e.errors.items():
        print(f"  {field}: {error}")
    
    # Access any partial data that was successfully processed
    if hasattr(e, 'partial_data') and e.partial_data:
        print(f"Partial data: {e.partial_data}")

Conversion Error Handling

from schematics.types import DateTimeType, EmailType

class User(Model):
    email = EmailType(required=True)
    registered_at = DateTimeType(required=True)

try:
    user = User({
        'email': 'invalid-email-format',
        'registered_at': 'not-a-date'
    })
    user.validate()
except ConversionError as e:
    print(f"Data conversion failed: {e}")
except ValidationError as e:
    print(f"Data validation failed: {e}")

Custom Error Handling for API Responses

def process_user_registration(user_data):
    """
    Process user registration with comprehensive error handling.
    
    Returns:
        tuple: (success: bool, data: dict, errors: dict)
    """
    try:
        user = User(user_data)
        user.validate()
        return True, user.to_primitive(), None
        
    except ValidationError as e:
        # Single field validation error
        return False, None, {
            'type': 'validation_error',
            'field': getattr(e, 'field_name', 'unknown'),
            'message': str(e)
        }
        
    except DataError as e:
        # Multiple field validation errors
        return False, e.partial_data, {
            'type': 'data_error',
            'errors': e.to_primitive(),
            'fields_with_errors': list(e.errors.keys())
        }
        
    except ConversionError as e:
        # Data type conversion error
        return False, None, {
            'type': 'conversion_error',
            'field': getattr(e, 'field_name', 'unknown'),
            'message': f"Could not convert value: {str(e)}"
        }

# Usage
success, data, errors = process_user_registration({
    'email': 'john@example.com',
    'registered_at': '2024-01-15T10:30:00Z'
})

if success:
    print(f"User registered successfully: {data}")
else:
    print(f"Registration failed: {errors}")

Error Aggregation for Nested Models

from schematics.types import ModelType, ListType

class Address(Model):
    street = StringType(required=True)
    city = StringType(required=True)
    zip_code = StringType(required=True, regex=r'^\d{5}(-\d{4})?$')

class Person(Model):
    name = StringType(required=True)
    addresses = ListType(ModelType(Address), min_size=1)

# Complex validation with nested errors
try:
    person = Person({
        'name': '',  # Invalid: required field empty
        'addresses': [
            {
                'street': '123 Main St',
                'city': 'Anytown',
                'zip_code': 'invalid'  # Invalid: doesn't match regex
            },
            {
                'street': '',          # Invalid: required field empty
                'city': 'Other City',
                'zip_code': '12345'
            }
        ]
    })
    person.validate()
    
except DataError as e:
    print("Nested validation errors:")
    errors = e.to_primitive()
    
    # Navigate nested error structure
    if 'name' in errors:
        print(f"Name error: {errors['name']}")
    
    if 'addresses' in errors:
        for i, addr_errors in enumerate(errors['addresses']):
            if addr_errors:
                print(f"Address {i} errors: {addr_errors}")

Custom Exception Handling Patterns

def safe_model_creation(model_class, data, strict=True):
    """
    Safely create and validate model with configurable error handling.
    
    Args:
        model_class: Model class to instantiate
        data: Raw data dictionary
        strict: Whether to raise on validation errors
        
    Returns:
        tuple: (model_instance or None, error_info or None)
    """
    try:
        model = model_class(data)
        model.validate()
        return model, None
        
    except ValidationError as e:
        error_info = {
            'error_type': 'validation',
            'message': str(e),
            'field': getattr(e, 'field_name', None)
        }
        if strict:
            raise
        return None, error_info
        
    except ConversionError as e:
        error_info = {
            'error_type': 'conversion', 
            'message': str(e),
            'field': getattr(e, 'field_name', None)
        }
        if strict:
            raise
        return None, error_info
        
    except DataError as e:
        error_info = {
            'error_type': 'data',
            'errors': e.to_primitive(),
            'partial_data': getattr(e, 'partial_data', None)
        }
        if strict:
            raise
        return None, error_info

# Usage with different error handling strategies
model, error = safe_model_creation(User, user_data, strict=False)
if model:
    print("Model created successfully")
else:
    print(f"Model creation failed: {error}")

Install with Tessl CLI

npx tessl i tessl/pypi-schematics

docs

basic-types.md

compound-types.md

contrib-modules.md

dynamic-fields.md

exceptions.md

index.md

models.md

network-types.md

utilities.md

tile.json