typing_validation.plugins
The extension point: how a parametrised class declares the way its type arguments are validated.
The hook needs no machinery of its own, because the dispatch point already exists. It is the generic-class arm — the one reached when a parametrised type’s origin is a plain class the core knows nothing about — which is precisely where the core has run out of things it can determine on its own.
It is also free. int, list[int], dict[str, int], unions and literals
all resolve long before that arm, so nothing that is not already unknown pays
anything for its existence.
PluginCheck
- PluginCheck = PluginCheck
What a plugin must provide: given a value and the type arguments, say whether the value is valid. Nothing more is required.
Asking every plugin author to also emit source for the compiled path would be an absurd toll for supporting one type. A plugin may optionally supply more — structure, diagnostics, an emitter — but a boolean is the whole obligation.
PluginComponents
- PluginComponents = PluginComponents
Optional: which of a parametrised class’s type arguments the core validates, by position.
Not every type argument is one, and
numpy.ndarray[shape, dtype]has one of each. The shape is an ordinary type, which the core checks the array’s.shapetuple against.numpy.dtype[numpy.uint8]is a specification the plugin interprets, and never a validation target in its own right — so NumPy declares(0,).The core cannot tell them apart, and guessing wrong is not harmless. Treating every argument as a component makes
numpy.dtype[numpy.uint8]one — and it is itself a parametrised NumPy class with no validator of its own, so totality poisons it, and with it every array type there is. Declaring components is what keeps totality propagating through the arguments that deserve it and out of the ones that do not.Absent this, a plugin’s arguments are opaque: the plugin checks them, and totality does not reach inside.
plugin_import
- plugin_import(origin, /)[source]
The import that would enable this distribution’s plugin for a class, or
Noneif we ship no plugin for it.A class we ship a plugin for is one whose arguments are checkable, so leaving them unchecked would report success we had not earned. Answering non-
Nonehere is therefore what turns an unregistered parametrised class from “arguments unchecked, by design” into an error.
register_validator
- register_validator(cls, check, /, components=None)[source]
Declare how the type arguments of a parametrised class are validated.
This is the route for classes you do not own. For a class you do own, define a
__validate__classmethod instead, and a__validate_components__class attribute if you want components:class Box[T]: __validate_components__ = (0,) @classmethod def __validate__(cls, val, args): return is_valid(val.item, args[0])
clsis the class unparametrised —numpy.ndarray, notnumpy.ndarray[shape, dtype].componentssays which type arguments the core validates, by position, so that totality propagates through them; seePluginComponentsfor why the core cannot work that out for itself.- Raises:
TypeError – if
clsis not a class,checkis not callable, orcomponentsis not a sequence of positions.- Parameters:
cls (
type)check (
PluginCheck)components (
PluginComponents|None)
- Return type: