Source code for user_management.domain.specifications.specification

"""
Base Specification pattern implementation.

Defines an abstract interface for business rule specifications,
enabling validation and composition of domain rules through logical operations
such as AND, OR, and NOT. Supports the creation of complex, reusable, and testable
business logic in a clean and expressive way.
"""
from abc import ABC, abstractmethod
from typing import TypeVar, Generic, TYPE_CHECKING

if TYPE_CHECKING:
    from .and_specification import AndSpecification
    from .or_specification import OrSpecification
    from .not_specification import NotSpecification

T = TypeVar('T')


[docs] class Specification(Generic[T], ABC): """ Abstract base class for domain rule specifications. Represents a business rule that evaluates whether a candidate object satisfies a given condition. Specifications can be composed using logical operators (and_, or_, not_) to build more complex validation logic. This pattern promotes high cohesion, reusability, and clarity in enforcing domain invariants across different use cases. """
[docs] @abstractmethod def is_satisfied_by(self, candidate: T) -> bool: """ Determines whether the candidate satisfies this specification. Args: candidate (T): The object to evaluate against the rule. Returns: bool: True if the rule is satisfied; False otherwise. """ pass
[docs] def and_(self, other: 'Specification[T]') -> 'AndSpecification[T]': """ Composes this specification with another using logical AND. The resulting specification is satisfied only if both this and the provided specification are satisfied. Args: other (Specification[T]): Another specification to combine. Returns: AndSpecification[T]: A new composite specification. """ from .and_specification import AndSpecification return AndSpecification(self, other)
[docs] def or_(self, other: 'Specification[T]') -> 'OrSpecification[T]': """ Composes this specification with another using logical OR. The resulting specification is satisfied if at least one of the two specifications is satisfied. Args: other (Specification[T]): Another specification to combine. Returns: OrSpecification[T]: A new composite specification. """ from .or_specification import OrSpecification return OrSpecification(self, other)
[docs] def not_(self) -> 'NotSpecification[T]': """ Negates this specification using logical NOT. The resulting specification is satisfied if this specification is NOT satisfied by the candidate. Returns: NotSpecification[T]: A new negated specification. """ from .not_specification import NotSpecification return NotSpecification(self)