Function Call and Argument Validation
To validate function signatures and execute calls with validated data, you use CallSchema in conjunction with ArgumentsSchema. This allows you to enforce types on positional and keyword arguments before they reach your function, and optionally validate the return value.
Validating and Calling a Function
The most direct way to validate a function call is to define a CallSchema that points to your function and describes its arguments using an ArgumentsSchema.
from pydantic_core import SchemaValidator, core_schema
def my_function(a: int, b: int, c: int) -> int:
return a + b + c
# Define the schema
schema = core_schema.call_schema(
function=my_function,
arguments_schema=core_schema.arguments_schema(
arguments_schema=[
core_schema.arguments_parameter(name='a', mode='positional_or_keyword', schema=core_schema.int_schema()),
core_schema.arguments_parameter(name='b', mode='positional_or_keyword', schema=core_schema.int_schema()),
core_schema.arguments_parameter(name='c', mode='positional_or_keyword', schema=core_schema.int_schema()),
]
),
return_schema=core_schema.int_schema(le=10)
)
v = SchemaValidator(schema)
# Validate and call using a tuple of positional arguments
assert v.validate_python((1, 2, 3)) == 6
# Validate and call using a dictionary of keyword arguments
assert v.validate_python({'a': 1, 'b': 2, 'c': 3}) == 6
Defining Parameter Modes
Each ArgumentsParameter in the arguments_schema list must specify a mode which determines how the argument can be passed.
positional_only: The argument must be passed by position.positional_or_keyword: The argument can be passed by position or by name (default).keyword_only: The argument must be passed by name.
arguments = core_schema.arguments_schema(
arguments_schema=[
# Must be first argument, cannot be passed as 'a=1'
core_schema.arguments_parameter(name='a', mode='positional_only', schema=core_schema.int_schema()),
# Can be second argument or passed as 'b=2'
core_schema.arguments_parameter(name='b', mode='positional_or_keyword', schema=core_schema.int_schema()),
# Must be passed as 'c=3'
core_schema.arguments_parameter(name='c', mode='keyword_only', schema=core_schema.int_schema()),
]
)
Handling Variadic Arguments (*args and **kwargs)
ArgumentsSchema supports variadic arguments through var_args_schema and var_kwargs_schema. When these are provided, any extra positional or keyword arguments are validated against these schemas.
schema = core_schema.arguments_schema(
arguments_schema=[
core_schema.arguments_parameter(name='a', mode='positional_only', schema=core_schema.int_schema()),
],
var_args_schema=core_schema.str_schema(), # All extra positional args must be strings
var_kwargs_schema=core_schema.float_schema(), # All extra keyword args must be floats
)
v = SchemaValidator(schema)
# Returns (args_tuple, kwargs_dict)
args, kwargs = v.validate_python((1, 'extra1', 'extra2'), {'extra_kw': 1.5})
assert args == (1, 'extra1', 'extra2')
assert kwargs == {'extra_kw': 1.5}
Using ArgumentsV3Schema for Complex Signatures
ArgumentsV3Schema provides a more uniform way to define parameters by including variadic arguments directly in the main arguments_schema list using specific modes.
v3_schema = core_schema.arguments_v3_schema(
[
core_schema.arguments_v3_parameter(name='a', schema=core_schema.int_schema(), mode='positional_only'),
core_schema.arguments_v3_parameter(name='b', schema=core_schema.str_schema(), mode='positional_or_keyword'),
# Captures extra positional arguments
core_schema.arguments_v3_parameter(name='args', schema=core_schema.int_schema(), mode='var_args'),
core_schema.arguments_v3_parameter(name='c', schema=core_schema.bool_schema(), mode='keyword_only'),
# Captures extra keyword arguments
core_schema.arguments_v3_parameter(name='kwargs', schema=core_schema.int_schema(), mode='var_kwargs_uniform'),
]
)
v = SchemaValidator(v3_schema)
# Input can be an ArgsKwargs object or a tuple/dict structure
from pydantic_core import ArgsKwargs
result = v.validate_python(ArgsKwargs((1, 'text', 2, 3), {'c': True, 'other': 10}))
# result is ((1, 'text', 2, 3), {'c': True, 'other': 10})
Troubleshooting Common Errors
When validation fails within a CallSchema, the error location (loc) indicates whether the failure happened during argument validation or return value validation.
- Argument Errors: Located under
('arguments', ...). Common types include:unexpected_keyword_argument: A keyword was provided that isn't in the schema.missing_positional_only_argument: A required positional argument was omitted.unexpected_positional_argument: More positional arguments were provided than defined (and novar_args_schemaexists).
- Return Errors: Located under
('return',). This occurs if the function executes successfully but its output fails thereturn_schema.
# Example of an unexpected keyword argument error
try:
v.validate_python({'a': 1, 'unknown': 2})
except ValidationError as e:
# e.errors() will contain:
# {'type': 'unexpected_keyword_argument', 'loc': ('arguments', 'unknown'), ...}
pass
Note that ArgumentsSchema and ArgumentsV3Schema return a tuple of (args_tuple, kwargs_dict). If you are using these schemas outside of CallSchema, you can call your function manually using func(*args, **kwargs).