Skip to content

Feature: Add structured pass/fail explanations for dirty_equals validators #119

Description

@dhruvjain1512

For any validator (including |, &, ~ compositions), return a structured trace of pass/fail with nested attempts, reasons, and failure paths.

Proposed Solution:
Implement explain_validation(validator, value) -> ValidationExplanation with root_attempt: ValidationAttempt. Accept validator classes or instances; capture validator_repr before validation.

ValidationAttempt fields: validator_type (class name), validator_repr (repr), value, passed (bool), failure_reason (str|None), children (list[ValidationAttempt]), path (tuple of keys/indices).
Track paths through dict keys and list/tuple/tuple indices for all nesting.

OR (|): flatten branches left-to-right into root children; each child uses the underlying validator's class name; never expose DirtyOr.
AND (&): flatten branches left-to-right; never expose DirtyAnd.
NOT (~): add one child for the inner validator; parent passes iff the child fails; record both attempts.

Provide concrete failure reasons: type mismatches; numeric bounds (gt, ge, lt, le); regex mismatches; min/max length; case upper/lower; missing/extra dict keys; list/tuple length and per-item failures.

Capture exceptions from custom DirtyEquals subclasses; mark the attempt failed with the exception message.

ValidationExplanation.get_failure_path(): return attempts from root to deepest failing leaf; on full success return [] (or a single passed root).

ValidationExplanation.format_explanation(max_depth): print a tree with exactly two spaces per depth; each line includes validator_repr and, if present, the failure_reason immediately after; hard-cutoff at max_depth.

Implement explain_failure(validator, value): return None on pass; else a non-empty human-readable string.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions