from pydantic import BaseModel, root_validator, validator
from typing import Optional, Union, List, Dict, Any
from datetime import datetime, date
import json
class ConditionalValidation(BaseModel):
"""Model with complex conditional validation logic"""
user_type: str = Field(..., regex=r'^(admin|user|guest)$')
permissions: List[str] = Field(default_factory=list)
access_level: int = Field(..., ge=1, le=10)
# Conditional fields
admin_key: Optional[str] = None
department: Optional[str] = None
temp_access_expires: Optional[datetime] = None
@root_validator
def validate_user_permissions(cls, values):
user_type = values.get('user_type')
permissions = values.get('permissions', [])
access_level = values.get('access_level')
if user_type == 'admin':
# Admin must have admin_key
if not values.get('admin_key'):
raise ValueError('admin_key is required for admin users')
# Admin must have department
if not values.get('department'):
raise ValueError('department is required for admin users')
# Admin access level must be 7+
if access_level < 7:
raise ValueError('Admin users must have access level 7 or higher')
elif user_type == 'guest':
# Guest must have expiration
if not values.get('temp_access_expires'):
raise ValueError('temp_access_expires is required for guest users')
# Guest access level limited
if access_level > 3:
raise ValueError('Guest users cannot have access level above 3')
# Validate expiration is in future
expires = values.get('temp_access_expires')
if expires and expires <= datetime.utcnow():
raise ValueError('temp_access_expires must be in the future')
# Validate permissions based on access level
max_permissions = {
1: ['read'],
2: ['read', 'write'],
3: ['read', 'write', 'delete'],
4: ['read', 'write', 'delete', 'create'],
5: ['read', 'write', 'delete', 'create', 'modify'],
}
allowed_perms = []
for level in range(1, access_level + 1):
allowed_perms.extend(max_permissions.get(level, []))
invalid_perms = set(permissions) - set(allowed_perms)
if invalid_perms:
raise ValueError(f'Permissions {invalid_perms} not allowed for access level {access_level}')
return values
class DynamicModel(BaseModel):
"""Model that handles dynamic/flexible schemas"""
schema_version: str = Field(..., regex=r'^\d+\.\d+$')
data: Dict[str, Any]
@validator('data')
def validate_data_by_schema(cls, v, values):
schema_version = values.get('schema_version')
if schema_version == '1.0':
return cls._validate_v1_schema(v)
elif schema_version == '2.0':
return cls._validate_v2_schema(v)
else:
raise ValueError(f'Unsupported schema version: {schema_version}')
@classmethod
def _validate_v1_schema(cls, data):
required_fields = ['name', 'age']
for field in required_fields:
if field not in data:
raise ValueError(f'Missing required field: {field}')
if not isinstance(data['age'], int) or data['age'] < 0:
raise ValueError('age must be a positive integer')
return data
@classmethod
def _validate_v2_schema(cls, data):
required_fields = ['full_name', 'birth_date', 'email']
for field in required_fields:
if field not in data:
raise ValueError(f'Missing required field: {field}')
# Validate birth_date format
try:
datetime.strptime(data['birth_date'], '%Y-%m-%d')
except ValueError:
raise ValueError('birth_date must be in YYYY-MM-DD format')
return data