Web Error Handling Python Samples

Web Python error handling examples including exception catching, logging, and parameter validation

Key Facts

Category
Python
Items
3
Format Families
audio

Sample Overview

Web Python error handling examples including exception catching, logging, and parameter validation This sample set belongs to Python and can be used to test related workflows inside Elysia Tools.

💻 Exception Catching python

🟢 simple ⭐⭐

Handle exceptions using try-except blocks with multiple exception types, else/finally blocks, and exception chaining

⏱️ 25 min 🏷️ python, web, error handling, exception
Prerequisites: Basic Python, exception handling
# Web Python Exception Catching Examples
# Comprehensive exception handling patterns

# 1. Basic Try-Except
from typing import Optional, Any
import sys

def divide_basic(a: float, b: float) -> Optional[float]:
    """
    Basic division with exception handling

    Args:
        a: Numerator
        b: Denominator

    Returns:
        Result or None if error
    """
    try:
        return a / b
    except ZeroDivisionError:
        print("Error: Division by zero")
        return None

def safe_divide(a: float, b: float) -> float:
    """
    Safe division with custom error message

    Args:
        a: Numerator
        b: Denominator

    Returns:
        Division result

    Raises:
        ValueError: If denominator is zero
    """
    if b == 0:
        raise ValueError("Denominator cannot be zero")
    return a / b

# 2. Multiple Except Blocks
def handle_multiple_exceptions(value: Any) -> str:
    """
    Handle multiple exception types

    Args:
        value: Input value of any type

    Returns:
        Result string or error message
    """
    try:
        result = int(value)
        return f"Converted to integer: {result}"
    except ValueError:
        return f"Error: '{value}' cannot be converted to integer"
    except TypeError:
        return f"Error: Invalid type {type(value)}"
    except Exception as e:
        return f"Unexpected error: {e}"

def parse_input(input_str: str) -> dict:
    """
    Parse input with multiple exception handlers

    Args:
        input_str: Input string

    Returns:
        Dictionary with parsed data
    """
    try:
        # Try to evaluate as expression
        result = eval(input_str)
        return {'type': 'expression', 'value': result}
    except SyntaxError:
        try:
            # Try to parse as JSON
            import json
            result = json.loads(input_str)
            return {'type': 'json', 'value': result}
        except json.JSONDecodeError:
            return {'type': 'string', 'value': input_str}
    except Exception as e:
        return {'type': 'error', 'value': str(e)}

# 3. Else and Finally Blocks
def process_file(filepath: str) -> Optional[str]:
    """
    Process file with finally block for cleanup

    Args:
        filepath: Path to file

    Returns:
        File content or None
    """
    file = None
    try:
        file = open(filepath, 'r')
        content = file.read()
        print(f"Successfully read {len(content)} characters")
        return content
    except FileNotFoundError:
        print(f"Error: File '{filepath}' not found")
        return None
    except IOError as e:
        print(f"Error reading file: {e}")
        return None
    else:
        print("File processing completed successfully")
        return content
    finally:
        if file:
            file.close()
            print("File closed")

def divide_with_logging(a: float, b: float) -> Optional[float]:
    """
    Division with logging in else block

    Args:
        a: Numerator
        b: Denominator

    Returns:
        Result or None
    """
    try:
        result = a / b
    except ZeroDivisionError:
        print("Division by zero occurred")
        return None
    else:
        print(f"Division successful: {a} / {b} = {result}")
        return result
    finally:
        print("Division attempt completed")

# 4. Specific Exception Handling
def handle_specific_errors(data: dict, key: str) -> Any:
    """
    Handle specific dictionary errors

    Args:
        data: Dictionary
        key: Key to access

    Returns:
        Value or default
    """
    try:
        return data[key]
    except KeyError:
        print(f"Key '{key}' not found")
        return None
    except TypeError:
        print("Error: data is not a dictionary")
        return None

def safe_list_access(lst: list, index: int) -> Optional[Any]:
    """
    Safe list access with error handling

    Args:
        lst: List
        index: Index to access

    Returns:
        Element or None
    """
    try:
        return lst[index]
    except IndexError:
        print(f"Index {index} out of range")
        return None
    except TypeError:
        print("Error: Invalid index type")
        return None

# 5. Exception Chaining
def chain_exceptions(value: str) -> int:
    """
    Demonstrate exception chaining

    Args:
        value: String to parse

    Returns:
        Parsed integer

    Raises:
        ValueError: With chained original exception
    """
    try:
        number = int(value)
        if number < 0:
            raise ValueError("Number must be positive")
        return number
    except ValueError as e:
        # Chain with original exception
        raise ValueError(f"Invalid input '{value}': {e}") from e

def nested_exception_handling(filepath: str) -> str:
    """
    Nested exception handling with chaining

    Args:
        filepath: File path

    Returns:
        File content

    Raises:
        IOError: With chained exception
    """
    try:
        try:
            with open(filepath, 'r') as f:
                return f.read()
        except FileNotFoundError as e:
            raise IOError(f"File not found: {filepath}") from e
    except IOError as e:
        raise IOError(f"Failed to read file: {filepath}") from e

# 6. Context Manager Exception Handling
def read_with_context_manager(filepath: str) -> Optional[str]:
    """
    Read file using context manager with exception handling

    Args:
        filepath: File path

    Returns:
        File content or None
    """
    try:
        with open(filepath, 'r') as f:
            return f.read()
    except FileNotFoundError:
        print(f"File '{filepath}' not found")
        return None
    except IOError as e:
        print(f"Error reading file: {e}")
        return None

class CustomFileManager:
    """Custom context manager for file operations"""

    def __init__(self, filepath: str, mode: str = 'r'):
        self.filepath = filepath
        self.mode = mode
        self.file = None

    def __enter__(self):
        try:
            self.file = open(self.filepath, self.mode)
            return self.file
        except IOError as e:
            print(f"Error opening file: {e}")
            raise

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.file:
            self.file.close()
        if exc_type is not None:
            print(f"Exception occurred: {exc_type.__name__}: {exc_val}")
            return False  # Re-raise exception
        return True

# 7. Custom Exceptions
class CustomError(Exception):
    """Base custom exception"""
    pass

class ValidationError(CustomError):
    """Validation error"""
    def __init__(self, message: str, field: str = None):
        self.field = field
        super().__init__(message)

class NotFoundError(CustomError):
    """Resource not found error"""
    pass

def validate_age(age: int) -> None:
    """
    Validate age with custom exception

    Args:
        age: Age to validate

    Raises:
        ValidationError: If age is invalid
    """
    if age < 0:
        raise ValidationError("Age cannot be negative", "age")
    if age > 150:
        raise ValidationError("Age seems unrealistic", "age")

def find_user(user_id: int) -> dict:
    """
    Find user with custom exception

    Args:
        user_id: User ID

    Returns:
        User data

    Raises:
        NotFoundError: If user not found
    """
    # Simulate user lookup
    users = {1: {'name': 'Alice'}, 2: {'name': 'Bob'}}

    if user_id not in users:
        raise NotFoundError(f"User {user_id} not found")

    return users[user_id]

# 8. Exception Suppression
def suppress_exception(func, *args, **kwargs) -> Optional[Any]:
    """
    Suppress exceptions from function call

    Args:
        func: Function to call
        *args: Positional arguments
        **kwargs: Keyword arguments

    Returns:
        Result or None
    """
    try:
        return func(*args, **kwargs)
    except Exception:
        return None

def safe_execute(func, *args, default=None, **kwargs) -> Any:
    """
    Execute function with default on exception

    Args:
        func: Function to call
        *args: Positional arguments
        default: Default value on exception
        **kwargs: Keyword arguments

    Returns:
        Result or default value
    """
    try:
        return func(*args, **kwargs)
    except Exception:
        return default

# 9. Exception Information
def get_exception_info() -> dict:
    """
    Get detailed exception information

    Returns:
        Dictionary with exception info
    """
    try:
        result = 1 / 0
    except Exception as e:
        return {
            'type': type(e).__name__,
            'message': str(e),
            'args': e.args,
            'traceback': sys.exc_info()[2]
        }

def log_exception(exc: Exception, context: str = "") -> None:
    """
    Log exception with context

    Args:
        exc: Exception object
        context: Additional context
    """
    import traceback

    print(f"Exception in {context}:")
    print(f"  Type: {type(exc).__name__}")
    print(f"  Message: {exc}")
    print(f"  Traceback:")
    traceback.print_exc()

# 10. Retry Pattern
def retry_on_exception(func, max_attempts: int = 3, exceptions: tuple = (Exception,)):
    """
    Retry function on exception

    Args:
        func: Function to retry
        max_attempts: Maximum number of attempts
        exceptions: Exception types to catch

    Returns:
        Function result

    Raises:
        Exception: If all attempts fail
    """
    import time

    for attempt in range(max_attempts):
        try:
            return func()
        except exceptions as e:
            if attempt == max_attempts - 1:
                raise
            print(f"Attempt {attempt + 1} failed, retrying...")
            time.sleep(1)

# Usage Examples
def demonstrate_exception_catching():
    print("=== Web Python Exception Catching Examples ===\n")

    # 1. Basic try-except
    print("--- 1. Basic Try-Except ---")
    print(divide_basic(10, 2))
    print(divide_basic(10, 0))

    # 2. Multiple exceptions
    print("\n--- 2. Multiple Exception Types ---")
    print(handle_multiple_exceptions("42"))
    print(handle_multiple_exceptions("abc"))
    print(handle_multiple_exceptions(None))

    # 3. Else and finally
    print("\n--- 3. Else and Finally Blocks ---")
    print("Note: File operations in examples")
    print("# Example structure:")
    print("try:")
    print("    result = risky_operation()")
    print("except SpecificError:")
    print("    handle_error()")
    print("else:")
    print("    print('Success!')")
    print("finally:")
    print("    cleanup()")

    # 4. Specific exceptions
    print("\n--- 4. Specific Exception Handling ---")
    data = {'name': 'Alice', 'age': 30}
    print(handle_specific_errors(data, 'name'))
    print(handle_specific_errors(data, 'email'))
    print(safe_list_access([1, 2, 3], 1))
    print(safe_list_access([1, 2, 3], 10))

    # 5. Exception chaining
    print("\n--- 5. Exception Chaining ---")
    try:
        chain_exceptions("-5")
    except ValueError as e:
        print(f"Chained error: {e}")
        print(f"Original cause: {e.__cause__}")

    # 6. Custom exceptions
    print("\n--- 6. Custom Exceptions ---")
    try:
        validate_age(-5)
    except ValidationError as e:
        print(f"Validation error: {e} (field: {e.field})")

    try:
        find_user(999)
    except NotFoundError as e:
        print(f"Not found: {e}")

    # 7. Exception suppression
    print("\n--- 7. Exception Suppression ---")
    print(f"Suppress: {suppress_exception(lambda: 1/0)}")
    print(f"Safe execute: {safe_execute(lambda: 1/0, default='Error handled')}")

    # 8. Exception info
    print("\n--- 8. Exception Information ---")
    info = get_exception_info()
    print(f"Exception type: {info['type']}")
    print(f"Message: {info['message']}")

    # 9. Retry pattern
    print("\n--- 9. Retry Pattern ---")
    attempts = 0
    def failing_func():
        nonlocal attempts
        attempts += 1
        if attempts < 3:
            raise ValueError("Not yet!")
        return "Success!"

    result = retry_on_exception(failing_func)
    print(f"Retry result: {result}")

    print("\n=== All Exception Catching Examples Completed ===")

# Export functions
# export { divide_basic, safe_divide }
# export { handle_multiple_exceptions, parse_input }
# export { process_file, divide_with_logging }
# export { handle_specific_errors, safe_list_access }
# export { chain_exceptions, nested_exception_handling }
# export { read_with_context_manager, CustomFileManager }
# export { ValidationError, NotFoundError, validate_age, find_user }
# export { suppress_exception, safe_execute }
# export { get_exception_info, log_exception }
# export { retry_on_exception }
# export { demonstrate_exception_catching }

💻 Logging python

🟡 intermediate ⭐⭐⭐

Implement comprehensive logging with different levels, formats, file handlers, and log rotation

⏱️ 30 min 🏷️ python, web, error handling, logging
Prerequisites: Intermediate Python, logging module
# Web Python Logging Examples
# Comprehensive logging system implementation

# 1. Basic Logging
import logging
from typing import Optional
import sys
from datetime import datetime
import os

def setup_basic_logging():
    """Configure basic logging to console"""
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(levelname)s - %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S'
    )

def basic_logging_examples():
    """Demonstrate basic logging levels"""
    logging.debug("This is a debug message")
    logging.info("This is an info message")
    logging.warning("This is a warning message")
    logging.error("This is an error message")
    logging.critical("This is a critical message")

# 2. Custom Logger
def create_logger(name: str, level: int = logging.INFO) -> logging.Logger:
    """
    Create custom logger

    Args:
        name: Logger name
        level: Logging level

    Returns:
        Logger instance
    """
    logger = logging.getLogger(name)
    logger.setLevel(level)

    # Avoid duplicate handlers
    if not logger.handlers:
        # Console handler
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setLevel(level)

        # Formatter
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S'
        )
        console_handler.setFormatter(formatter)

        logger.addHandler(console_handler)

    return logger

# 3. File Logging
def setup_file_logging(filepath: str, level: int = logging.INFO) -> logging.Logger:
    """
    Setup file logging

    Args:
        filepath: Log file path
        level: Logging level

    Returns:
        Logger instance
    """
    # Create directory if needed
    os.makedirs(os.path.dirname(filepath) or '.', exist_ok=True)

    logger = logging.getLogger('file_logger')
    logger.setLevel(level)

    # Remove existing handlers
    logger.handlers.clear()

    # File handler
    file_handler = logging.FileHandler(filepath)
    file_handler.setLevel(level)

    # Formatter
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s'
    )
    file_handler.setFormatter(formatter)

    logger.addHandler(file_handler)

    return logger

def setup_dual_logging(log_file: str, console_level: int = logging.INFO, file_level: int = logging.DEBUG) -> logging.Logger:
    """
    Setup both console and file logging

    Args:
        log_file: Log file path
        console_level: Console logging level
        file_level: File logging level

    Returns:
        Logger instance
    """
    logger = logging.getLogger('dual_logger')
    logger.setLevel(logging.DEBUG)

    logger.handlers.clear()

    # Console handler
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setLevel(console_level)
    console_formatter = logging.Formatter('%(levelname)s: %(message)s')
    console_handler.setFormatter(console_formatter)
    logger.addHandler(console_handler)

    # File handler
    file_handler = logging.FileHandler(log_file)
    file_handler.setLevel(file_level)
    file_formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s'
    )
    file_handler.setFormatter(file_formatter)
    logger.addHandler(file_handler)

    return logger

# 4. Log Levels
def log_all_levels(logger: logging.Logger):
    """
    Log messages at all levels

    Args:
        logger: Logger instance
    """
    logger.debug("Debug message - detailed information for diagnosing problems")
    logger.info("Info message - confirmation that things are working as expected")
    logger.warning("Warning message - something unexpected happened")
    logger.error("Error message - serious problem occurred")
    logger.critical("Critical message - serious error, program may be unable to continue")

# 5. Formatted Logging
def setup_formatted_logging(format_string: str) -> logging.Logger:
    """
    Setup logging with custom format

    Args:
        format_string: Custom format string

    Returns:
        Logger instance
    """
    logger = logging.getLogger('formatted_logger')
    logger.setLevel(logging.INFO)

    logger.handlers.clear()

    handler = logging.StreamHandler(sys.stdout)
    formatter = logging.Formatter(format_string)
    handler.setFormatter(formatter)
    logger.addHandler(handler)

    return logger

def get_format_examples() -> dict:
    """Get example format strings"""
    return {
        'simple': '%(levelname)s: %(message)s',
        'detailed': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        'verbose': '%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s',
        'json': '{"time": "%(asctime)s", "level": "%(levelname)s", "message": "%(message)s"}'
    }

# 6. Log Rotation
def setup_rotating_file_log(log_file: str, max_bytes: int = 1048576, backup_count: int = 5) -> logging.Logger:
    """
    Setup rotating file logging

    Args:
        log_file: Log file path
        max_bytes: Max file size before rotation
        backup_count: Number of backup files to keep

    Returns:
        Logger instance
    """
    from logging.handlers import RotatingFileHandler

    logger = logging.getLogger('rotating_logger')
    logger.setLevel(logging.INFO)

    logger.handlers.clear()

    handler = RotatingFileHandler(
        log_file,
        maxBytes=max_bytes,
        backupCount=backup_count
    )
    handler.setLevel(logging.INFO)

    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    handler.setFormatter(formatter)

    logger.addHandler(handler)

    return logger

def setup_time_based_rotation(log_file: str, when: str = 'midnight', interval: int = 1, backup_count: int = 7) -> logging.Logger:
    """
    Setup time-based log rotation

    Args:
        log_file: Log file path
        when: When to rotate ('S', 'M', 'H', 'D', 'midnight', 'W0-W6')
        interval: Rotation interval
        backup_count: Number of backups to keep

    Returns:
        Logger instance
    """
    from logging.handlers import TimedRotatingFileHandler

    logger = logging.getLogger('time_rotating_logger')
    logger.setLevel(logging.INFO)

    logger.handlers.clear()

    handler = TimedRotatingFileHandler(
        log_file,
        when=when,
        interval=interval,
        backupCount=backup_count
    )
    handler.setLevel(logging.INFO)

    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    handler.setFormatter(formatter)

    logger.addHandler(handler)

    return logger

# 7. Structured Logging
class StructuredLogger:
    """Structured logger with contextual information"""

    def __init__(self, name: str):
        self.logger = logging.getLogger(name)
        self.logger.setLevel(logging.INFO)
        if not self.logger.handlers:
            handler = logging.StreamHandler(sys.stdout)
            handler.setFormatter(logging.Formatter('%(message)s'))
            self.logger.addHandler(handler)

    def log(self, level: int, message: str, **context):
        """
        Log structured message

        Args:
            level: Log level
            message: Log message
            **context: Additional context
        """
        import json
        log_data = {
            'message': message,
            'timestamp': datetime.now().isoformat(),
            **context
        }
        self.logger.log(level, json.dumps(log_data))

    def debug(self, message: str, **context):
        """Log debug message"""
        self.log(logging.DEBUG, message, **context)

    def info(self, message: str, **context):
        """Log info message"""
        self.log(logging.INFO, message, **context)

    def warning(self, message: str, **context):
        """Log warning message"""
        self.log(logging.WARNING, message, **context)

    def error(self, message: str, **context):
        """Log error message"""
        self.log(logging.ERROR, message, **context)

# 8. Contextual Logging
class ContextualLogger:
    """Logger with automatic context"""

    def __init__(self, name: str, context: dict = None):
        self.logger = logging.getLogger(name)
        self.context = context or {}

    def with_context(self, **context) -> 'ContextualLogger':
        """Create new logger with additional context"""
        new_context = {**self.context, **context}
        return ContextualLogger(self.logger.name, new_context)

    def _log(self, level: int, message: str, **extra_context):
        """Log with context"""
        all_context = {**self.context, **extra_context}
        log_message = f"{message} | Context: {all_context}"
        self.logger.log(level, log_message)

    def info(self, message: str, **context):
        """Info level log"""
        self._log(logging.INFO, message, **context)

    def error(self, message: str, **context):
        """Error level log"""
        self._log(logging.ERROR, message, **context)

# 9. Exception Logging
def log_exception(logger: logging.Logger, exc: Exception, context: str = ""):
    """
    Log exception with traceback

    Args:
        logger: Logger instance
        exc: Exception object
        context: Additional context
    """
    logger.error(f"Exception in {context}: {exc}", exc_info=True)

def safe_execute_with_logging(logger: logging.Logger, func, *args, **kwargs):
    """
    Execute function with exception logging

    Args:
        logger: Logger instance
        func: Function to execute
        *args: Positional arguments
        **kwargs: Keyword arguments

    Returns:
        Function result or None
    """
    try:
        return func(*args, **kwargs)
    except Exception as e:
        log_exception(logger, e, f"function '{func.__name__}'")
        return None

# 10. Performance Logging
class PerformanceLogger:
    """Logger for performance monitoring"""

    def __init__(self, logger: logging.Logger):
        self.logger = logger
        self.start_times = {}

    def start(self, operation: str):
        """Start timing operation"""
        self.start_times[operation] = datetime.now()

    def end(self, operation: str):
        """End timing and log duration"""
        if operation in self.start_times:
            duration = (datetime.now() - self.start_times[operation]).total_seconds()
            self.logger.info(f"Operation '{operation}' completed in {duration:.3f}s")
            del self.start_times[operation]

# Usage Examples
def demonstrate_logging():
    print("=== Web Python Logging Examples ===\n")

    print("--- 1. Basic Logging ---")
    setup_basic_logging()
    basic_logging_examples()

    print("\n--- 2. Custom Logger ---")
    logger = create_logger('my_app', level=logging.DEBUG)
    logger.debug("Debug message")
    logger.info("Info message")
    logger.warning("Warning message")

    print("\n--- 3. File Logging ---")
    file_logger = setup_file_logging('app.log')
    file_logger.info("This goes to file")
    file_logger.error("Error in file")
    print("Check 'app.log' for file output")

    print("\n--- 4. Dual Logging ---")
    dual_logger = setup_dual_logging('dual.log')
    dual_logger.debug("Debug to file only")
    dual_logger.info("Info to both console and file")

    print("\n--- 5. Structured Logging ---")
    struct_logger = StructuredLogger('structured')
    struct_logger.info("User login", user_id=123, ip="192.168.1.1")
    struct_logger.error("Database error", error_code=500, query="SELECT * FROM users")

    print("\n--- 6. Contextual Logging ---")
    base_logger = ContextualLogger('app', context={'app': 'my_app', 'version': '1.0'})
    base_logger.info("Application started")
    request_logger = base_logger.with_context(request_id='abc123', user='alice')
    request_logger.info("Processing request")

    print("\n--- 7. Rotating File Handler ---")
    rotating_logger = setup_rotating_file_log('rotating.log', max_bytes=1024, backup_count=3)
    for i in range(100):
        rotating_logger.info(f"Log message {i}")
    print("Check 'rotating.log' for rotating output")

    print("\n--- 8. Exception Logging ---")
    try:
        1 / 0
    except Exception as e:
        log_exception(logger, e, "demonstration")

    print("\n--- 9. Performance Logging ---")
    perf_logger = PerformanceLogger(logger)
    perf_logger.start('data_processing')
    import time
    time.sleep(0.1)
    perf_logger.end('data_processing')

    print("\n=== All Logging Examples Completed ===")

# Export functions
# export { setup_basic_logging, basic_logging_examples }
# export { create_logger }
# export { setup_file_logging, setup_dual_logging }
# export { log_all_levels }
# export { setup_formatted_logging, get_format_examples }
# export { setup_rotating_file_log, setup_time_based_rotation }
# export { StructuredLogger }
# export { ContextualLogger }
# export { log_exception, safe_execute_with_logging }
# export { PerformanceLogger }
# export { demonstrate_logging }

💻 Parameter Validation python

🟡 intermediate ⭐⭐⭐

Validate function parameters using type checking, range validation, custom validators, and dataclasses

⏱️ 35 min 🏷️ python, web, error handling, validation
Prerequisites: Intermediate Python, decorators, dataclasses
# Web Python Parameter Validation Examples
# Comprehensive parameter validation techniques

# 1. Type Checking
from typing import Any, Optional, List, Type, get_type_hints
import re
from datetime import datetime
from dataclasses import dataclass
from enum import Enum

def validate_type(value: Any, expected_type: Type, param_name: str = "parameter") -> None:
    """
    Validate value type

    Args:
        value: Value to check
        expected_type: Expected type
        param_name: Parameter name for error message

    Raises:
        TypeError: If type mismatch
    """
    if not isinstance(value, expected_type):
        raise TypeError(f"{param_name} must be {expected_type.__name__}, got {type(value).__name__}")

def validate_types(**params) -> None:
    """
    Validate multiple parameters

    Args:
        **params: Parameter name and (value, type) tuples

    Raises:
        TypeError: If any type mismatch
    """
    for param_name, (value, expected_type) in params.items():
        validate_type(value, expected_type, param_name)

def typed_function(name: str, age: int, scores: List[float]) -> str:
    """
    Function with type validation

    Args:
        name: Person name (string)
        age: Person age (integer)
        scores: List of scores

    Returns:
        Formatted string

    Raises:
        TypeError: If any parameter has wrong type
    """
    validate_types(
        name=(name, str),
        age=(age, int),
        scores=(scores, list)
    )

    # Validate list elements
    for i, score in enumerate(scores):
        validate_type(score, float, f"scores[{i}]")

    return f"{name}, age {age}, scores: {scores}"

# 2. Range Validation
def validate_range(value: int, min_val: Optional[int] = None, max_val: Optional[int] = None, param_name: str = "parameter") -> None:
    """
    Validate numeric range

    Args:
        value: Value to check
        min_val: Minimum value (None = no minimum)
        max_val: Maximum value (None = no maximum)
        param_name: Parameter name

    Raises:
        ValueError: If out of range
    """
    if min_val is not None and value < min_val:
        raise ValueError(f"{param_name} must be >= {min_val}, got {value}")

    if max_val is not None and value > max_val:
        raise ValueError(f"{param_name} must be <= {max_val}, got {value}")

def validate_positive(value: int, param_name: str = "parameter") -> None:
    """Validate positive value"""
    validate_range(value, min_val=1, param_name=param_name)

def validate_non_negative(value: int, param_name: str = "parameter") -> None:
    """Validate non-negative value"""
    validate_range(value, min_val=0, param_name=param_name)

def validate_percentage(value: float, param_name: str = "parameter") -> None:
    """Validate percentage (0-100)"""
    validate_range(value, min_val=0, max_val=100, param_name=param_name)

def validate_length(value: List, min_length: Optional[int] = None, max_length: Optional[int] = None, param_name: str = "parameter") -> None:
    """
    Validate list length

    Args:
        value: List to check
        min_length: Minimum length
        max_length: Maximum length
        param_name: Parameter name
    """
    length = len(value)
    validate_range(length, min_length, max_length, f"{param_name} length")

# 3. String Validation
def validate_string_length(value: str, min_length: int = 0, max_length: Optional[int] = None, param_name: str = "parameter") -> None:
    """
    Validate string length

    Args:
        value: String to validate
        min_length: Minimum length
        max_length: Maximum length
        param_name: Parameter name
    """
    validate_type(value, str, param_name)
    validate_range(len(value), min_length, max_length, param_name)

def validate_email(value: str, param_name: str = "email") -> None:
    """
    Validate email format

    Args:
        value: Email string
        param_name: Parameter name

    Raises:
        ValueError: If invalid email format
    """
    validate_type(value, str, param_name)

    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    if not re.match(pattern, value):
        raise ValueError(f"{param_name} must be a valid email address")

def validate_url(value: str, param_name: str = "url") -> None:
    """
    Validate URL format

    Args:
        value: URL string
        param_name: Parameter name

    Raises:
        ValueError: If invalid URL format
    """
    validate_type(value, str, param_name)

    pattern = r'^https?://[a-zA-Z0-9.-]+(\.[a-zA-Z]{2,})?(/.*)?$'
    if not re.match(pattern, value):
        raise ValueError(f"{param_name} must be a valid URL")

def validate_regex(value: str, pattern: str, param_name: str = "parameter") -> None:
    """
    Validate string against regex pattern

    Args:
        value: String to validate
        pattern: Regex pattern
        param_name: Parameter name
    """
    validate_type(value, str, param_name)

    if not re.match(pattern, value):
        raise ValueError(f"{param_name} does not match required pattern")

def validate_phone(value: str, param_name: str = "phone") -> None:
    """
    Validate phone number format

    Args:
        value: Phone number string
        param_name: Parameter name
    """
    validate_type(value, str, param_name)

    # Allow formats: (123) 456-7890, 123-456-7890, 123.456.7890, 1234567890
    pattern = r'^\(?(\d{3})\)?[-.\s]?(\d{3})[-.\s]?(\d{4})$'
    if not re.match(pattern, value):
        raise ValueError(f"{param_name} must be a valid phone number")

# 4. Date Validation
def validate_date(value: str, format: str = "%Y-%m-%d", param_name: str = "date") -> datetime:
    """
    Validate and parse date string

    Args:
        value: Date string
        format: Expected date format
        param_name: Parameter name

    Returns:
        Parsed datetime object

    Raises:
        ValueError: If invalid date
    """
    validate_type(value, str, param_name)

    try:
        return datetime.strptime(value, format)
    except ValueError:
        raise ValueError(f"{param_name} must be a valid date in format {format}")

def validate_date_range(start_date: str, end_date: str, format: str = "%Y-%m-%d") -> None:
    """
    Validate date range (start <= end)

    Args:
        start_date: Start date string
        end_date: End date string
        format: Date format
    """
    start = validate_date(start_date, format, "start_date")
    end = validate_date(end_date, format, "end_date")

    if start > end:
        raise ValueError("start_date must be before or equal to end_date")

def validate_age(value: int, param_name: str = "age") -> None:
    """Validate age (0-150)"""
    validate_range(value, 0, 150, param_name)

# 5. Custom Validators
class ValidationError(Exception):
    """Custom validation error"""
    def __init__(self, message: str, field: str = None):
        self.field = field
        super().__init__(message)

def validate_username(value: str) -> None:
    """
    Validate username format

    Args:
        value: Username string

    Raises:
        ValidationError: If invalid username
    """
    validate_string_length(value, min_length=3, max_length=20, param_name="username")

    # Alphanumeric and underscores only
    if not re.match(r'^[a-zA-Z0-9_]+$', value):
        raise ValidationError("Username can only contain letters, numbers, and underscores", "username")

def validate_password(value: str, min_length: int = 8) -> None:
    """
    Validate password strength

    Args:
        value: Password string
        min_length: Minimum length

    Raises:
        ValidationError: If password too weak
    """
    validate_string_length(value, min_length=min_length, param_name="password")

    # Must contain uppercase, lowercase, and digit
    if not re.search(r'[A-Z]', value):
        raise ValidationError("Password must contain at least one uppercase letter", "password")

    if not re.search(r'[a-z]', value):
        raise ValidationError("Password must contain at least one lowercase letter", "password")

    if not re.search(r'\d', value):
        raise ValidationError("Password must contain at least one digit", "password")

# 6. Dataclass Validation
@dataclass
class User:
    """User with validation"""
    name: str
    email: str
    age: int

    def __post_init__(self):
        """Validate after initialization"""
        validate_string_length(self.name, min_length=1, max_length=100, param_name="name")
        validate_email(self.email, param_name="email")
        validate_age(self.age, param_name="age")

@dataclass
class Product:
    """Product with validation"""
    name: str
    price: float
    stock: int

    def __post_init__(self):
        """Validate product data"""
        validate_string_length(self.name, min_length=1, param_name="name")
        validate_range(self.price, min_val=0, param_name="price")
        validate_non_negative(self.stock, param_name="stock")

# 7. Enum Validation
class Status(Enum):
    """Status enum"""
    PENDING = "pending"
    ACTIVE = "active"
    INACTIVE = "inactive"
    CANCELLED = "cancelled"

def validate_enum(value: str, enum_class: Type[Enum], param_name: str = "parameter") -> Enum:
    """
    Validate enum value

    Args:
        value: String value
        enum_class: Enum class
        param_name: Parameter name

    Returns:
        Enum value

    Raises:
        ValueError: If invalid enum value
    """
    valid_values = [e.value for e in enum_class]

    if value not in valid_values:
        raise ValueError(f"{param_name} must be one of {valid_values}, got '{value}'")

    return enum_class(value)

# 8. Required Parameters
def validate_required(value: Any, param_name: str = "parameter") -> None:
    """
    Validate required parameter

    Args:
        value: Value to check
        param_name: Parameter name

    Raises:
        ValueError: If value is None or empty
    """
    if value is None:
        raise ValueError(f"{param_name} is required")

    if isinstance(value, str) and len(value.strip()) == 0:
        raise ValueError(f"{param_name} cannot be empty")

    if isinstance(value, (list, dict)) and len(value) == 0:
        raise ValueError(f"{param_name} cannot be empty")

# 9. Composite Validation
def validate_user_data(name: str, email: str, age: int, **kwargs) -> None:
    """
    Validate complete user data

    Args:
        name: User name
        email: User email
        age: User age
        **kwargs: Additional fields

    Raises:
        ValidationError: If any validation fails
    """
    # Required fields
    validate_required(name, "name")
    validate_required(email, "email")
    validate_required(age, "age")

    # Type validation
    validate_types(
        name=(name, str),
        email=(email, str),
        age=(age, int)
    )

    # Format validation
    validate_string_length(name, min_length=2, max_length=50, param_name="name")
    validate_email(email)
    validate_age(age)

    # Optional fields
    if 'phone' in kwargs:
        validate_phone(kwargs['phone'])

    if 'address' in kwargs:
        validate_string_length(kwargs['address'], min_length=5, param_name="address")

# 10. Validation Decorator
def validate_params(**validators):
    """
    Decorator for parameter validation

    Args:
        **validators: Parameter name -> validator function mappings

    Returns:
        Decorated function
    """
    def decorator(func):
        def wrapper(*args, **kwargs):
            # Get function signature
            import inspect
            sig = inspect.signature(func)
            bound_args = sig.bind(*args, **kwargs)
            bound_args.apply_defaults()

            # Validate each parameter
            for param_name, value in bound_args.arguments.items():
                if param_name in validators:
                    validators[param_name](value)

            return func(*args, **kwargs)
        return wrapper
    return decorator

# Usage Examples
def demonstrate_parameter_validation():
    print("=== Web Python Parameter Validation Examples ===\n")

    # 1. Type checking
    print("--- 1. Type Checking ---")
    try:
        print(typed_function("Alice", 30, [85.5, 90.0, 88.5]))
    except TypeError as e:
        print(f"Type error: {e}")

    # 2. Range validation
    print("\n--- 2. Range Validation ---")
    try:
        validate_range(50, min_val=0, max_val=100)
        print("Valid: 50 in range [0, 100]")

        validate_range(150, min_val=0, max_val=100)
    except ValueError as e:
        print(f"Range error: {e}")

    # 3. String validation
    print("\n--- 3. String Validation ---")
    try:
        validate_email("[email protected]")
        print("Valid email")

        validate_email("invalid-email")
    except ValueError as e:
        print(f"Email error: {e}")

    # 4. Date validation
    print("\n--- 4. Date Validation ---")
    try:
        date = validate_date("2025-12-31")
        print(f"Valid date: {date}")

        validate_date("31/12/2025")
    except ValueError as e:
        print(f"Date error: {e}")

    # 5. Custom validators
    print("\n--- 5. Custom Validators ---")
    try:
        validate_username("user123")
        print("Valid username")

        validate_username("us")
    except ValidationError as e:
        print(f"Username error: {e}")

    try:
        validate_password("StrongPass123")
        print("Valid password")

        validate_password("weak")
    except ValidationError as e:
        print(f"Password error: {e}")

    # 6. Dataclass validation
    print("\n--- 6. Dataclass Validation ---")
    try:
        user = User(name="Alice", email="[email protected]", age=30)
        print(f"Valid user: {user}")

        invalid_user = User(name="", email="invalid", age=-5)
    except (ValueError, TypeError) as e:
        print(f"Dataclass error: {e}")

    # 7. Enum validation
    print("\n--- 7. Enum Validation ---")
    try:
        status = validate_enum("active", Status)
        print(f"Valid status: {status.value}")

        validate_enum("invalid", Status)
    except ValueError as e:
        print(f"Enum error: {e}")

    # 8. Validation decorator
    print("\n--- 8. Validation Decorator ---")

    @validate_params(
        name=lambda x: validate_string_length(x, min_length=2, param_name="name"),
        age=lambda x: validate_range(x, 0, 150, param_name="age")
    )
    def create_user(name: str, age: int):
        return f"User: {name}, Age: {age}"

    try:
        print(create_user("Alice", 30))
        print(create_user("A", 30))
    except ValueError as e:
        print(f"Decorator error: {e}")

    print("\n=== All Parameter Validation Examples Completed ===")

# Export functions
# export { validate_type, validate_types, typed_function }
# export { validate_range, validate_positive, validate_non_negative, validate_percentage, validate_length }
# export { validate_string_length, validate_email, validate_url, validate_regex, validate_phone }
# export { validate_date, validate_date_range, validate_age }
# export { ValidationError, validate_username, validate_password }
# export { User, Product }
# export { validate_enum, Status }
# export { validate_required }
# export { validate_user_data }
# export { validate_params }
# export { demonstrate_parameter_validation }