Validation decorator
The validate_arguments decorator allows the arguments passed to a function to be parsed and validated using
the function’s annotations before the function is called. While under the hood this uses the same approach of model
creation and initialisation; it provides an extremely easy way to apply validation to your code with minimal
boilerplate.
Example of usage:
Argument types are inferred from type annotations on the function, arguments without a type decorator are considered
as Any. Since validate_arguments internally uses a standard BaseModel, all types listed in
types can be validated, including pydantic models and custom types.
As with the rest of pydantic, types can be coerced by the decorator before they’re passed to the actual function:
A few notes:
- though they’re passed as strings,
pathandregexare converted to aPathobject and regex respectively by the decorator maxhas no type annotation, so will be considered asAnyby the decorator
Type coercion like this can be extremely helpful but also confusing or not desired,
see below for a discussion of validate_arguments’s limitations in this regard.
The decorator is designed to work with functions using all possible parameter configurations and all possible combinations of these:
- positional or keyword arguments with or without defaults
- variable positional arguments defined via
*(often*args) - variable keyword arguments defined via
**(often**kwargs) - keyword only arguments - arguments after
*, - positional only arguments - arguments before
, /(new in Python 3.8)
To demonstrate all the above parameter types:
Field can also be used with validate_arguments to provide extra information about
the field and validations. In general it should be used in a type hint with
Annotated, unless default_factory is specified, in which case it should be used
as the default value of the field:
The alias can be used with the decorator as normal.
The validate_arguments decorator should work “out of the box” with mypy since it’s
defined to return a function with the same signature as the function it decorates. The only limitation is that
since we trick mypy into thinking the function returned by the decorator is the same as the function being
decorated; access to the raw function or other attributes will require type: ignore.
By default, arguments validation is done by directly calling the decorated function with parameters.
But what if you wanted to validate them without actually calling the function?
To do that you can call the validate method bound to the decorated function.
The raw function which was decorated is accessible, this is useful if in some scenarios you trust your input arguments and want to call the function in the most performant way (see notes on performance below):
validate_arguments can also be used on async functions:
The model behind validate_arguments can be customised using a config setting which is equivalent to
setting the Config sub-class in normal models.
Configuration is set using the config keyword argument to the decorator, it may be either a config class
or a dict of properties which are converted to a class later.
validate_arguments has been released on a provisional basis without all the bells and whistles, which may
be added later, see #1205 for some more discussion of this.
In particular:
Currently upon validation failure, a standard pydantic ValidationError is raised,
see model error handling.
This is helpful since it’s str() method provides useful details of the error which occurred and methods like
.errors() and .json() can be useful when exposing the errors to end users, however ValidationError inherits
from ValueError not TypeError which may be unexpected since Python would raise a TypeError upon invalid
or missing arguments. This may be addressed in future by either allow a custom error or raising a different
exception by default, or both.
pydantic currently leans on the side of trying to coerce types rather than raise an error if a type is wrong,
see model data conversion and validate_arguments is no different.
See #1098 and other issues with the “strictness” label
for a discussion of this. If pydantic gets a “strict” mode in future, validate_arguments will have an option
to use this, it may even become the default for the decorator.
We’ve made a big effort to make pydantic as performant as possible
and argument inspect and model creation is only performed once when the function is defined, however
there will still be a performance impact to using the validate_arguments decorator compared to
calling the raw function.
In many situations this will have little or no noticeable effect, however be aware that
validate_arguments is not an equivalent or alternative to function definitions in strongly typed languages;
it never will be.
The return value of the function is not validated against its return type annotation, this may be added as an option in future.
fields and alias_generator on custom Config are not supported, see above.
Neither are validators.
The following names may not be used by arguments since they can be used internally to store information about the function’s signature:
v__argsv__kwargsv__positional_only
These names (together with "args" and "kwargs") may or may not (depending on the function’s signature) appear as
fields on the internal pydantic model accessible via .model thus this model isn’t especially useful
(e.g. for generating a schema) at the moment.
This should be fixable in future as the way error are raised is changed.