Coverage for pydantic/functional_validators.py: 98.28%
127 statements
« prev ^ index » next coverage.py v7.5.4, created at 2024-07-03 19:29 +0000
« prev ^ index » next coverage.py v7.5.4, created at 2024-07-03 19:29 +0000
1"""This module contains related classes and functions for validation."""
3from __future__ import annotations as _annotations 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
5import dataclasses 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
6import sys 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
7from functools import partialmethod 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
8from types import FunctionType 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
9from typing import TYPE_CHECKING, Any, Callable, TypeVar, Union, cast, overload 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
11from pydantic_core import core_schema 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
12from pydantic_core import core_schema as _core_schema 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
13from typing_extensions import Annotated, Literal, TypeAlias 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
15from . import GetCoreSchemaHandler as _GetCoreSchemaHandler 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
16from ._internal import _core_metadata, _decorators, _generics, _internal_dataclass 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
17from .annotated_handlers import GetCoreSchemaHandler 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
18from .errors import PydanticUserError 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
20if sys.version_info < (3, 11): 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
21 from typing_extensions import Protocol 1ABCDopnmEFGHstUVOPQRSIJKLwx
22else:
23 from typing import Protocol 1qrabcduvefghTMNyzijkl
25_inspect_validator = _decorators.inspect_validator 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
28@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true) 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
29class AfterValidator: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
30 """Usage docs: https://docs.pydantic.dev/2.8/concepts/validators/#annotated-validators
32 A metadata class that indicates that a validation should be applied **after** the inner validation logic.
34 Attributes:
35 func: The validator function.
37 Example:
38 ```py
39 from typing_extensions import Annotated
41 from pydantic import AfterValidator, BaseModel, ValidationError
43 MyInt = Annotated[int, AfterValidator(lambda v: v + 1)]
45 class Model(BaseModel):
46 a: MyInt
48 print(Model(a=1).a)
49 #> 2
51 try:
52 Model(a='a')
53 except ValidationError as e:
54 print(e.json(indent=2))
55 '''
56 [
57 {
58 "type": "int_parsing",
59 "loc": [
60 "a"
61 ],
62 "msg": "Input should be a valid integer, unable to parse string as an integer",
63 "input": "a",
64 "url": "https://errors.pydantic.dev/2/v/int_parsing"
65 }
66 ]
67 '''
68 ```
69 """
71 func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
73 def __get_pydantic_core_schema__(self, source_type: Any, handler: _GetCoreSchemaHandler) -> core_schema.CoreSchema: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
74 schema = handler(source_type) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
75 info_arg = _inspect_validator(self.func, 'after') 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
76 if info_arg: 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
77 func = cast(core_schema.WithInfoValidatorFunction, self.func) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
78 return core_schema.with_info_after_validator_function(func, schema=schema, field_name=handler.field_name) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
79 else:
80 func = cast(core_schema.NoInfoValidatorFunction, self.func) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
81 return core_schema.no_info_after_validator_function(func, schema=schema) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
84@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true) 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
85class BeforeValidator: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
86 """Usage docs: https://docs.pydantic.dev/2.8/concepts/validators/#annotated-validators
88 A metadata class that indicates that a validation should be applied **before** the inner validation logic.
90 Attributes:
91 func: The validator function.
93 Example:
94 ```py
95 from typing_extensions import Annotated
97 from pydantic import BaseModel, BeforeValidator
99 MyInt = Annotated[int, BeforeValidator(lambda v: v + 1)]
101 class Model(BaseModel):
102 a: MyInt
104 print(Model(a=1).a)
105 #> 2
107 try:
108 Model(a='a')
109 except TypeError as e:
110 print(e)
111 #> can only concatenate str (not "int") to str
112 ```
113 """
115 func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
117 def __get_pydantic_core_schema__(self, source_type: Any, handler: _GetCoreSchemaHandler) -> core_schema.CoreSchema: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
118 schema = handler(source_type) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
119 info_arg = _inspect_validator(self.func, 'before') 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
120 if info_arg: 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
121 func = cast(core_schema.WithInfoValidatorFunction, self.func) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
122 return core_schema.with_info_before_validator_function(func, schema=schema, field_name=handler.field_name) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
123 else:
124 func = cast(core_schema.NoInfoValidatorFunction, self.func) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
125 return core_schema.no_info_before_validator_function(func, schema=schema) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
128@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true) 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
129class PlainValidator: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
130 """Usage docs: https://docs.pydantic.dev/2.8/concepts/validators/#annotated-validators
132 A metadata class that indicates that a validation should be applied **instead** of the inner validation logic.
134 Attributes:
135 func: The validator function.
137 Example:
138 ```py
139 from typing_extensions import Annotated
141 from pydantic import BaseModel, PlainValidator
143 MyInt = Annotated[int, PlainValidator(lambda v: int(v) + 1)]
145 class Model(BaseModel):
146 a: MyInt
148 print(Model(a='1').a)
149 #> 2
150 ```
151 """
153 func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
155 def __get_pydantic_core_schema__(self, source_type: Any, handler: _GetCoreSchemaHandler) -> core_schema.CoreSchema: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
156 # Note that for some valid uses of PlainValidator, it is not possible to generate a core schema for the
157 # source_type, so calling `handler(source_type)` will error, which prevents us from generating a proper
158 # serialization schema. To work around this for use cases that will not involve serialization, we simply
159 # catch any PydanticSchemaGenerationError that may be raised while attempting to build the serialization schema
160 # and abort any attempts to handle special serialization.
161 from pydantic import PydanticSchemaGenerationError 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
163 try: 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
164 schema = handler(source_type) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
165 serialization = core_schema.wrap_serializer_function_ser_schema(function=lambda v, h: h(v), schema=schema) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
166 except PydanticSchemaGenerationError: 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
167 serialization = None 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
169 info_arg = _inspect_validator(self.func, 'plain') 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
170 if info_arg: 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
171 func = cast(core_schema.WithInfoValidatorFunction, self.func) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
172 return core_schema.with_info_plain_validator_function( 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
173 func, field_name=handler.field_name, serialization=serialization
174 )
175 else:
176 func = cast(core_schema.NoInfoValidatorFunction, self.func) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
177 return core_schema.no_info_plain_validator_function(func, serialization=serialization) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
180@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true) 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
181class WrapValidator: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
182 """Usage docs: https://docs.pydantic.dev/2.8/concepts/validators/#annotated-validators
184 A metadata class that indicates that a validation should be applied **around** the inner validation logic.
186 Attributes:
187 func: The validator function.
189 ```py
190 from datetime import datetime
192 from typing_extensions import Annotated
194 from pydantic import BaseModel, ValidationError, WrapValidator
196 def validate_timestamp(v, handler):
197 if v == 'now':
198 # we don't want to bother with further validation, just return the new value
199 return datetime.now()
200 try:
201 return handler(v)
202 except ValidationError:
203 # validation failed, in this case we want to return a default value
204 return datetime(2000, 1, 1)
206 MyTimestamp = Annotated[datetime, WrapValidator(validate_timestamp)]
208 class Model(BaseModel):
209 a: MyTimestamp
211 print(Model(a='now').a)
212 #> 2032-01-02 03:04:05.000006
213 print(Model(a='invalid').a)
214 #> 2000-01-01 00:00:00
215 ```
216 """
218 func: core_schema.NoInfoWrapValidatorFunction | core_schema.WithInfoWrapValidatorFunction 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
220 def __get_pydantic_core_schema__(self, source_type: Any, handler: _GetCoreSchemaHandler) -> core_schema.CoreSchema: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
221 schema = handler(source_type) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
222 info_arg = _inspect_validator(self.func, 'wrap') 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
223 if info_arg: 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
224 func = cast(core_schema.WithInfoWrapValidatorFunction, self.func) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
225 return core_schema.with_info_wrap_validator_function(func, schema=schema, field_name=handler.field_name) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
226 else:
227 func = cast(core_schema.NoInfoWrapValidatorFunction, self.func) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
228 return core_schema.no_info_wrap_validator_function(func, schema=schema) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
231if TYPE_CHECKING: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
233 class _OnlyValueValidatorClsMethod(Protocol):
234 def __call__(self, cls: Any, value: Any, /) -> Any: ...
236 class _V2ValidatorClsMethod(Protocol):
237 def __call__(self, cls: Any, value: Any, info: _core_schema.ValidationInfo, /) -> Any: ...
239 class _V2WrapValidatorClsMethod(Protocol):
240 def __call__(
241 self,
242 cls: Any,
243 value: Any,
244 handler: _core_schema.ValidatorFunctionWrapHandler,
245 info: _core_schema.ValidationInfo,
246 /,
247 ) -> Any: ...
249 _V2Validator = Union[
250 _V2ValidatorClsMethod,
251 _core_schema.WithInfoValidatorFunction,
252 _OnlyValueValidatorClsMethod,
253 _core_schema.NoInfoValidatorFunction,
254 ]
256 _V2WrapValidator = Union[
257 _V2WrapValidatorClsMethod,
258 _core_schema.WithInfoWrapValidatorFunction,
259 ]
261 _PartialClsOrStaticMethod: TypeAlias = Union[classmethod[Any, Any, Any], staticmethod[Any, Any], partialmethod[Any]]
263 _V2BeforeAfterOrPlainValidatorType = TypeVar(
264 '_V2BeforeAfterOrPlainValidatorType',
265 _V2Validator,
266 _PartialClsOrStaticMethod,
267 )
268 _V2WrapValidatorType = TypeVar('_V2WrapValidatorType', _V2WrapValidator, _PartialClsOrStaticMethod)
271@overload 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
272def field_validator( 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
273 field: str, 1abcdnmefghMNijkl
274 /,
275 *fields: str, 1abcdnmefghMNijkl
276 mode: Literal['before', 'after', 'plain'] = ..., 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
277 check_fields: bool | None = ..., 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
278) -> Callable[[_V2BeforeAfterOrPlainValidatorType], _V2BeforeAfterOrPlainValidatorType]: ... 1abcdnmefghMNijkl
281@overload 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
282def field_validator( 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
283 field: str, 1abcdnmefghMNijkl
284 /,
285 *fields: str, 1abcdnmefghMNijkl
286 mode: Literal['wrap'], 1abcdnmefghMNijkl
287 check_fields: bool | None = ..., 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
288) -> Callable[[_V2WrapValidatorType], _V2WrapValidatorType]: ... 1abcdnmefghMNijkl
291FieldValidatorModes: TypeAlias = Literal['before', 'after', 'wrap', 'plain'] 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
294def field_validator( 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
295 field: str,
296 /,
297 *fields: str,
298 mode: FieldValidatorModes = 'after',
299 check_fields: bool | None = None,
300) -> Callable[[Any], Any]:
301 """Usage docs: https://docs.pydantic.dev/2.8/concepts/validators/#field-validators
303 Decorate methods on the class indicating that they should be used to validate fields.
305 Example usage:
306 ```py
307 from typing import Any
309 from pydantic import (
310 BaseModel,
311 ValidationError,
312 field_validator,
313 )
315 class Model(BaseModel):
316 a: str
318 @field_validator('a')
319 @classmethod
320 def ensure_foobar(cls, v: Any):
321 if 'foobar' not in v:
322 raise ValueError('"foobar" not found in a')
323 return v
325 print(repr(Model(a='this is foobar good')))
326 #> Model(a='this is foobar good')
328 try:
329 Model(a='snap')
330 except ValidationError as exc_info:
331 print(exc_info)
332 '''
333 1 validation error for Model
334 a
335 Value error, "foobar" not found in a [type=value_error, input_value='snap', input_type=str]
336 '''
337 ```
339 For more in depth examples, see [Field Validators](../concepts/validators.md#field-validators).
341 Args:
342 field: The first field the `field_validator` should be called on; this is separate
343 from `fields` to ensure an error is raised if you don't pass at least one.
344 *fields: Additional field(s) the `field_validator` should be called on.
345 mode: Specifies whether to validate the fields before or after validation.
346 check_fields: Whether to check that the fields actually exist on the model.
348 Returns:
349 A decorator that can be used to decorate a function to be used as a field_validator.
351 Raises:
352 PydanticUserError:
353 - If `@field_validator` is used bare (with no fields).
354 - If the args passed to `@field_validator` as fields are not strings.
355 - If `@field_validator` applied to instance methods.
356 """
357 if isinstance(field, FunctionType): 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
358 raise PydanticUserError( 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
359 '`@field_validator` should be used with fields and keyword arguments, not bare. '
360 "E.g. usage should be `@validator('<field_name>', ...)`",
361 code='validator-no-fields',
362 )
363 fields = field, *fields 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
364 if not all(isinstance(field, str) for field in fields): 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
365 raise PydanticUserError( 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
366 '`@field_validator` fields should be passed as separate string args. '
367 "E.g. usage should be `@validator('<field_name_1>', '<field_name_2>', ...)`",
368 code='validator-invalid-fields',
369 )
371 def dec( 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
372 f: Callable[..., Any] | staticmethod[Any, Any] | classmethod[Any, Any, Any],
373 ) -> _decorators.PydanticDescriptorProxy[Any]:
374 if _decorators.is_instance_method_from_sig(f): 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
375 raise PydanticUserError( 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
376 '`@field_validator` cannot be applied to instance methods', code='validator-instance-method'
377 )
379 # auto apply the @classmethod decorator
380 f = _decorators.ensure_classmethod_based_on_signature(f) 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
382 dec_info = _decorators.FieldValidatorDecoratorInfo(fields=fields, mode=mode, check_fields=check_fields) 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
383 return _decorators.PydanticDescriptorProxy(f, dec_info) 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
385 return dec 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
388_ModelType = TypeVar('_ModelType') 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
389_ModelTypeCo = TypeVar('_ModelTypeCo', covariant=True) 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
392class ModelWrapValidatorHandler(_core_schema.ValidatorFunctionWrapHandler, Protocol[_ModelTypeCo]): 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
393 """@model_validator decorated function handler argument type. This is used when `mode='wrap'`."""
395 def __call__( # noqa: D102 1ABCDopqrabcdEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
396 self,
397 value: Any, 1abcdnmefghMNijkl
398 outer_location: str | int | None = None, 1opqrabcdnmstuvefghOPQRSTMNwxyzijkl
399 /,
400 ) -> _ModelTypeCo: # pragma: no cover 1abcdnmefghMNijkl
401 ...
404class ModelWrapValidatorWithoutInfo(Protocol[_ModelType]): 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
405 """A @model_validator decorated function signature.
406 This is used when `mode='wrap'` and the function does not have info argument.
407 """
409 def __call__( # noqa: D102 409 ↛ exitline 409 didn't jump to the function exit1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
410 self,
411 cls: type[_ModelType],
412 # this can be a dict, a model instance
413 # or anything else that gets passed to validate_python
414 # thus validators _must_ handle all cases
415 value: Any,
416 handler: ModelWrapValidatorHandler[_ModelType],
417 /,
418 ) -> _ModelType: ...
421class ModelWrapValidator(Protocol[_ModelType]): 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
422 """A @model_validator decorated function signature. This is used when `mode='wrap'`."""
424 def __call__( # noqa: D102 424 ↛ exitline 424 didn't jump to the function exit1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
425 self,
426 cls: type[_ModelType],
427 # this can be a dict, a model instance
428 # or anything else that gets passed to validate_python
429 # thus validators _must_ handle all cases
430 value: Any,
431 handler: ModelWrapValidatorHandler[_ModelType],
432 info: _core_schema.ValidationInfo,
433 /,
434 ) -> _ModelType: ...
437class FreeModelBeforeValidatorWithoutInfo(Protocol): 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
438 """A @model_validator decorated function signature. 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
439 This is used when `mode='before'` and the function does not have info argument.
440 """
442 def __call__( # noqa: D102 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
443 self,
444 # this can be a dict, a model instance
445 # or anything else that gets passed to validate_python
446 # thus validators _must_ handle all cases
447 value: Any, 1abcdnmefghMNijkl
448 /,
449 ) -> Any: ... 1abcdnmefghMNijkl
452class ModelBeforeValidatorWithoutInfo(Protocol): 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
453 """A @model_validator decorated function signature. 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
454 This is used when `mode='before'` and the function does not have info argument.
455 """
457 def __call__( # noqa: D102 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
458 self,
459 cls: Any, 1abcdnmefghMNijkl
460 # this can be a dict, a model instance
461 # or anything else that gets passed to validate_python
462 # thus validators _must_ handle all cases
463 value: Any, 1abcdnmefghMNijkl
464 /,
465 ) -> Any: ... 1abcdnmefghMNijkl
468class FreeModelBeforeValidator(Protocol): 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
469 """A `@model_validator` decorated function signature. This is used when `mode='before'`.""" 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
471 def __call__( # noqa: D102 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
472 self,
473 # this can be a dict, a model instance
474 # or anything else that gets passed to validate_python
475 # thus validators _must_ handle all cases
476 value: Any, 1abcdnmefghMNijkl
477 info: _core_schema.ValidationInfo, 1abcdnmefghMNijkl
478 /,
479 ) -> Any: ... 1abcdnmefghMNijkl
482class ModelBeforeValidator(Protocol): 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
483 """A `@model_validator` decorated function signature. This is used when `mode='before'`.""" 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
485 def __call__( # noqa: D102 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
486 self,
487 cls: Any, 1abcdnmefghMNijkl
488 # this can be a dict, a model instance
489 # or anything else that gets passed to validate_python
490 # thus validators _must_ handle all cases
491 value: Any, 1abcdnmefghMNijkl
492 info: _core_schema.ValidationInfo, 1abcdnmefghMNijkl
493 /,
494 ) -> Any: ... 1abcdnmefghMNijkl
497ModelAfterValidatorWithoutInfo = Callable[[_ModelType], _ModelType] 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
498"""A `@model_validator` decorated function signature. This is used when `mode='after'` and the function does not 1opqrabcdmstuvefghOPQRSTMNwxyzijkl
499have info argument.
500"""
502ModelAfterValidator = Callable[[_ModelType, _core_schema.ValidationInfo], _ModelType] 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
503"""A `@model_validator` decorated function signature. This is used when `mode='after'`.""" 1opqrabcdmstuvefghOPQRSTMNwxyzijkl
505_AnyModelWrapValidator = Union[ModelWrapValidator[_ModelType], ModelWrapValidatorWithoutInfo[_ModelType]] 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
506_AnyModeBeforeValidator = Union[ 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
507 FreeModelBeforeValidator, ModelBeforeValidator, FreeModelBeforeValidatorWithoutInfo, ModelBeforeValidatorWithoutInfo
508]
509_AnyModelAfterValidator = Union[ModelAfterValidator[_ModelType], ModelAfterValidatorWithoutInfo[_ModelType]] 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
512@overload 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
513def model_validator( 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
514 *,
515 mode: Literal['wrap'], 1abcdnmefghMNijkl
516) -> Callable[ 1abcdnmefghMNijkl
517 [_AnyModelWrapValidator[_ModelType]], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]
518]: ...
521@overload 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
522def model_validator( 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
523 *,
524 mode: Literal['before'], 1abcdnmefghMNijkl
525) -> Callable[ 1abcdnmefghMNijkl
526 [_AnyModeBeforeValidator], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]
527]: ...
530@overload 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
531def model_validator( 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
532 *,
533 mode: Literal['after'], 1abcdnmefghMNijkl
534) -> Callable[ 1abcdnmefghMNijkl
535 [_AnyModelAfterValidator[_ModelType]], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]
536]: ...
539def model_validator( 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
540 *,
541 mode: Literal['wrap', 'before', 'after'],
542) -> Any:
543 """Usage docs: https://docs.pydantic.dev/2.8/concepts/validators/#model-validators
545 Decorate model methods for validation purposes.
547 Example usage:
548 ```py
549 from typing_extensions import Self
551 from pydantic import BaseModel, ValidationError, model_validator
553 class Square(BaseModel):
554 width: float
555 height: float
557 @model_validator(mode='after')
558 def verify_square(self) -> Self:
559 if self.width != self.height:
560 raise ValueError('width and height do not match')
561 return self
563 s = Square(width=1, height=1)
564 print(repr(s))
565 #> Square(width=1.0, height=1.0)
567 try:
568 Square(width=1, height=2)
569 except ValidationError as e:
570 print(e)
571 '''
572 1 validation error for Square
573 Value error, width and height do not match [type=value_error, input_value={'width': 1, 'height': 2}, input_type=dict]
574 '''
575 ```
577 For more in depth examples, see [Model Validators](../concepts/validators.md#model-validators).
579 Args:
580 mode: A required string literal that specifies the validation mode.
581 It can be one of the following: 'wrap', 'before', or 'after'.
583 Returns:
584 A decorator that can be used to decorate a function to be used as a model validator.
585 """
587 def dec(f: Any) -> _decorators.PydanticDescriptorProxy[Any]: 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
588 # auto apply the @classmethod decorator
589 f = _decorators.ensure_classmethod_based_on_signature(f) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
590 dec_info = _decorators.ModelValidatorDecoratorInfo(mode=mode) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
591 return _decorators.PydanticDescriptorProxy(f, dec_info) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
593 return dec 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
596AnyType = TypeVar('AnyType') 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
599if TYPE_CHECKING: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
600 # If we add configurable attributes to IsInstance, we'd probably need to stop hiding it from type checkers like this
601 InstanceOf = Annotated[AnyType, ...] # `IsInstance[Sequence]` will be recognized by type checkers as `Sequence`
603else:
605 @dataclasses.dataclass(**_internal_dataclass.slots_true) 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
606 class InstanceOf: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
607 '''Generic type for annotating a type that is an instance of a given class.
609 Example:
610 ```py
611 from pydantic import BaseModel, InstanceOf
613 class Foo:
614 ...
616 class Bar(BaseModel):
617 foo: InstanceOf[Foo]
619 Bar(foo=Foo())
620 try:
621 Bar(foo=42)
622 except ValidationError as e:
623 print(e)
624 """
625 [
626 │ {
627 │ │ 'type': 'is_instance_of',
628 │ │ 'loc': ('foo',),
629 │ │ 'msg': 'Input should be an instance of Foo',
630 │ │ 'input': 42,
631 │ │ 'ctx': {'class': 'Foo'},
632 │ │ 'url': 'https://errors.pydantic.dev/0.38.0/v/is_instance_of'
633 │ }
634 ]
635 """
636 ```
637 '''
639 @classmethod 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
640 def __class_getitem__(cls, item: AnyType) -> AnyType: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
641 return Annotated[item, cls()] 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
643 @classmethod 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
644 def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
645 from pydantic import PydanticSchemaGenerationError 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
647 # use the generic _origin_ as the second argument to isinstance when appropriate
648 instance_of_schema = core_schema.is_instance_schema(_generics.get_origin(source) or source) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
650 try: 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
651 # Try to generate the "standard" schema, which will be used when loading from JSON
652 original_schema = handler(source) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
653 except PydanticSchemaGenerationError: 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
654 # If that fails, just produce a schema that can validate from python
655 return instance_of_schema 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
656 else:
657 # Use the "original" approach to serialization
658 instance_of_schema['serialization'] = core_schema.wrap_serializer_function_ser_schema( 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
659 function=lambda v, h: h(v), schema=original_schema
660 )
661 return core_schema.json_or_python_schema(python_schema=instance_of_schema, json_schema=original_schema) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
663 __hash__ = object.__hash__ 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
666if TYPE_CHECKING: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
667 SkipValidation = Annotated[AnyType, ...] # SkipValidation[list[str]] will be treated by type checkers as list[str]
668else:
670 @dataclasses.dataclass(**_internal_dataclass.slots_true) 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
671 class SkipValidation: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
672 """If this is applied as an annotation (e.g., via `x: Annotated[int, SkipValidation]`), validation will be
673 skipped. You can also use `SkipValidation[int]` as a shorthand for `Annotated[int, SkipValidation]`.
675 This can be useful if you want to use a type annotation for documentation/IDE/type-checking purposes,
676 and know that it is safe to skip validation for one or more of the fields.
678 Because this converts the validation schema to `any_schema`, subsequent annotation-applied transformations
679 may not have the expected effects. Therefore, when used, this annotation should generally be the final
680 annotation applied to a type.
681 """
683 def __class_getitem__(cls, item: Any) -> Any: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
684 return Annotated[item, SkipValidation()] 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
686 @classmethod 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
687 def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl
688 original_schema = handler(source) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
689 metadata = _core_metadata.build_metadata_dict(js_annotation_functions=[lambda _c, h: h(original_schema)]) 1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
690 return core_schema.any_schema( 690 ↛ exitline 690 didn't jump to the function exit1ABCDopqrabcdnmEFGHstuvefghIJKLwxyzijkl
691 metadata=metadata,
692 serialization=core_schema.wrap_serializer_function_ser_schema(
693 function=lambda v, h: h(v), schema=original_schema
694 ),
695 )
697 __hash__ = object.__hash__ 1ABCDopqrabcdnmEFGHstuvefghUVOPQRSTMNIJKLwxyzijkl