"""Base value object for DDD domain layer. This module provides the foundational ValueObject class that all domain value objects must inherit from. Implements equality, hashing, and validation patterns for immutable value objects. """ from abc import ABC, abstractmethod from dataclasses import dataclass from typing import Any, Generic, TypeVar T = TypeVar("T") @dataclass(frozen=True, slots=True) class ValueObject(ABC, Generic[T]): """Base class for all value objects. Value objects are immutable objects defined by their attributes rather than identity. They are validated on creation and provide type safety. Attributes: value: The underlying value wrapped by the value object. Type Parameters: T: Type of the wrapped value. Example: >>> class Email(ValueObject[str]): ... def _validate(self) -> None: ... if "@" not in self.value: ... raise ValueError("Invalid email") """ value: T def __post_init__(self) -> None: """Validate value object after initialization. Automatically called by dataclass after __init__. Triggers the validation method to ensure value integrity. """ self._validate() @abstractmethod def _validate(self) -> None: """Validate the value object. Must be implemented by subclasses to enforce value constraints. Raises: ValueError: If the value does not meet validation criteria. """ ... def __eq__(self, other: object) -> bool: """Compare value objects by value. Args: other: Another object to compare with. Returns: True if both are ValueObjects with equal values. """ if not isinstance(other, ValueObject): return False return bool(self.value == other.value) def __hash__(self) -> int: """Get hash based on wrapped value. Returns: Hash of the underlying value. """ return hash(self.value) def __str__(self) -> str: """Convert value object to string. Returns: String representation of the wrapped value. """ return str(self.value) def to_primitive(self) -> Any: """Convert value object to primitive type. Returns: The underlying primitive value. """ return self.value