from __future__ import annotations
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import Dict, List, Optional
[docs]@dataclass(frozen=True)
class ErrorItem:
code: str
context: Dict[str, int | str] = field(default_factory=dict)
[docs]@dataclass(frozen=True)
class ValidationResult:
errors: List[ErrorItem] = field(default_factory=list)
[docs] @classmethod
def error(
cls, code: str, context: Optional[Dict[str, int | str]] = None
) -> ValidationResult:
return cls(errors=[ErrorItem(code=code, context=context or {})])
[docs] def is_valid(self) -> bool:
return len(self.errors) == 0
[docs] def merge(self, other: ValidationResult) -> ValidationResult:
return ValidationResult(self.errors + other.errors)
[docs]class ValidationRule(ABC):
[docs] @abstractmethod
def validate(self, password: str) -> ValidationResult:
...