Skip to main content

Overview

Lodum provides a set of validator classes for runtime validation of deserialized values. All validators inherit from the base Validator class and raise DeserializationError when validation fails.

Validator Base Class

The abstract base class for all validators.
from lodum.validators import Validator

class Validator:
    def __call__(self, value: Any) -> None:
        raise NotImplementedError

Range

Validates that a value falls within a specified numeric range.
from lodum.validators import Range

Constructor

min
Optional[Any]
default:"None"
Minimum acceptable value (inclusive). If None, no minimum is enforced.
max
Optional[Any]
default:"None"
Maximum acceptable value (inclusive). If None, no maximum is enforced.

Behavior

Raises DeserializationError if:
  • Value is less than min (when min is not None)
  • Value is greater than max (when max is not None)

Example

from lodum import lodum, field
from lodum.validators import Range

@lodum
class Product:
    price: float = field(validate=[Range(min=0.0, max=10000.0)])
    quantity: int = field(validate=[Range(min=1)])

# Valid
product = Product(price=99.99, quantity=5)

# Raises DeserializationError: "Value -10 is less than minimum 0.0"
product = Product(price=-10, quantity=5)

# Raises DeserializationError: "Value 15000 is greater than maximum 10000.0"
product = Product(price=15000, quantity=5)

Length

Validates the length of sequences, strings, or any object supporting len().
from lodum.validators import Length

Constructor

min
Optional[int]
default:"None"
Minimum acceptable length (inclusive). If None, no minimum is enforced.
max
Optional[int]
default:"None"
Maximum acceptable length (inclusive). If None, no maximum is enforced.

Behavior

Raises DeserializationError if:
  • The value does not support len() operation
  • Length is less than min (when min is not None)
  • Length is greater than max (when max is not None)

Example

from lodum import lodum, field
from lodum.validators import Length

@lodum
class User:
    username: str = field(validate=[Length(min=3, max=20)])
    tags: list[str] = Field(validators=[Length(max=5)])

# Valid
user = User(username="alice", tags=["python", "coding"])

# Raises DeserializationError: "Length 2 is less than minimum 3"
user = User(username="ab", tags=[])

# Raises DeserializationError: "Length 6 is greater than maximum 5"
user = User(username="alice", tags=["a", "b", "c", "d", "e", "f"])

Match

Validates that a string value matches a regular expression pattern.
from lodum.validators import Match

Constructor

pattern
str
required
Regular expression pattern to match against. Uses Python’s re module.

Behavior

Raises DeserializationError if:
  • Value is not a string
  • Value does not match the compiled regex pattern

Example

from lodum import lodum, field
from lodum.validators import Match

@lodum
class Contact:
    email: str = field(validate=[Match(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')])
    phone: str = field(validate=[Match(r'^\d{3}-\d{3}-\d{4}$')])

# Valid
contact = Contact(email="[email protected]", phone="555-123-4567")

# Raises DeserializationError: "Value 'invalid-email' does not match pattern..."
contact = Contact(email="invalid-email", phone="555-123-4567")

# Raises DeserializationError: value is not a string
contact = Contact(email=12345, phone="555-123-4567")

OneOf

Validates that a value is one of a predefined set of acceptable values.
from lodum.validators import OneOf

Constructor

options
Container[Any]
required
A container of acceptable values. Any type supporting the in operator (list, set, tuple, etc.) can be used.

Behavior

Raises DeserializationError if the value is not in the options container.

Example

from lodum import lodum, field
from lodum.validators import OneOf

@lodum
class Order:
    status: str = field(validate=[OneOf(["pending", "processing", "shipped", "delivered"])])
    priority: int = Field(validators=[OneOf({1, 2, 3})])

# Valid
order = Order(status="pending", priority=1)

# Raises DeserializationError: "Value 'cancelled' is not one of [...]"
order = Order(status="cancelled", priority=1)

# Raises DeserializationError: "Value 5 is not one of {1, 2, 3}"
order = Order(status="pending", priority=5)

Combining Validators

Multiple validators can be applied to a single field:
from lodum import lodum, field
from lodum.validators import Length, Match

@lodum
class Account:
    password: str = field(validate=[
        Length(min=8, max=128),
        Match(r'^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).*$')  # Must contain uppercase, lowercase, and digit
    ])
Validators are executed in order, and the first validation failure raises DeserializationError.

Custom Validators

You can create custom validators by subclassing Validator:
from lodum import lodum, field
from lodum.validators import Validator
from lodum.exception import DeserializationError

class Even(Validator):
    def __call__(self, value: int) -> None:
        if value % 2 != 0:
            raise DeserializationError(f"Value {value} is not even")

@lodum
class EvenNumber:
    value: int = field(validate=[Even()])

Build docs developers (and LLMs) love