typing_validation.emission
Emitting Python source specialised to one type, compiling it, and returning the result.
The goal is code equivalent to what a competent programmer would write by hand
for that one type: flat, unrolled, with the isinstance checks inlined and no
per-node dispatch of any kind. The cost is compile latency, paid once,
deliberately, by a caller who has decided it is worth it.
Why unrolling is safe, and where it stops. Unrolled loops nest once per level
of the type, and for an acyclic type that bounds the value: list[int]
against a value nested twenty thousand deep fails its isinstance at level two
and never descends. So there is no recursion to overflow, and the emitted code can
be exactly the nested loops one would write.
A cycle removes that bound — a recursive alias accepts a value of any depth — and unrolling it does not terminate anyway. So unrolling stops at a back-edge, and at every other boundary the emitted code calls into the composed validator, whose driver is a loop and therefore safe at any depth. That is the same de-optimisation a plugin forces, for the same reason: you cannot inline code you do not have.
compiled_validator
- compiled_validator(t, /)[source]
A validation function specialised to one type, compiled from source.
Same contract as
validateandvalidator, and the same verdict on every value. It costs more to build than either and less to run, so it is worth it when the same type is validated very many times:check = compiled_validator(list[int]) for payload in payloads: check(payload)
Like
validator, and for the same reason, it refuses an unsupported type at construction rather than waiting for a value to reach the unsupported part.- Raises:
UnsupportedTypeError – if the type, or any component of it, is not one this library can validate against.
- Parameters:
t (
Any)- Return type:
source_for
- source_for(t, /)[source]
The source that
compiled_validatorwould compile for a type.Exposed because emitted code that cannot be read cannot be reviewed, and because a test that asserts on the source can say things about the shape — that a loop was unrolled, that a boundary became a call — which a test that only runs the result cannot.