CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pydantic-core

Core functionality for Pydantic validation and serialization

Pending
Overview
Eval results
Files

special-values.mddocs/

Special Values and Utilities

Sentinel values, utility classes, and helper functions for advanced validation scenarios and edge case handling. These utilities provide fine-grained control over validation behavior and enable sophisticated data processing patterns.

Capabilities

Sentinel Values

Special values that represent different states during validation and serialization.

PydanticUndefined: PydanticUndefinedType
"""
Sentinel value representing undefined/missing values in Pydantic Core.

This is the primary sentinel value used internally by pydantic-core
to indicate when a value has not been provided or is undefined.
"""

class PydanticUndefinedType:
    """
    Type class for the PydanticUndefined sentinel.
    
    This type ensures PydanticUndefined has a unique type that can
    be used in type annotations and isinstance checks.
    """
    
    def __repr__(self) -> str:
        return 'PydanticUndefined'
    
    def __bool__(self) -> bool:
        return False

MISSING: Sentinel
"""
Sentinel indicating a field value was not provided during validation.

Can be used as a default value alternative to None when None has
explicit meaning. During serialization, fields with MISSING are excluded.
"""

UNSET: Sentinel  # Alias for MISSING
"""
Alternative name for MISSING sentinel value.

Provides a more explicit name when indicating that a field
has not been set or provided.
"""

Utility Classes

Helper classes for advanced validation and data handling scenarios.

class Some:
    """
    Wrapper for optional values that distinguishes between None and undefined.
    
    Useful when you need to differentiate between an explicit None value
    and a missing/undefined value in validation contexts.
    """
    
    def __init__(self, value):
        """
        Create a Some wrapper around a value.
        
        Args:
            value: The value to wrap (can be None)
        """
        self.value = value
    
    def __repr__(self) -> str:
        return f'Some({self.value!r})'

class ArgsKwargs:
    """
    Container for function arguments and keyword arguments.
    
    Used in advanced validation scenarios where you need to capture
    and validate both positional and keyword arguments together.
    """
    
    def __init__(self, args: tuple, kwargs: dict):
        """
        Create an ArgsKwargs container.
        
        Args:
            args: Tuple of positional arguments
            kwargs: Dictionary of keyword arguments
        """
        self.args = args
        self.kwargs = kwargs
    
    def __repr__(self) -> str:
        return f'ArgsKwargs({self.args!r}, {self.kwargs!r})'

Marker Classes

Special marker classes used to control validation and serialization behavior.

class PydanticOmit:
    """
    Marker to omit fields during serialization.
    
    When a field value is set to PydanticOmit (or a validator returns it),
    the field will be excluded from serialization output.
    """
    
    def __repr__(self) -> str:
        return 'PydanticOmit'

class PydanticUseDefault:
    """
    Marker to use default value during validation.
    
    When a validator returns PydanticUseDefault, the validation process
    will use the field's default value instead of the returned marker.
    """
    
    def __repr__(self) -> str:
        return 'PydanticUseDefault'

Time and Timezone Utilities

class TzInfo:
    """
    Timezone information handling for datetime validation.
    
    Provides timezone-aware datetime processing and validation
    with support for various timezone representations.
    """
    
    def __repr__(self) -> str:
        return 'TzInfo(...)'

Usage Examples

Working with Sentinel Values

from pydantic_core import SchemaValidator, MISSING, UNSET, PydanticUndefined
from pydantic_core.core_schema import dict_schema, str_schema, default_schema

# Schema with optional fields using sentinels
schema = dict_schema({
    'name': str_schema(),
    'nickname': default_schema(str_schema(), default=MISSING),
    'email': default_schema(str_schema(), default=UNSET),
    'phone': default_schema(str_schema(), default=PydanticUndefined)
})

validator = SchemaValidator(schema)

# Test data without optional fields
data = {'name': 'Alice'}
result = validator.validate_python(data)

print(f"Result: {result}")
print(f"Nickname: {result.get('nickname', 'NOT_FOUND')}")
print(f"Email: {result.get('email', 'NOT_FOUND')}")
print(f"Phone: {result.get('phone', 'NOT_FOUND')}")

# Check sentinel values
print(f"MISSING is UNSET: {MISSING is UNSET}")  # True - they're aliases
print(f"MISSING == PydanticUndefined: {MISSING == PydanticUndefined}")  # False

# Type checking
print(f"Type of PydanticUndefined: {type(PydanticUndefined)}")
print(f"isinstance(PydanticUndefined, PydanticUndefinedType): {isinstance(PydanticUndefined, type(PydanticUndefined))}")

Using Some for Optional Values

from pydantic_core import SchemaValidator, Some
from pydantic_core.core_schema import (
    with_info_plain_validator_function,
    union_schema,
    none_schema,
    str_schema
)

def validate_optional_with_some(value):
    """Validator that distinguishes None from missing."""
    if isinstance(value, Some):
        # Extract the wrapped value, even if it's None
        return value.value
    elif value is None:
        # Explicit None
        return None
    else:
        # Regular value
        if not isinstance(value, str):
            raise ValueError("Expected string or Some(value)")
        return value

# Schema using Some
optional_schema = with_info_plain_validator_function(validate_optional_with_some)
validator = SchemaValidator(optional_schema)

# Test different values
test_values = [
    "regular_string",
    None,
    Some("wrapped_string"),
    Some(None),  # Explicit None wrapped in Some
]

for value in test_values:
    try:
        result = validator.validate_python(value)
        print(f"Input: {value} -> Output: {result}")
    except Exception as e:
        print(f"Input: {value} -> Error: {e}")

Using ArgsKwargs for Function Validation

from pydantic_core import SchemaValidator, ArgsKwargs
from pydantic_core.core_schema import (
    with_info_plain_validator_function,
    arguments_schema,
    str_schema,
    int_schema
)

def validate_function_call(value):
    """Validate function arguments structure."""
    if isinstance(value, ArgsKwargs):
        args, kwargs = value.args, value.kwargs
    elif isinstance(value, dict) and 'args' in value and 'kwargs' in value:
        args, kwargs = value['args'], value['kwargs']
    else:
        raise ValueError("Expected ArgsKwargs or dict with 'args' and 'kwargs'")
    
    # Validate arguments
    if len(args) < 1:
        raise ValueError("At least one positional argument required")
    
    if not isinstance(args[0], str):
        raise ValueError("First argument must be a string")
    
    # Return validated ArgsKwargs
    return ArgsKwargs(args, kwargs)

# Create validator
func_validator = SchemaValidator(
    with_info_plain_validator_function(validate_function_call)
)

# Test function call validation
test_calls = [
    ArgsKwargs(("hello",), {"count": 3}),
    {"args": ("world",), "kwargs": {"repeat": True}},
    ArgsKwargs((), {"name": "test"}),  # Invalid: no args
]

for call in test_calls:
    try:
        result = func_validator.validate_python(call)
        print(f"Valid call: {result}")
        print(f"  Args: {result.args}")
        print(f"  Kwargs: {result.kwargs}")
    except Exception as e:
        print(f"Invalid call: {e}")

Marker Classes for Serialization Control

from pydantic_core import (
    SchemaValidator, 
    SchemaSerializer, 
    PydanticOmit, 
    PydanticUseDefault
)
from pydantic_core.core_schema import (
    dict_schema, 
    str_schema, 
    int_schema,
    with_info_plain_validator_function,
    default_schema
)

def process_field_value(value):
    """Validator that may omit fields or use defaults."""
    if isinstance(value, str):
        if value == "OMIT":
            return PydanticOmit  # This field will be excluded
        elif value == "DEFAULT":
            return PydanticUseDefault  # Use the field's default value
        elif value.startswith("PROCESS:"):
            return value[8:]  # Remove "PROCESS:" prefix
    return value

# Schema with conditional processing
schema = dict_schema({
    'id': int_schema(),
    'name': with_info_plain_validator_function(process_field_value),
    'description': default_schema(
        with_info_plain_validator_function(process_field_value),
        default="Default description"
    ),
    'status': with_info_plain_validator_function(process_field_value)
})

validator = SchemaValidator(schema)
serializer = SchemaSerializer(schema)

# Test data with markers
test_data = {
    'id': 123,
    'name': 'PROCESS:Alice',    # Will become 'Alice'
    'description': 'DEFAULT',   # Will use default value
    'status': 'OMIT'           # Will be omitted from output
}

# Validate
validated = validator.validate_python(test_data)
print(f"Validated: {validated}")

# Serialize - status should be omitted
serialized = serializer.to_python(validated)
print(f"Serialized: {serialized}")

# Check what fields are present
print(f"Fields in result: {list(serialized.keys())}")
print(f"Status omitted: {'status' not in serialized}")

Advanced Sentinel Usage in Models

from pydantic_core import SchemaValidator, SchemaSerializer, MISSING
from pydantic_core.core_schema import (
    model_schema, 
    str_schema, 
    int_schema, 
    default_schema,
    nullable_schema
)

# User model with various optional field types
user_schema = model_schema(
    'User',
    {
        'id': int_schema(),
        'name': str_schema(),
        'email': nullable_schema(str_schema()),  # Can be None
        'phone': default_schema(str_schema(), default=MISSING),  # Missing by default
        'address': default_schema(nullable_schema(str_schema()), default=None),  # None by default
    }
)

validator = SchemaValidator(user_schema)
serializer = SchemaSerializer(user_schema)

# Test different scenarios
test_users = [
    # Minimal user
    {'id': 1, 'name': 'Alice', 'email': None},
    
    # User with phone
    {'id': 2, 'name': 'Bob', 'email': 'bob@example.com', 'phone': '123-456-7890'},
    
    # User with all fields
    {'id': 3, 'name': 'Charlie', 'email': 'charlie@example.com', 'phone': '098-765-4321', 'address': '123 Main St'},
]

for user_data in test_users:
    print(f"\nInput: {user_data}")
    
    # Validate
    validated = validator.validate_python(user_data)
    print(f"Validated: {validated}")
    
    # Serialize excluding unset fields
    serialized_exclude_unset = serializer.to_python(validated, exclude_unset=True)
    print(f"Exclude unset: {serialized_exclude_unset}")
    
    # Serialize excluding None values
    serialized_exclude_none = serializer.to_python(validated, exclude_none=True)
    print(f"Exclude None: {serialized_exclude_none}")

Creating Custom Sentinel Values

from typing_extensions import Sentinel

# Create custom sentinel values for specific use cases
REDACTED = Sentinel('REDACTED')
COMPUTED = Sentinel('COMPUTED')
INHERITED = Sentinel('INHERITED')

def process_config_value(value):
    """Process configuration values with custom sentinels."""
    if value is REDACTED:
        return "[REDACTED]"
    elif value is COMPUTED:
        return f"computed_value_{hash('config')}"
    elif value is INHERITED:
        return "inherited_from_parent"
    else:
        return value

# Example usage in configuration processing
config_data = {
    'api_key': REDACTED,
    'cache_size': COMPUTED,
    'log_level': INHERITED,
    'service_name': 'my-service'
}

processed_config = {
    key: process_config_value(value)
    for key, value in config_data.items()
}

print("Original config:")
for key, value in config_data.items():
    print(f"  {key}: {value}")

print("\nProcessed config:")
for key, value in processed_config.items():
    print(f"  {key}: {value}")

# Sentinel comparison
print(f"\nSentinel comparisons:")
print(f"REDACTED is REDACTED: {REDACTED is REDACTED}")
print(f"REDACTED == REDACTED: {REDACTED == REDACTED}")
print(f"REDACTED is COMPUTED: {REDACTED is COMPUTED}")

Install with Tessl CLI

npx tessl i tessl/pypi-pydantic-core

docs

error-handling.md

index.md

json-processing.md

schema-building.md

special-values.md

url-network.md

validation-serialization.md

tile.json