CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-voluptuous

Python data validation library for validating nested data structures with comprehensive error reporting

Pending
Overview
Eval results
Files

utility-transformers.mddocs/

Utility Transformers

String transformation utilities, default value handling, value setting, and collection conversion utilities. These transformers modify data during validation rather than just validating it.

Capabilities

String Transformation

Functions that transform strings while validating them.

def Lower(v):
    """
    Transform string to lowercase.
    
    Parameters:
    - v: String to transform
    
    Returns:
    Lowercase version of input string
    
    Raises:
    Invalid: If input cannot be converted to string
    """

def Upper(v):
    """
    Transform string to uppercase.
    
    Parameters:
    - v: String to transform
    
    Returns:
    Uppercase version of input string
    
    Raises:
    Invalid: If input cannot be converted to string
    """

def Capitalize(v):
    """
    Capitalize first letter of string.
    
    Parameters:
    - v: String to transform
    
    Returns:
    String with first letter capitalized, rest lowercase
    
    Raises:
    Invalid: If input cannot be converted to string
    """

def Title(v):
    """
    Transform string to title case (each word capitalized).
    
    Parameters:
    - v: String to transform
    
    Returns:
    String in title case
    
    Raises:
    Invalid: If input cannot be converted to string
    """

def Strip(v):
    """
    Remove leading and trailing whitespace from string.
    
    Parameters:
    - v: String to transform
    
    Returns:
    String with whitespace stripped
    
    Raises:
    Invalid: If input cannot be converted to string
    """

Usage Examples:

from voluptuous import Schema, All, Lower, Upper, Capitalize, Title, Strip, Length

# Data normalization
user_schema = Schema({
    'username': All(str, Strip, Lower),           # Clean and lowercase username
    'name': All(str, Strip, Title),               # Clean and title case name
    'email': All(str, Strip, Lower),              # Clean and lowercase email
    'country': All(str, Strip, Upper),            # Clean and uppercase country code
})

# Text processing pipeline
text_processor = All(
    str,                          # Ensure string
    Strip,                        # Remove whitespace
    lambda s: s if s else None,   # Convert empty strings to None
)

# Combined with validation
clean_name = All(
    str,
    Strip,                        # Remove whitespace
    Title,                        # Title case
    Length(min=1, max=100),       # Validate length
)

# Usage examples:
user_schema({
    'username': '  JohnDoe  ',    # -> 'johndoe'
    'name': '  john doe  ',       # -> 'John Doe'
    'email': '  JOHN@EXAMPLE.COM  ',  # -> 'john@example.com'
    'country': '  usa  ',         # -> 'USA'
})

Default Value Handling

Set default values when input is None or missing.

class DefaultTo:
    def __init__(self, default_value, msg=None):
        """
        Set default value when input is None.
        
        Parameters:
        - default_value: Value to use when input is None (can be callable for factory)
        - msg: Custom error message (rarely used)
        
        Returns:
        Input value if not None, otherwise default_value (or result of calling it)
        
        Note:
        If default_value is callable, it will be called each time to generate the default
        """

Usage Examples:

from voluptuous import Schema, DefaultTo, Required, Optional

# Simple default values
config_schema = Schema({
    Required('host', default='localhost'): str,    # Default host
    Required('port', default=8080): int,           # Default port
    Required('debug', default=False): bool,        # Default debug mode
})

# Factory functions for dynamic defaults
import datetime

session_schema = Schema({
    'user_id': str,
    'created_at': DefaultTo(datetime.datetime.now),  # Current time as default
    'expires_at': DefaultTo(lambda: datetime.datetime.now() + datetime.timedelta(hours=24)),
    'permissions': DefaultTo(list),                   # Empty list as default
    'metadata': DefaultTo(dict),                      # Empty dict as default
})

# Conditional defaults
def default_config():
    return {'theme': 'light', 'language': 'en'}

user_prefs_schema = Schema({
    'username': str,
    'config': DefaultTo(default_config),              # Function returns dict
})

# Usage examples:
config_schema({'host': None})  # -> {'host': 'localhost', 'port': 8080, 'debug': False}
session_schema({'user_id': '123'})  # Adds timestamps and empty collections

Value Setting

Always set specific values regardless of input.

class SetTo:
    def __init__(self, value):
        """
        Always set to specific value, ignoring input.
        
        Parameters:
        - value: Value to always return (can be callable for factory)
        
        Returns:
        The specified value (or result of calling it if callable)
        
        Note:
        Completely ignores the input value
        """

Usage Examples:

from voluptuous import Schema, SetTo, Any, All
import uuid
import datetime

# Always set specific values
audit_schema = Schema({
    'data': dict,                              # User data
    'created_by': SetTo('system'),             # Always 'system'
    'created_at': SetTo(datetime.datetime.now), # Always current time
    'id': SetTo(lambda: str(uuid.uuid4())),    # Always new UUID
    'version': SetTo(1),                       # Always version 1
})

# Conditional value setting
def status_based_priority(data):
    if data.get('status') == 'urgent':
        return SetTo(1)  # High priority
    elif data.get('status') == 'low':
        return SetTo(5)  # Low priority
    else:
        return SetTo(3)  # Medium priority

task_schema = Schema({
    'title': str,
    'status': str,
    'priority': status_based_priority,         # Set based on status
})

# Default or override pattern
flexible_schema = Schema({
    'name': str,
    'type': Any(str, SetTo('default')),        # Use provided or default to 'default'
})

# Usage examples:
audit_result = audit_schema({'data': {'key': 'value'}})
# Result includes system-generated fields regardless of input

task_result = task_schema({'title': 'Fix bug', 'status': 'urgent'})
# Result: {'title': 'Fix bug', 'status': 'urgent', 'priority': 1}

Collection Conversion

Convert between different collection types.

class Set:
    def __init__(self, msg=None):
        """
        Convert iterable to Python set.
        
        Parameters:
        - msg: Custom error message if conversion fails
        
        Returns:
        Set containing unique elements from input iterable
        
        Raises:
        TypeInvalid: If input cannot be converted to set (not iterable or contains unhashable types)
        """

Usage Examples:

from voluptuous import Schema, Set, All, Length

# Remove duplicates by converting to set
unique_tags_schema = Schema({
    'tags': All([str], Set()),     # Convert list to set (removes duplicates)
})

# Validate set properties
permissions_schema = Schema(All(
    [str],                         # Start with list of strings
    Set(),                         # Convert to set
    lambda s: len(s) >= 2,        # Must have at least 2 unique permissions
))

# Combined with other validation
category_schema = Schema(All(
    [str],                         # List of strings
    lambda lst: [s.strip().lower() for s in lst],  # Normalize
    Set(),                         # Remove duplicates
    lambda s: len(s) <= 10,       # Max 10 unique categories
))

# Usage examples:
unique_tags_schema({'tags': ['python', 'web', 'python', 'api']})
# Result: {'tags': {'python', 'web', 'api'}}

permissions_schema(['read', 'write', 'read', 'admin'])
# Result: {'read', 'write', 'admin'}

Literal Value Matching

Validate exact literal values with custom comparison.

class Literal:
    def __init__(self, lit):
        """
        Validate exact literal value match.
        
        Parameters:
        - lit: Literal value that input must exactly match
        
        Returns:
        The literal value if input matches exactly
        
        Raises:
        LiteralInvalid: If input doesn't match literal value exactly
        """

Usage Examples:

from voluptuous import Schema, Literal, Any

# API version validation
api_schema = Schema({
    'version': Literal('v1'),                  # Must be exactly 'v1'
    'format': Literal('json'),                 # Must be exactly 'json'
})

# Multiple literal options
status_schema = Schema({
    'status': Any(
        Literal('active'),
        Literal('inactive'),
        Literal('pending'),
    ),
})

# Configuration flags
feature_flags = Schema({
    'new_ui': Any(Literal(True), Literal(False)),     # Boolean literals
    'api_version': Any(Literal(1), Literal(2)),       # Integer literals
    'mode': Any(Literal('dev'), Literal('prod')),     # String literals
})

# Null/None validation
nullable_field = Schema({
    'optional_field': Any(str, Literal(None)),        # String or exactly None
})

# Usage examples:
api_schema({'version': 'v1', 'format': 'json'})      # Valid
# api_schema({'version': 'v2', 'format': 'json'})    # Invalid - wrong version

status_schema({'status': 'active'})                   # Valid
feature_flags({'new_ui': True, 'api_version': 1, 'mode': 'prod'})  # Valid

Transformation Pipelines

Complex data transformation patterns using multiple transformers.

Text Normalization Pipeline:

from voluptuous import Schema, All, Strip, Lower, Replace, Length
import re

# Complete text normalization
normalize_text = All(
    str,                          # Ensure string
    Strip,                        # Remove leading/trailing whitespace
    lambda s: re.sub(r'\s+', ' ', s),  # Normalize internal whitespace
    Lower,                        # Convert to lowercase
    lambda s: s if s else None,   # Convert empty strings to None
)

# URL slug generation
create_slug = All(
    str,
    Strip,
    Lower,
    Replace(r'[^\w\s-]', ''),     # Remove special characters
    Replace(r'\s+', '-'),         # Replace spaces with hyphens
    Replace(r'-+', '-'),          # Collapse multiple hyphens
    lambda s: s.strip('-'),       # Remove leading/trailing hyphens
)

# Usage:
normalize_text('  Hello   World  ')  # -> 'hello world'
create_slug('My Blog Post Title!')   # -> 'my-blog-post-title'

Data Cleaning Pipeline:

from voluptuous import Schema, All, DefaultTo, Strip, Coerce

# Clean and validate user input
clean_user_data = Schema({
    'name': All(str, Strip, DefaultTo('Anonymous')),
    'age': All(Any(int, str), Coerce(int), Range(min=0, max=150)),
    'email': All(str, Strip, Lower, Any(Email(), DefaultTo(None))),
    'tags': All(
        Any(list, str),           # Accept list or comma-separated string
        lambda x: x.split(',') if isinstance(x, str) else x,  # Split if string
        [All(str, Strip)],        # Clean each tag
        lambda tags: [t for t in tags if t],  # Remove empty tags
        Set(),                    # Remove duplicates
    ),
})

Configuration Processing:

from voluptuous import Schema, All, DefaultTo, Coerce, Any

# Process configuration with defaults and coercion
config_processor = Schema({
    'database': {
        'host': All(str, Strip, DefaultTo('localhost')),
        'port': All(Any(int, str), Coerce(int), Range(min=1024, max=65535), DefaultTo(5432)),
        'name': All(str, Strip),
        'ssl': All(Any(bool, str), Boolean, DefaultTo(True)),
    },
    'cache': {
        'enabled': All(Any(bool, str), Boolean, DefaultTo(False)),
        'ttl': All(Any(int, str), Coerce(int), Range(min=1), DefaultTo(3600)),
    },
    'features': All(
        Any([str], str),          # List or comma-separated string
        lambda x: x.split(',') if isinstance(x, str) else x,
        [All(str, Strip, Lower)], # Normalize feature names
        Set(),                    # Remove duplicates
        DefaultTo(set()),         # Default to empty set
    ),
})

Flexible Data Transformation:

from voluptuous import Schema, All, Any, SetTo

def smart_transform(field_name, transforms):
    """Apply different transformations based on field name or value."""
    def transformer(value):
        for condition, transform in transforms:
            if condition(field_name, value):
                return transform(value)
        return value
    return transformer

# Dynamic field processing
dynamic_schema = Schema({
    'username': smart_transform('username', [
        (lambda f, v: isinstance(v, str), All(Strip, Lower)),
        (lambda f, v: True, SetTo('anonymous')),  # Fallback
    ]),
    'created_at': smart_transform('created_at', [
        (lambda f, v: v is None, SetTo(datetime.datetime.now)),
        (lambda f, v: isinstance(v, str), lambda s: datetime.datetime.fromisoformat(s)),
        (lambda f, v: True, lambda x: x),  # Pass through
    ]),
})

Install with Tessl CLI

npx tessl i tessl/pypi-voluptuous

docs

core-schema.md

error-handling.md

index.md

range-collection-validators.md

string-pattern-validators.md

type-validators.md

utility-transformers.md

validation-composers.md

tile.json