1"""This module contains related classes and functions for validation.""" 
    2 
    3from __future__ import annotations as _annotations 
    4 
    5import dataclasses 
    6import sys 
    7import warnings 
    8from functools import partialmethod 
    9from types import FunctionType 
    10from typing import TYPE_CHECKING, Annotated, Any, Callable, Literal, TypeVar, Union, cast, overload 
    11 
    12from pydantic_core import PydanticUndefined, core_schema 
    13from typing_extensions import Self, TypeAlias 
    14 
    15from ._internal import _decorators, _generics, _internal_dataclass 
    16from .annotated_handlers import GetCoreSchemaHandler 
    17from .errors import PydanticUserError 
    18from .version import version_short 
    19from .warnings import ArbitraryTypeWarning, PydanticDeprecatedSince212 
    20 
    21if sys.version_info < (3, 11): 
    22    from typing_extensions import Protocol 
    23else: 
    24    from typing import Protocol 
    25 
    26_inspect_validator = _decorators.inspect_validator 
    27 
    28 
    29@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true) 
    30class AfterValidator: 
    31    """!!! abstract "Usage Documentation" 
    32        [field *after* validators](../concepts/validators.md#field-after-validator) 
    33 
    34    A metadata class that indicates that a validation should be applied **after** the inner validation logic. 
    35 
    36    Attributes: 
    37        func: The validator function. 
    38 
    39    Example: 
    40        ```python 
    41        from typing import Annotated 
    42 
    43        from pydantic import AfterValidator, BaseModel, ValidationError 
    44 
    45        MyInt = Annotated[int, AfterValidator(lambda v: v + 1)] 
    46 
    47        class Model(BaseModel): 
    48            a: MyInt 
    49 
    50        print(Model(a=1).a) 
    51        #> 2 
    52 
    53        try: 
    54            Model(a='a') 
    55        except ValidationError as e: 
    56            print(e.json(indent=2)) 
    57            ''' 
    58            [ 
    59              { 
    60                "type": "int_parsing", 
    61                "loc": [ 
    62                  "a" 
    63                ], 
    64                "msg": "Input should be a valid integer, unable to parse string as an integer", 
    65                "input": "a", 
    66                "url": "https://errors.pydantic.dev/2/v/int_parsing" 
    67              } 
    68            ] 
    69            ''' 
    70        ``` 
    71    """ 
    72 
    73    func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction 
    74 
    75    def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: 
    76        schema = handler(source_type) 
    77        info_arg = _inspect_validator(self.func, mode='after', type='field') 
    78        if info_arg: 
    79            func = cast(core_schema.WithInfoValidatorFunction, self.func) 
    80            return core_schema.with_info_after_validator_function(func, schema=schema) 
    81        else: 
    82            func = cast(core_schema.NoInfoValidatorFunction, self.func) 
    83            return core_schema.no_info_after_validator_function(func, schema=schema) 
    84 
    85    @classmethod 
    86    def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self: 
    87        return cls(func=decorator.func) 
    88 
    89 
    90@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true) 
    91class BeforeValidator: 
    92    """!!! abstract "Usage Documentation" 
    93        [field *before* validators](../concepts/validators.md#field-before-validator) 
    94 
    95    A metadata class that indicates that a validation should be applied **before** the inner validation logic. 
    96 
    97    Attributes: 
    98        func: The validator function. 
    99        json_schema_input_type: The input type used to generate the appropriate 
    100            JSON Schema (in validation mode). The actual input type is `Any`. 
    101 
    102    Example: 
    103        ```python 
    104        from typing import Annotated 
    105 
    106        from pydantic import BaseModel, BeforeValidator 
    107 
    108        MyInt = Annotated[int, BeforeValidator(lambda v: v + 1)] 
    109 
    110        class Model(BaseModel): 
    111            a: MyInt 
    112 
    113        print(Model(a=1).a) 
    114        #> 2 
    115 
    116        try: 
    117            Model(a='a') 
    118        except TypeError as e: 
    119            print(e) 
    120            #> can only concatenate str (not "int") to str 
    121        ``` 
    122    """ 
    123 
    124    func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction 
    125    json_schema_input_type: Any = PydanticUndefined 
    126 
    127    def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: 
    128        schema = handler(source_type) 
    129        input_schema = ( 
    130            None 
    131            if self.json_schema_input_type is PydanticUndefined 
    132            else handler.generate_schema(self.json_schema_input_type) 
    133        ) 
    134 
    135        info_arg = _inspect_validator(self.func, mode='before', type='field') 
    136        if info_arg: 
    137            func = cast(core_schema.WithInfoValidatorFunction, self.func) 
    138            return core_schema.with_info_before_validator_function( 
    139                func, 
    140                schema=schema, 
    141                json_schema_input_schema=input_schema, 
    142            ) 
    143        else: 
    144            func = cast(core_schema.NoInfoValidatorFunction, self.func) 
    145            return core_schema.no_info_before_validator_function( 
    146                func, schema=schema, json_schema_input_schema=input_schema 
    147            ) 
    148 
    149    @classmethod 
    150    def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self: 
    151        return cls( 
    152            func=decorator.func, 
    153            json_schema_input_type=decorator.info.json_schema_input_type, 
    154        ) 
    155 
    156 
    157@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true) 
    158class PlainValidator: 
    159    """!!! abstract "Usage Documentation" 
    160        [field *plain* validators](../concepts/validators.md#field-plain-validator) 
    161 
    162    A metadata class that indicates that a validation should be applied **instead** of the inner validation logic. 
    163 
    164    !!! note 
    165        Before v2.9, `PlainValidator` wasn't always compatible with JSON Schema generation for `mode='validation'`. 
    166        You can now use the `json_schema_input_type` argument to specify the input type of the function 
    167        to be used in the JSON schema when `mode='validation'` (the default). See the example below for more details. 
    168 
    169    Attributes: 
    170        func: The validator function. 
    171        json_schema_input_type: The input type used to generate the appropriate 
    172            JSON Schema (in validation mode). The actual input type is `Any`. 
    173 
    174    Example: 
    175        ```python 
    176        from typing import Annotated, Union 
    177 
    178        from pydantic import BaseModel, PlainValidator 
    179 
    180        def validate(v: object) -> int: 
    181            if not isinstance(v, (int, str)): 
    182                raise ValueError(f'Expected int or str, go {type(v)}') 
    183 
    184            return int(v) + 1 
    185 
    186        MyInt = Annotated[ 
    187            int, 
    188            PlainValidator(validate, json_schema_input_type=Union[str, int]),  # (1)! 
    189        ] 
    190 
    191        class Model(BaseModel): 
    192            a: MyInt 
    193 
    194        print(Model(a='1').a) 
    195        #> 2 
    196 
    197        print(Model(a=1).a) 
    198        #> 2 
    199        ``` 
    200 
    201        1. In this example, we've specified the `json_schema_input_type` as `Union[str, int]` which indicates to the JSON schema 
    202        generator that in validation mode, the input type for the `a` field can be either a [`str`][] or an [`int`][]. 
    203    """ 
    204 
    205    func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction 
    206    json_schema_input_type: Any = Any 
    207 
    208    def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: 
    209        # Note that for some valid uses of PlainValidator, it is not possible to generate a core schema for the 
    210        # source_type, so calling `handler(source_type)` will error, which prevents us from generating a proper 
    211        # serialization schema. To work around this for use cases that will not involve serialization, we simply 
    212        # catch any PydanticSchemaGenerationError that may be raised while attempting to build the serialization schema 
    213        # and abort any attempts to handle special serialization. 
    214        from pydantic import PydanticSchemaGenerationError 
    215 
    216        try: 
    217            schema = handler(source_type) 
    218            # TODO if `schema['serialization']` is one of `'include-exclude-dict/sequence', 
    219            # schema validation will fail. That's why we use 'type ignore' comments below. 
    220            serialization = schema.get( 
    221                'serialization', 
    222                core_schema.wrap_serializer_function_ser_schema( 
    223                    function=lambda v, h: h(v), 
    224                    schema=schema, 
    225                    return_schema=handler.generate_schema(source_type), 
    226                ), 
    227            ) 
    228        except PydanticSchemaGenerationError: 
    229            serialization = None 
    230 
    231        input_schema = handler.generate_schema(self.json_schema_input_type) 
    232 
    233        info_arg = _inspect_validator(self.func, mode='plain', type='field') 
    234        if info_arg: 
    235            func = cast(core_schema.WithInfoValidatorFunction, self.func) 
    236            return core_schema.with_info_plain_validator_function( 
    237                func, 
    238                serialization=serialization,  # pyright: ignore[reportArgumentType] 
    239                json_schema_input_schema=input_schema, 
    240            ) 
    241        else: 
    242            func = cast(core_schema.NoInfoValidatorFunction, self.func) 
    243            return core_schema.no_info_plain_validator_function( 
    244                func, 
    245                serialization=serialization,  # pyright: ignore[reportArgumentType] 
    246                json_schema_input_schema=input_schema, 
    247            ) 
    248 
    249    @classmethod 
    250    def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self: 
    251        return cls( 
    252            func=decorator.func, 
    253            json_schema_input_type=decorator.info.json_schema_input_type, 
    254        ) 
    255 
    256 
    257@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true) 
    258class WrapValidator: 
    259    """!!! abstract "Usage Documentation" 
    260        [field *wrap* validators](../concepts/validators.md#field-wrap-validator) 
    261 
    262    A metadata class that indicates that a validation should be applied **around** the inner validation logic. 
    263 
    264    Attributes: 
    265        func: The validator function. 
    266        json_schema_input_type: The input type used to generate the appropriate 
    267            JSON Schema (in validation mode). The actual input type is `Any`. 
    268 
    269    ```python 
    270    from datetime import datetime 
    271    from typing import Annotated 
    272 
    273    from pydantic import BaseModel, ValidationError, WrapValidator 
    274 
    275    def validate_timestamp(v, handler): 
    276        if v == 'now': 
    277            # we don't want to bother with further validation, just return the new value 
    278            return datetime.now() 
    279        try: 
    280            return handler(v) 
    281        except ValidationError: 
    282            # validation failed, in this case we want to return a default value 
    283            return datetime(2000, 1, 1) 
    284 
    285    MyTimestamp = Annotated[datetime, WrapValidator(validate_timestamp)] 
    286 
    287    class Model(BaseModel): 
    288        a: MyTimestamp 
    289 
    290    print(Model(a='now').a) 
    291    #> 2032-01-02 03:04:05.000006 
    292    print(Model(a='invalid').a) 
    293    #> 2000-01-01 00:00:00 
    294    ``` 
    295    """ 
    296 
    297    func: core_schema.NoInfoWrapValidatorFunction | core_schema.WithInfoWrapValidatorFunction 
    298    json_schema_input_type: Any = PydanticUndefined 
    299 
    300    def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: 
    301        schema = handler(source_type) 
    302        input_schema = ( 
    303            None 
    304            if self.json_schema_input_type is PydanticUndefined 
    305            else handler.generate_schema(self.json_schema_input_type) 
    306        ) 
    307 
    308        info_arg = _inspect_validator(self.func, mode='wrap', type='field') 
    309        if info_arg: 
    310            func = cast(core_schema.WithInfoWrapValidatorFunction, self.func) 
    311            return core_schema.with_info_wrap_validator_function( 
    312                func, 
    313                schema=schema, 
    314                json_schema_input_schema=input_schema, 
    315            ) 
    316        else: 
    317            func = cast(core_schema.NoInfoWrapValidatorFunction, self.func) 
    318            return core_schema.no_info_wrap_validator_function( 
    319                func, 
    320                schema=schema, 
    321                json_schema_input_schema=input_schema, 
    322            ) 
    323 
    324    @classmethod 
    325    def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self: 
    326        return cls( 
    327            func=decorator.func, 
    328            json_schema_input_type=decorator.info.json_schema_input_type, 
    329        ) 
    330 
    331 
    332if TYPE_CHECKING: 
    333 
    334    class _OnlyValueValidatorClsMethod(Protocol): 
    335        def __call__(self, cls: Any, value: Any, /) -> Any: ... 
    336 
    337    class _V2ValidatorClsMethod(Protocol): 
    338        def __call__(self, cls: Any, value: Any, info: core_schema.ValidationInfo[Any], /) -> Any: ... 
    339 
    340    class _OnlyValueWrapValidatorClsMethod(Protocol): 
    341        def __call__(self, cls: Any, value: Any, handler: core_schema.ValidatorFunctionWrapHandler, /) -> Any: ... 
    342 
    343    class _V2WrapValidatorClsMethod(Protocol): 
    344        def __call__( 
    345            self, 
    346            cls: Any, 
    347            value: Any, 
    348            handler: core_schema.ValidatorFunctionWrapHandler, 
    349            info: core_schema.ValidationInfo[Any], 
    350            /, 
    351        ) -> Any: ... 
    352 
    353    _V2Validator = Union[ 
    354        _V2ValidatorClsMethod, 
    355        core_schema.WithInfoValidatorFunction, 
    356        _OnlyValueValidatorClsMethod, 
    357        core_schema.NoInfoValidatorFunction, 
    358    ] 
    359 
    360    _V2WrapValidator = Union[ 
    361        _V2WrapValidatorClsMethod, 
    362        core_schema.WithInfoWrapValidatorFunction, 
    363        _OnlyValueWrapValidatorClsMethod, 
    364        core_schema.NoInfoWrapValidatorFunction, 
    365    ] 
    366 
    367    _PartialClsOrStaticMethod: TypeAlias = Union[classmethod[Any, Any, Any], staticmethod[Any, Any], partialmethod[Any]] 
    368 
    369    _V2BeforeAfterOrPlainValidatorType = TypeVar( 
    370        '_V2BeforeAfterOrPlainValidatorType', 
    371        bound=Union[_V2Validator, _PartialClsOrStaticMethod], 
    372    ) 
    373    _V2WrapValidatorType = TypeVar('_V2WrapValidatorType', bound=Union[_V2WrapValidator, _PartialClsOrStaticMethod]) 
    374 
    375FieldValidatorModes: TypeAlias = Literal['before', 'after', 'wrap', 'plain'] 
    376 
    377 
    378@overload 
    379def field_validator( 
    380    field: str, 
    381    /, 
    382    *fields: str, 
    383    mode: Literal['wrap'], 
    384    check_fields: bool | None = ..., 
    385    json_schema_input_type: Any = ..., 
    386) -> Callable[[_V2WrapValidatorType], _V2WrapValidatorType]: ... 
    387 
    388 
    389@overload 
    390def field_validator( 
    391    field: str, 
    392    /, 
    393    *fields: str, 
    394    mode: Literal['before', 'plain'], 
    395    check_fields: bool | None = ..., 
    396    json_schema_input_type: Any = ..., 
    397) -> Callable[[_V2BeforeAfterOrPlainValidatorType], _V2BeforeAfterOrPlainValidatorType]: ... 
    398 
    399 
    400@overload 
    401def field_validator( 
    402    field: str, 
    403    /, 
    404    *fields: str, 
    405    mode: Literal['after'] = ..., 
    406    check_fields: bool | None = ..., 
    407) -> Callable[[_V2BeforeAfterOrPlainValidatorType], _V2BeforeAfterOrPlainValidatorType]: ... 
    408 
    409 
    410def field_validator( 
    411    field: str, 
    412    /, 
    413    *fields: str, 
    414    mode: FieldValidatorModes = 'after', 
    415    check_fields: bool | None = None, 
    416    json_schema_input_type: Any = PydanticUndefined, 
    417) -> Callable[[Any], Any]: 
    418    """!!! abstract "Usage Documentation" 
    419        [field validators](../concepts/validators.md#field-validators) 
    420 
    421    Decorate methods on the class indicating that they should be used to validate fields. 
    422 
    423    Example usage: 
    424    ```python 
    425    from typing import Any 
    426 
    427    from pydantic import ( 
    428        BaseModel, 
    429        ValidationError, 
    430        field_validator, 
    431    ) 
    432 
    433    class Model(BaseModel): 
    434        a: str 
    435 
    436        @field_validator('a') 
    437        @classmethod 
    438        def ensure_foobar(cls, v: Any): 
    439            if 'foobar' not in v: 
    440                raise ValueError('"foobar" not found in a') 
    441            return v 
    442 
    443    print(repr(Model(a='this is foobar good'))) 
    444    #> Model(a='this is foobar good') 
    445 
    446    try: 
    447        Model(a='snap') 
    448    except ValidationError as exc_info: 
    449        print(exc_info) 
    450        ''' 
    451        1 validation error for Model 
    452        a 
    453          Value error, "foobar" not found in a [type=value_error, input_value='snap', input_type=str] 
    454        ''' 
    455    ``` 
    456 
    457    For more in depth examples, see [Field Validators](../concepts/validators.md#field-validators). 
    458 
    459    Args: 
    460        field: The first field the `field_validator` should be called on; this is separate 
    461            from `fields` to ensure an error is raised if you don't pass at least one. 
    462        *fields: Additional field(s) the `field_validator` should be called on. 
    463        mode: Specifies whether to validate the fields before or after validation. 
    464        check_fields: Whether to check that the fields actually exist on the model. 
    465        json_schema_input_type: The input type of the function. This is only used to generate 
    466            the appropriate JSON Schema (in validation mode) and can only specified 
    467            when `mode` is either `'before'`, `'plain'` or `'wrap'`. 
    468 
    469    Returns: 
    470        A decorator that can be used to decorate a function to be used as a field_validator. 
    471 
    472    Raises: 
    473        PydanticUserError: 
    474            - If `@field_validator` is used bare (with no fields). 
    475            - If the args passed to `@field_validator` as fields are not strings. 
    476            - If `@field_validator` applied to instance methods. 
    477    """ 
    478    if isinstance(field, FunctionType): 
    479        raise PydanticUserError( 
    480            '`@field_validator` should be used with fields and keyword arguments, not bare. ' 
    481            "E.g. usage should be `@validator('<field_name>', ...)`", 
    482            code='validator-no-fields', 
    483        ) 
    484 
    485    if mode not in ('before', 'plain', 'wrap') and json_schema_input_type is not PydanticUndefined: 
    486        raise PydanticUserError( 
    487            f"`json_schema_input_type` can't be used when mode is set to {mode!r}", 
    488            code='validator-input-type', 
    489        ) 
    490 
    491    if json_schema_input_type is PydanticUndefined and mode == 'plain': 
    492        json_schema_input_type = Any 
    493 
    494    fields = field, *fields 
    495    if not all(isinstance(field, str) for field in fields): 
    496        raise PydanticUserError( 
    497            '`@field_validator` fields should be passed as separate string args. ' 
    498            "E.g. usage should be `@validator('<field_name_1>', '<field_name_2>', ...)`", 
    499            code='validator-invalid-fields', 
    500        ) 
    501 
    502    def dec( 
    503        f: Callable[..., Any] | staticmethod[Any, Any] | classmethod[Any, Any, Any], 
    504    ) -> _decorators.PydanticDescriptorProxy[Any]: 
    505        if _decorators.is_instance_method_from_sig(f): 
    506            raise PydanticUserError( 
    507                '`@field_validator` cannot be applied to instance methods', code='validator-instance-method' 
    508            ) 
    509 
    510        # auto apply the @classmethod decorator 
    511        f = _decorators.ensure_classmethod_based_on_signature(f) 
    512 
    513        dec_info = _decorators.FieldValidatorDecoratorInfo( 
    514            fields=fields, mode=mode, check_fields=check_fields, json_schema_input_type=json_schema_input_type 
    515        ) 
    516        return _decorators.PydanticDescriptorProxy(f, dec_info) 
    517 
    518    return dec 
    519 
    520 
    521_ModelType = TypeVar('_ModelType') 
    522_ModelTypeCo = TypeVar('_ModelTypeCo', covariant=True) 
    523 
    524 
    525class ModelWrapValidatorHandler(core_schema.ValidatorFunctionWrapHandler, Protocol[_ModelTypeCo]): 
    526    """`@model_validator` decorated function handler argument type. This is used when `mode='wrap'`.""" 
    527 
    528    def __call__(  # noqa: D102 
    529        self, 
    530        value: Any, 
    531        outer_location: str | int | None = None, 
    532        /, 
    533    ) -> _ModelTypeCo:  # pragma: no cover 
    534        ... 
    535 
    536 
    537class ModelWrapValidatorWithoutInfo(Protocol[_ModelType]): 
    538    """A `@model_validator` decorated function signature. 
    539    This is used when `mode='wrap'` and the function does not have info argument. 
    540    """ 
    541 
    542    def __call__(  # noqa: D102 
    543        self, 
    544        cls: type[_ModelType], 
    545        # this can be a dict, a model instance 
    546        # or anything else that gets passed to validate_python 
    547        # thus validators _must_ handle all cases 
    548        value: Any, 
    549        handler: ModelWrapValidatorHandler[_ModelType], 
    550        /, 
    551    ) -> _ModelType: ... 
    552 
    553 
    554class ModelWrapValidator(Protocol[_ModelType]): 
    555    """A `@model_validator` decorated function signature. This is used when `mode='wrap'`.""" 
    556 
    557    def __call__(  # noqa: D102 
    558        self, 
    559        cls: type[_ModelType], 
    560        # this can be a dict, a model instance 
    561        # or anything else that gets passed to validate_python 
    562        # thus validators _must_ handle all cases 
    563        value: Any, 
    564        handler: ModelWrapValidatorHandler[_ModelType], 
    565        info: core_schema.ValidationInfo, 
    566        /, 
    567    ) -> _ModelType: ... 
    568 
    569 
    570class FreeModelBeforeValidatorWithoutInfo(Protocol): 
    571    """A `@model_validator` decorated function signature. 
    572    This is used when `mode='before'` and the function does not have info argument. 
    573    """ 
    574 
    575    def __call__(  # noqa: D102 
    576        self, 
    577        # this can be a dict, a model instance 
    578        # or anything else that gets passed to validate_python 
    579        # thus validators _must_ handle all cases 
    580        value: Any, 
    581        /, 
    582    ) -> Any: ... 
    583 
    584 
    585class ModelBeforeValidatorWithoutInfo(Protocol): 
    586    """A `@model_validator` decorated function signature. 
    587    This is used when `mode='before'` and the function does not have info argument. 
    588    """ 
    589 
    590    def __call__(  # noqa: D102 
    591        self, 
    592        cls: Any, 
    593        # this can be a dict, a model instance 
    594        # or anything else that gets passed to validate_python 
    595        # thus validators _must_ handle all cases 
    596        value: Any, 
    597        /, 
    598    ) -> Any: ... 
    599 
    600 
    601class FreeModelBeforeValidator(Protocol): 
    602    """A `@model_validator` decorated function signature. This is used when `mode='before'`.""" 
    603 
    604    def __call__(  # noqa: D102 
    605        self, 
    606        # this can be a dict, a model instance 
    607        # or anything else that gets passed to validate_python 
    608        # thus validators _must_ handle all cases 
    609        value: Any, 
    610        info: core_schema.ValidationInfo[Any], 
    611        /, 
    612    ) -> Any: ... 
    613 
    614 
    615class ModelBeforeValidator(Protocol): 
    616    """A `@model_validator` decorated function signature. This is used when `mode='before'`.""" 
    617 
    618    def __call__(  # noqa: D102 
    619        self, 
    620        cls: Any, 
    621        # this can be a dict, a model instance 
    622        # or anything else that gets passed to validate_python 
    623        # thus validators _must_ handle all cases 
    624        value: Any, 
    625        info: core_schema.ValidationInfo[Any], 
    626        /, 
    627    ) -> Any: ... 
    628 
    629 
    630ModelAfterValidatorWithoutInfo = Callable[[_ModelType], _ModelType] 
    631"""A `@model_validator` decorated function signature. This is used when `mode='after'` and the function does not 
    632have info argument. 
    633""" 
    634 
    635ModelAfterValidator = Callable[[_ModelType, core_schema.ValidationInfo[Any]], _ModelType] 
    636"""A `@model_validator` decorated function signature. This is used when `mode='after'`.""" 
    637 
    638_AnyModelWrapValidator = Union[ModelWrapValidator[_ModelType], ModelWrapValidatorWithoutInfo[_ModelType]] 
    639_AnyModelBeforeValidator = Union[ 
    640    FreeModelBeforeValidator, ModelBeforeValidator, FreeModelBeforeValidatorWithoutInfo, ModelBeforeValidatorWithoutInfo 
    641] 
    642_AnyModelAfterValidator = Union[ModelAfterValidator[_ModelType], ModelAfterValidatorWithoutInfo[_ModelType]] 
    643 
    644 
    645@overload 
    646def model_validator( 
    647    *, 
    648    mode: Literal['wrap'], 
    649) -> Callable[ 
    650    [_AnyModelWrapValidator[_ModelType]], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo] 
    651]: ... 
    652 
    653 
    654@overload 
    655def model_validator( 
    656    *, 
    657    mode: Literal['before'], 
    658) -> Callable[ 
    659    [_AnyModelBeforeValidator], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo] 
    660]: ... 
    661 
    662 
    663@overload 
    664def model_validator( 
    665    *, 
    666    mode: Literal['after'], 
    667) -> Callable[ 
    668    [_AnyModelAfterValidator[_ModelType]], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo] 
    669]: ... 
    670 
    671 
    672def model_validator( 
    673    *, 
    674    mode: Literal['wrap', 'before', 'after'], 
    675) -> Any: 
    676    """!!! abstract "Usage Documentation" 
    677        [Model Validators](../concepts/validators.md#model-validators) 
    678 
    679    Decorate model methods for validation purposes. 
    680 
    681    Example usage: 
    682    ```python 
    683    from typing_extensions import Self 
    684 
    685    from pydantic import BaseModel, ValidationError, model_validator 
    686 
    687    class Square(BaseModel): 
    688        width: float 
    689        height: float 
    690 
    691        @model_validator(mode='after') 
    692        def verify_square(self) -> Self: 
    693            if self.width != self.height: 
    694                raise ValueError('width and height do not match') 
    695            return self 
    696 
    697    s = Square(width=1, height=1) 
    698    print(repr(s)) 
    699    #> Square(width=1.0, height=1.0) 
    700 
    701    try: 
    702        Square(width=1, height=2) 
    703    except ValidationError as e: 
    704        print(e) 
    705        ''' 
    706        1 validation error for Square 
    707          Value error, width and height do not match [type=value_error, input_value={'width': 1, 'height': 2}, input_type=dict] 
    708        ''' 
    709    ``` 
    710 
    711    For more in depth examples, see [Model Validators](../concepts/validators.md#model-validators). 
    712 
    713    Args: 
    714        mode: A required string literal that specifies the validation mode. 
    715            It can be one of the following: 'wrap', 'before', or 'after'. 
    716 
    717    Returns: 
    718        A decorator that can be used to decorate a function to be used as a model validator. 
    719    """ 
    720 
    721    def dec(f: Any) -> _decorators.PydanticDescriptorProxy[Any]: 
    722        # auto apply the @classmethod decorator. NOTE: in V3, do not apply the conversion for 'after' validators: 
    723        f = _decorators.ensure_classmethod_based_on_signature(f) 
    724        if mode == 'after' and isinstance(f, classmethod): 
    725            warnings.warn( 
    726                category=PydanticDeprecatedSince212, 
    727                message=( 
    728                    "Using `@model_validator` with mode='after' on a classmethod is deprecated. Instead, use an instance method. " 
    729                    f'See the documentation at https://docs.pydantic.dev/{version_short()}/concepts/validators/#model-after-validator.' 
    730                ), 
    731                stacklevel=2, 
    732            ) 
    733 
    734        dec_info = _decorators.ModelValidatorDecoratorInfo(mode=mode) 
    735        return _decorators.PydanticDescriptorProxy(f, dec_info) 
    736 
    737    return dec 
    738 
    739 
    740AnyType = TypeVar('AnyType') 
    741 
    742 
    743if TYPE_CHECKING: 
    744    # If we add configurable attributes to IsInstance, we'd probably need to stop hiding it from type checkers like this 
    745    InstanceOf = Annotated[AnyType, ...]  # `IsInstance[Sequence]` will be recognized by type checkers as `Sequence` 
    746 
    747else: 
    748 
    749    @dataclasses.dataclass(**_internal_dataclass.slots_true) 
    750    class InstanceOf: 
    751        '''Generic type for annotating a type that is an instance of a given class. 
    752 
    753        Example: 
    754            ```python 
    755            from pydantic import BaseModel, InstanceOf 
    756 
    757            class Foo: 
    758                ... 
    759 
    760            class Bar(BaseModel): 
    761                foo: InstanceOf[Foo] 
    762 
    763            Bar(foo=Foo()) 
    764            try: 
    765                Bar(foo=42) 
    766            except ValidationError as e: 
    767                print(e) 
    768                """ 
    769                [ 
    770                │   { 
    771                │   │   'type': 'is_instance_of', 
    772                │   │   'loc': ('foo',), 
    773                │   │   'msg': 'Input should be an instance of Foo', 
    774                │   │   'input': 42, 
    775                │   │   'ctx': {'class': 'Foo'}, 
    776                │   │   'url': 'https://errors.pydantic.dev/0.38.0/v/is_instance_of' 
    777                │   } 
    778                ] 
    779                """ 
    780            ``` 
    781        ''' 
    782 
    783        @classmethod 
    784        def __class_getitem__(cls, item: AnyType) -> AnyType: 
    785            return Annotated[item, cls()] 
    786 
    787        @classmethod 
    788        def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: 
    789            from pydantic import PydanticSchemaGenerationError 
    790 
    791            # use the generic _origin_ as the second argument to isinstance when appropriate 
    792            instance_of_schema = core_schema.is_instance_schema(_generics.get_origin(source) or source) 
    793 
    794            try: 
    795                # Try to generate the "standard" schema, which will be used when loading from JSON 
    796                original_schema = handler(source) 
    797            except PydanticSchemaGenerationError: 
    798                # If that fails, just produce a schema that can validate from python 
    799                return instance_of_schema 
    800            else: 
    801                # Use the "original" approach to serialization 
    802                instance_of_schema['serialization'] = core_schema.wrap_serializer_function_ser_schema( 
    803                    function=lambda v, h: h(v), schema=original_schema 
    804                ) 
    805                return core_schema.json_or_python_schema(python_schema=instance_of_schema, json_schema=original_schema) 
    806 
    807        __hash__ = object.__hash__ 
    808 
    809 
    810if TYPE_CHECKING: 
    811    SkipValidation = Annotated[AnyType, ...]  # SkipValidation[list[str]] will be treated by type checkers as list[str] 
    812else: 
    813 
    814    @dataclasses.dataclass(**_internal_dataclass.slots_true) 
    815    class SkipValidation: 
    816        """If this is applied as an annotation (e.g., via `x: Annotated[int, SkipValidation]`), validation will be 
    817            skipped. You can also use `SkipValidation[int]` as a shorthand for `Annotated[int, SkipValidation]`. 
    818 
    819        This can be useful if you want to use a type annotation for documentation/IDE/type-checking purposes, 
    820        and know that it is safe to skip validation for one or more of the fields. 
    821 
    822        Because this converts the validation schema to `any_schema`, subsequent annotation-applied transformations 
    823        may not have the expected effects. Therefore, when used, this annotation should generally be the final 
    824        annotation applied to a type. 
    825        """ 
    826 
    827        def __class_getitem__(cls, item: Any) -> Any: 
    828            return Annotated[item, SkipValidation()] 
    829 
    830        @classmethod 
    831        def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: 
    832            with warnings.catch_warnings(): 
    833                warnings.simplefilter('ignore', ArbitraryTypeWarning) 
    834                original_schema = handler(source) 
    835            metadata = {'pydantic_js_annotation_functions': [lambda _c, h: h(original_schema)]} 
    836            return core_schema.any_schema( 
    837                metadata=metadata, 
    838                serialization=core_schema.wrap_serializer_function_ser_schema( 
    839                    function=lambda v, h: h(v), schema=original_schema 
    840                ), 
    841            ) 
    842 
    843        __hash__ = object.__hash__ 
    844 
    845 
    846_FromTypeT = TypeVar('_FromTypeT') 
    847 
    848 
    849class ValidateAs: 
    850    """A helper class to validate a custom type from a type that is natively supported by Pydantic. 
    851 
    852    Args: 
    853        from_type: The type natively supported by Pydantic to use to perform validation. 
    854        instantiation_hook: A callable taking the validated type as an argument, and returning 
    855            the populated custom type. 
    856 
    857    Example: 
    858        ```python {lint="skip"} 
    859        from typing import Annotated 
    860 
    861        from pydantic import BaseModel, TypeAdapter, ValidateAs 
    862 
    863        class MyCls: 
    864            def __init__(self, a: int) -> None: 
    865                self.a = a 
    866 
    867            def __repr__(self) -> str: 
    868                return f"MyCls(a={self.a})" 
    869 
    870        class Model(BaseModel): 
    871            a: int 
    872 
    873 
    874        ta = TypeAdapter( 
    875            Annotated[MyCls, ValidateAs(Model, lambda v: MyCls(a=v.a))] 
    876        ) 
    877 
    878        print(ta.validate_python({'a': 1})) 
    879        #> MyCls(a=1) 
    880        ``` 
    881    """ 
    882 
    883    # TODO: make use of PEP 747 
    884    def __init__(self, from_type: type[_FromTypeT], /, instantiation_hook: Callable[[_FromTypeT], Any]) -> None: 
    885        self.from_type = from_type 
    886        self.instantiation_hook = instantiation_hook 
    887 
    888    def __get_pydantic_core_schema__(self, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: 
    889        schema = handler(self.from_type) 
    890        return core_schema.no_info_after_validator_function( 
    891            self.instantiation_hook, 
    892            schema=schema, 
    893        )