feat(validators): add composite validators

Implement AllOf and AnyOf for combining multiple checks into
composite validation rules.
This commit is contained in:
2026-02-03 17:14:20 +00:00
parent 75cd7b68de
commit b9f805b2f4

View File

@@ -0,0 +1,90 @@
"""Composite validators for combining multiple checks."""
from veritext.core.types import CheckResult, ValidationContext, ValidationResult
from veritext.validators.base import Check
class AllOf:
"""Passes only if all checks pass."""
def __init__(self, checks: list[Check]) -> None:
"""
Initialise the AllOf composite validator.
Args:
checks: List of checks that must all pass.
Raises:
ValueError: If checks list is empty.
"""
if not checks:
raise ValueError("checks list cannot be empty")
self._checks = checks
@property
def name(self) -> str:
"""Return the name of this composite check."""
return "all_of"
def check(self, text: str, context: ValidationContext) -> ValidationResult:
"""
Run all checks and return aggregate result.
Args:
text: The text to validate.
context: Validation context containing reference text and metadata.
Returns:
ValidationResult that passes only if all checks pass.
"""
results: list[CheckResult] = []
for check in self._checks:
results.append(check.check(text, context))
all_passed = all(r.passed for r in results)
return ValidationResult(passed=all_passed, checks=results)
class AnyOf:
"""Passes if any check passes."""
def __init__(self, checks: list[Check]) -> None:
"""
Initialise the AnyOf composite validator.
Args:
checks: List of checks where at least one must pass.
Raises:
ValueError: If checks list is empty.
"""
if not checks:
raise ValueError("checks list cannot be empty")
self._checks = checks
@property
def name(self) -> str:
"""Return the name of this composite check."""
return "any_of"
def check(self, text: str, context: ValidationContext) -> ValidationResult:
"""
Run all checks and return aggregate result.
Args:
text: The text to validate.
context: Validation context containing reference text and metadata.
Returns:
ValidationResult that passes if any check passes.
"""
results: list[CheckResult] = []
for check in self._checks:
results.append(check.check(text, context))
any_passed = any(r.passed for r in results)
return ValidationResult(passed=any_passed, checks=results)