typing_validation.inspection
Asking about a type, rather than about a value: what it is, whether it can be validated against, and — when it cannot — precisely what stopped it.
The structure is a real artifact, built from the node model, which exists anyway to serve the validators.
can_validate
- can_validate(t, /)[source]
Whether this library can validate against a type at all.
Support is all-or-nothing:
tuple[int, Callable[[int], int]]answersFalseeven though theintcomponent is perfectly checkable, because a validation that silently skipped part of its obligation would be worse than none. This function exists so a caller can ask up front.Note that
validateis lazier than this. It walks the value and the type together and raises only when it reaches an unsupported component, sovalidate([], list[Callable[[int], int]])returnsTruewhile this returnsFalse. That is deliberate: scanning the type on every call is exactly the overhead that mechanism exists to avoid. This is the total answer, and it is the one to branch on.
clear_cache
forget_type
inspect_type
- inspect_type(t, /)[source]
The structure of a type: its shape, its components, and whether each is supported.
When a type is unsupported this reports the whole structure and marks precisely which component poisoned it. Totality means the answer to “can this be validated” is then always “no”, but it should never be an opaque “no” — use
unsupported_componentsto name the culprits.
scoped_cache
- scoped_cache()[source]
Intern nodes into a temporary tier, dropped whole on exit.
For callers who want the sharing without the retention: a strong reference to a type transitively pins the classes it mentions, and through them their modules and closures, so a process that builds types dynamically — synthesised
TypedDicts, classes from a factory, types built per request — would otherwise accumulate them forever.While the tier is active, lookups consult tiers innermost-first and every new node is created in the innermost tier. Exiting drops that tier in one operation, with no per-entry bookkeeping:
with scoped_cache(): for spec in incoming_specs: t = build_a_type_from(spec) if can_validate(t): report(inspect_type(t))
Note that
validateis not what this is for: it analyses nothing and interns nothing, so it neither fills this tier nor benefits from it. What fills the cache is asking about a type —can_validate,inspect_type, and the explanation built when a validation fails.Nodes created inside may reference nodes in enclosing tiers, which outlive them; nothing enclosing can reference inward, because while this tier is active it is where all new nodes go. So dropping it can never leave a dangling reference — and can never change an answer, only a cost.