Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
functional_validators.py890 linesDownload Raw Back to pydantic
1"""This module contains related classes and functions for validation."""2 3from __future__ import annotations as _annotations4 5import dataclasses6import sys7import warnings8from functools import partialmethod9from typing import TYPE_CHECKING, Annotated, Any, Callable, Literal, TypeVar, Union, cast, overload10 11from pydantic_core import PydanticUndefined, core_schema12from typing_extensions import Self, TypeAlias13 14from ._internal import _decorators, _generics, _internal_dataclass15from .annotated_handlers import GetCoreSchemaHandler16from .errors import PydanticUserError17from .version import version_short18from .warnings import ArbitraryTypeWarning, PydanticDeprecatedSince21219 20if sys.version_info < (3, 11):21    from typing_extensions import Protocol22else:23    from typing import Protocol24 25_inspect_validator = _decorators.inspect_validator26 27 28@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true)29class AfterValidator:30    """!!! abstract "Usage Documentation"31        [field *after* validators](../concepts/validators.md#field-after-validator)32 33    A metadata class that indicates that a validation should be applied **after** the inner validation logic.34 35    Attributes:36        func: The validator function.37 38    Example:39        ```python40        from typing import Annotated41 42        from pydantic import AfterValidator, BaseModel, ValidationError43 44        MyInt = Annotated[int, AfterValidator(lambda v: v + 1)]45 46        class Model(BaseModel):47            a: MyInt48 49        print(Model(a=1).a)50        #> 251 52        try:53            Model(a='a')54        except ValidationError as e:55            print(e.json(indent=2))56            '''57            [58              {59                "type": "int_parsing",60                "loc": [61                  "a"62                ],63                "msg": "Input should be a valid integer, unable to parse string as an integer",64                "input": "a",65                "url": "https://errors.pydantic.dev/2/v/int_parsing"66              }67            ]68            '''69        ```70    """71 72    func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction73 74    def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:75        schema = handler(source_type)76        info_arg = _inspect_validator(self.func, mode='after', type='field')77        if info_arg:78            func = cast(core_schema.WithInfoValidatorFunction, self.func)79            return core_schema.with_info_after_validator_function(func, schema=schema)80        else:81            func = cast(core_schema.NoInfoValidatorFunction, self.func)82            return core_schema.no_info_after_validator_function(func, schema=schema)83 84    @classmethod85    def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self:86        return cls(func=decorator.func)87 88 89@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true)90class BeforeValidator:91    """!!! abstract "Usage Documentation"92        [field *before* validators](../concepts/validators.md#field-before-validator)93 94    A metadata class that indicates that a validation should be applied **before** the inner validation logic.95 96    Attributes:97        func: The validator function.98        json_schema_input_type: The input type used to generate the appropriate99            JSON Schema (in validation mode). The actual input type is `Any`.100 101    Example:102        ```python103        from typing import Annotated104 105        from pydantic import BaseModel, BeforeValidator106 107        MyInt = Annotated[int, BeforeValidator(lambda v: v + 1)]108 109        class Model(BaseModel):110            a: MyInt111 112        print(Model(a=1).a)113        #> 2114 115        try:116            Model(a='a')117        except TypeError as e:118            print(e)119            #> can only concatenate str (not "int") to str120        ```121    """122 123    func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction124    json_schema_input_type: Any = PydanticUndefined125 126    def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:127        schema = handler(source_type)128        input_schema = (129            None130            if self.json_schema_input_type is PydanticUndefined131            else handler.generate_schema(self.json_schema_input_type)132        )133 134        info_arg = _inspect_validator(self.func, mode='before', type='field')135        if info_arg:136            func = cast(core_schema.WithInfoValidatorFunction, self.func)137            return core_schema.with_info_before_validator_function(138                func,139                schema=schema,140                json_schema_input_schema=input_schema,141            )142        else:143            func = cast(core_schema.NoInfoValidatorFunction, self.func)144            return core_schema.no_info_before_validator_function(145                func, schema=schema, json_schema_input_schema=input_schema146            )147 148    @classmethod149    def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self:150        return cls(151            func=decorator.func,152            json_schema_input_type=decorator.info.json_schema_input_type,153        )154 155 156@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true)157class PlainValidator:158    """!!! abstract "Usage Documentation"159        [field *plain* validators](../concepts/validators.md#field-plain-validator)160 161    A metadata class that indicates that a validation should be applied **instead** of the inner validation logic.162 163    !!! note164        Before v2.9, `PlainValidator` wasn't always compatible with JSON Schema generation for `mode='validation'`.165        You can now use the `json_schema_input_type` argument to specify the input type of the function166        to be used in the JSON schema when `mode='validation'` (the default). See the example below for more details.167 168    Attributes:169        func: The validator function.170        json_schema_input_type: The input type used to generate the appropriate171            JSON Schema (in validation mode). The actual input type is `Any`.172 173    Example:174        ```python175        from typing import Annotated, Union176 177        from pydantic import BaseModel, PlainValidator178 179        def validate(v: object) -> int:180            if not isinstance(v, (int, str)):181                raise ValueError(f'Expected int or str, got {type(v)}')182 183            return int(v) + 1184 185        MyInt = Annotated[186            int,187            PlainValidator(validate, json_schema_input_type=Union[str, int]),  # (1)!188        ]189 190        class Model(BaseModel):191            a: MyInt192 193        print(Model(a='1').a)194        #> 2195 196        print(Model(a=1).a)197        #> 2198        ```199 200        1. In this example, we've specified the `json_schema_input_type` as `Union[str, int]` which indicates to the JSON schema201        generator that in validation mode, the input type for the `a` field can be either a [`str`][] or an [`int`][].202    """203 204    func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction205    json_schema_input_type: Any = Any206 207    def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:208        # Note that for some valid uses of PlainValidator, it is not possible to generate a core schema for the209        # source_type, so calling `handler(source_type)` will error, which prevents us from generating a proper210        # serialization schema. To work around this for use cases that will not involve serialization, we simply211        # catch any PydanticSchemaGenerationError that may be raised while attempting to build the serialization schema212        # and abort any attempts to handle special serialization.213        from pydantic import PydanticSchemaGenerationError214 215        try:216            schema = handler(source_type)217            # TODO if `schema['serialization']` is one of `'include-exclude-dict/sequence',218            # schema validation will fail. That's why we use 'type ignore' comments below.219            serialization = schema.get(220                'serialization',221                core_schema.wrap_serializer_function_ser_schema(222                    function=lambda v, h: h(v),223                    schema=schema,224                    return_schema=handler.generate_schema(source_type),225                ),226            )227        except PydanticSchemaGenerationError:228            serialization = None229 230        input_schema = handler.generate_schema(self.json_schema_input_type)231 232        info_arg = _inspect_validator(self.func, mode='plain', type='field')233        if info_arg:234            func = cast(core_schema.WithInfoValidatorFunction, self.func)235            return core_schema.with_info_plain_validator_function(236                func,237                serialization=serialization,  # pyright: ignore[reportArgumentType]238                json_schema_input_schema=input_schema,239            )240        else:241            func = cast(core_schema.NoInfoValidatorFunction, self.func)242            return core_schema.no_info_plain_validator_function(243                func,244                serialization=serialization,  # pyright: ignore[reportArgumentType]245                json_schema_input_schema=input_schema,246            )247 248    @classmethod249    def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self:250        return cls(251            func=decorator.func,252            json_schema_input_type=decorator.info.json_schema_input_type,253        )254 255 256@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true)257class WrapValidator:258    """!!! abstract "Usage Documentation"259        [field *wrap* validators](../concepts/validators.md#field-wrap-validator)260 261    A metadata class that indicates that a validation should be applied **around** the inner validation logic.262 263    Attributes:264        func: The validator function.265        json_schema_input_type: The input type used to generate the appropriate266            JSON Schema (in validation mode). The actual input type is `Any`.267 268    ```python269    from datetime import datetime270    from typing import Annotated271 272    from pydantic import BaseModel, ValidationError, WrapValidator273 274    def validate_timestamp(v, handler):275        if v == 'now':276            # we don't want to bother with further validation, just return the new value277            return datetime.now()278        try:279            return handler(v)280        except ValidationError:281            # validation failed, in this case we want to return a default value282            return datetime(2000, 1, 1)283 284    MyTimestamp = Annotated[datetime, WrapValidator(validate_timestamp)]285 286    class Model(BaseModel):287        a: MyTimestamp288 289    print(Model(a='now').a)290    #> 2032-01-02 03:04:05.000006291    print(Model(a='invalid').a)292    #> 2000-01-01 00:00:00293    ```294    """295 296    func: core_schema.NoInfoWrapValidatorFunction | core_schema.WithInfoWrapValidatorFunction297    json_schema_input_type: Any = PydanticUndefined298 299    def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:300        schema = handler(source_type)301        input_schema = (302            None303            if self.json_schema_input_type is PydanticUndefined304            else handler.generate_schema(self.json_schema_input_type)305        )306 307        info_arg = _inspect_validator(self.func, mode='wrap', type='field')308        if info_arg:309            func = cast(core_schema.WithInfoWrapValidatorFunction, self.func)310            return core_schema.with_info_wrap_validator_function(311                func,312                schema=schema,313                json_schema_input_schema=input_schema,314            )315        else:316            func = cast(core_schema.NoInfoWrapValidatorFunction, self.func)317            return core_schema.no_info_wrap_validator_function(318                func,319                schema=schema,320                json_schema_input_schema=input_schema,321            )322 323    @classmethod324    def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self:325        return cls(326            func=decorator.func,327            json_schema_input_type=decorator.info.json_schema_input_type,328        )329 330 331if TYPE_CHECKING:332 333    class _OnlyValueValidatorClsMethod(Protocol):334        def __call__(self, cls: Any, value: Any, /) -> Any: ...335 336    class _V2ValidatorClsMethod(Protocol):337        def __call__(self, cls: Any, value: Any, info: core_schema.ValidationInfo[Any], /) -> Any: ...338 339    class _OnlyValueWrapValidatorClsMethod(Protocol):340        def __call__(self, cls: Any, value: Any, handler: core_schema.ValidatorFunctionWrapHandler, /) -> Any: ...341 342    class _V2WrapValidatorClsMethod(Protocol):343        def __call__(344            self,345            cls: Any,346            value: Any,347            handler: core_schema.ValidatorFunctionWrapHandler,348            info: core_schema.ValidationInfo[Any],349            /,350        ) -> Any: ...351 352    _V2Validator = Union[353        _V2ValidatorClsMethod,354        core_schema.WithInfoValidatorFunction,355        _OnlyValueValidatorClsMethod,356        core_schema.NoInfoValidatorFunction,357    ]358 359    _V2WrapValidator = Union[360        _V2WrapValidatorClsMethod,361        core_schema.WithInfoWrapValidatorFunction,362        _OnlyValueWrapValidatorClsMethod,363        core_schema.NoInfoWrapValidatorFunction,364    ]365 366    _PartialClsOrStaticMethod: TypeAlias = Union[classmethod[Any, Any, Any], staticmethod[Any, Any], partialmethod[Any]]367 368    _V2BeforeAfterOrPlainValidatorType = TypeVar(369        '_V2BeforeAfterOrPlainValidatorType',370        bound=Union[_V2Validator, _PartialClsOrStaticMethod],371    )372    _V2WrapValidatorType = TypeVar('_V2WrapValidatorType', bound=Union[_V2WrapValidator, _PartialClsOrStaticMethod])373 374FieldValidatorModes: TypeAlias = Literal['before', 'after', 'wrap', 'plain']375 376 377@overload378def field_validator(379    field: str,380    /,381    *fields: str,382    mode: Literal['wrap'],383    check_fields: bool | None = ...,384    json_schema_input_type: Any = ...,385) -> Callable[[_V2WrapValidatorType], _V2WrapValidatorType]: ...386 387 388@overload389def field_validator(390    field: str,391    /,392    *fields: str,393    mode: Literal['before', 'plain'],394    check_fields: bool | None = ...,395    json_schema_input_type: Any = ...,396) -> Callable[[_V2BeforeAfterOrPlainValidatorType], _V2BeforeAfterOrPlainValidatorType]: ...397 398 399@overload400def field_validator(401    field: str,402    /,403    *fields: str,404    mode: Literal['after'] = ...,405    check_fields: bool | None = ...,406) -> Callable[[_V2BeforeAfterOrPlainValidatorType], _V2BeforeAfterOrPlainValidatorType]: ...407 408 409def field_validator(  # noqa: D417410    field: str,411    /,412    *fields: str,413    mode: FieldValidatorModes = 'after',414    check_fields: bool | None = None,415    json_schema_input_type: Any = PydanticUndefined,416) -> Callable[[Any], Any]:417    """!!! abstract "Usage Documentation"418        [field validators](../concepts/validators.md#field-validators)419 420    Decorate methods on the class indicating that they should be used to validate fields.421 422    Example usage:423    ```python424    from typing import Any425 426    from pydantic import (427        BaseModel,428        ValidationError,429        field_validator,430    )431 432    class Model(BaseModel):433        a: str434 435        @field_validator('a')436        @classmethod437        def ensure_foobar(cls, v: Any):438            if 'foobar' not in v:439                raise ValueError('"foobar" not found in a')440            return v441 442    print(repr(Model(a='this is foobar good')))443    #> Model(a='this is foobar good')444 445    try:446        Model(a='snap')447    except ValidationError as exc_info:448        print(exc_info)449        '''450        1 validation error for Model451        a452          Value error, "foobar" not found in a [type=value_error, input_value='snap', input_type=str]453        '''454    ```455 456    For more in depth examples, see [Field Validators](../concepts/validators.md#field-validators).457 458    Args:459        *fields: The field names the validator should apply to.460        mode: Specifies whether to validate the fields before or after validation.461        check_fields: Whether to check that the fields actually exist on the model.462        json_schema_input_type: The input type of the function. This is only used to generate463            the appropriate JSON Schema (in validation mode) and can only specified464            when `mode` is either `'before'`, `'plain'` or `'wrap'`.465 466    Raises:467        PydanticUserError:468            - If the decorator is used without any arguments (at least one field name must be provided).469            - If the provided field names are not strings.470            - If `json_schema_input_type` is provided with an unsupported `mode`.471            - If the decorator is applied to an instance method.472    """473    if callable(field) or isinstance(field, classmethod):474        raise PydanticUserError(475            'The `@field_validator` decorator cannot be used without arguments, at least one field must be provided. '476            "For example: `@field_validator('<field_name>', ...)`.",477            code='decorator-missing-arguments',478        )479 480    if mode not in ('before', 'plain', 'wrap') and json_schema_input_type is not PydanticUndefined:481        raise PydanticUserError(482            f"`json_schema_input_type` can't be used when mode is set to {mode!r}",483            code='validator-input-type',484        )485 486    if json_schema_input_type is PydanticUndefined and mode == 'plain':487        json_schema_input_type = Any488 489    fields = field, *fields490    if not all(isinstance(field, str) for field in fields):491        raise PydanticUserError(492            'The provided field names to the `@field_validator` decorator should be strings. '493            "For example: `@field_validator('<field_name_1>', '<field_name_2>', ...).`",494            code='decorator-invalid-fields',495        )496 497    def dec(498        f: Callable[..., Any] | staticmethod[Any, Any] | classmethod[Any, Any, Any],499    ) -> _decorators.PydanticDescriptorProxy[Any]:500        if _decorators.is_instance_method_from_sig(f):501            raise PydanticUserError(502                'The `@field_validator` decorator cannot be applied to instance methods',503                code='validator-instance-method',504            )505 506        # auto apply the @classmethod decorator507        f = _decorators.ensure_classmethod_based_on_signature(f)508 509        dec_info = _decorators.FieldValidatorDecoratorInfo(510            fields=fields, mode=mode, check_fields=check_fields, json_schema_input_type=json_schema_input_type511        )512        return _decorators.PydanticDescriptorProxy(f, dec_info)513 514    return dec515 516 517_ModelType = TypeVar('_ModelType')518_ModelTypeCo = TypeVar('_ModelTypeCo', covariant=True)519 520 521class ModelWrapValidatorHandler(core_schema.ValidatorFunctionWrapHandler, Protocol[_ModelTypeCo]):522    """`@model_validator` decorated function handler argument type. This is used when `mode='wrap'`."""523 524    def __call__(  # noqa: D102525        self,526        value: Any,527        outer_location: str | int | None = None,528        /,529    ) -> _ModelTypeCo:  # pragma: no cover530        ...531 532 533class ModelWrapValidatorWithoutInfo(Protocol[_ModelType]):534    """A `@model_validator` decorated function signature.535    This is used when `mode='wrap'` and the function does not have info argument.536    """537 538    def __call__(  # noqa: D102539        self,540        cls: type[_ModelType],541        # this can be a dict, a model instance542        # or anything else that gets passed to validate_python543        # thus validators _must_ handle all cases544        value: Any,545        handler: ModelWrapValidatorHandler[_ModelType],546        /,547    ) -> _ModelType: ...548 549 550class ModelWrapValidator(Protocol[_ModelType]):551    """A `@model_validator` decorated function signature. This is used when `mode='wrap'`."""552 553    def __call__(  # noqa: D102554        self,555        cls: type[_ModelType],556        # this can be a dict, a model instance557        # or anything else that gets passed to validate_python558        # thus validators _must_ handle all cases559        value: Any,560        handler: ModelWrapValidatorHandler[_ModelType],561        info: core_schema.ValidationInfo,562        /,563    ) -> _ModelType: ...564 565 566class FreeModelBeforeValidatorWithoutInfo(Protocol):567    """A `@model_validator` decorated function signature.568    This is used when `mode='before'` and the function does not have info argument.569    """570 571    def __call__(  # noqa: D102572        self,573        # this can be a dict, a model instance574        # or anything else that gets passed to validate_python575        # thus validators _must_ handle all cases576        value: Any,577        /,578    ) -> Any: ...579 580 581class ModelBeforeValidatorWithoutInfo(Protocol):582    """A `@model_validator` decorated function signature.583    This is used when `mode='before'` and the function does not have info argument.584    """585 586    def __call__(  # noqa: D102587        self,588        cls: Any,589        # this can be a dict, a model instance590        # or anything else that gets passed to validate_python591        # thus validators _must_ handle all cases592        value: Any,593        /,594    ) -> Any: ...595 596 597class FreeModelBeforeValidator(Protocol):598    """A `@model_validator` decorated function signature. This is used when `mode='before'`."""599 600    def __call__(  # noqa: D102601        self,602        # this can be a dict, a model instance603        # or anything else that gets passed to validate_python604        # thus validators _must_ handle all cases605        value: Any,606        info: core_schema.ValidationInfo[Any],607        /,608    ) -> Any: ...609 610 611class ModelBeforeValidator(Protocol):612    """A `@model_validator` decorated function signature. This is used when `mode='before'`."""613 614    def __call__(  # noqa: D102615        self,616        cls: Any,617        # this can be a dict, a model instance618        # or anything else that gets passed to validate_python619        # thus validators _must_ handle all cases620        value: Any,621        info: core_schema.ValidationInfo[Any],622        /,623    ) -> Any: ...624 625 626ModelAfterValidatorWithoutInfo = Callable[[_ModelType], _ModelType]627"""A `@model_validator` decorated function signature. This is used when `mode='after'` and the function does not628have info argument.629"""630 631ModelAfterValidator = Callable[[_ModelType, core_schema.ValidationInfo[Any]], _ModelType]632"""A `@model_validator` decorated function signature. This is used when `mode='after'`."""633 634_AnyModelWrapValidator = Union[ModelWrapValidator[_ModelType], ModelWrapValidatorWithoutInfo[_ModelType]]635_AnyModelBeforeValidator = Union[636    FreeModelBeforeValidator, ModelBeforeValidator, FreeModelBeforeValidatorWithoutInfo, ModelBeforeValidatorWithoutInfo637]638_AnyModelAfterValidator = Union[ModelAfterValidator[_ModelType], ModelAfterValidatorWithoutInfo[_ModelType]]639 640 641@overload642def model_validator(643    *,644    mode: Literal['wrap'],645) -> Callable[646    [_AnyModelWrapValidator[_ModelType]], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]647]: ...648 649 650@overload651def model_validator(652    *,653    mode: Literal['before'],654) -> Callable[655    [_AnyModelBeforeValidator], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]656]: ...657 658 659@overload660def model_validator(661    *,662    mode: Literal['after'],663) -> Callable[664    [_AnyModelAfterValidator[_ModelType]], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]665]: ...666 667 668def model_validator(669    *,670    mode: Literal['wrap', 'before', 'after'],671) -> Any:672    """!!! abstract "Usage Documentation"673        [Model Validators](../concepts/validators.md#model-validators)674 675    Decorate model methods for validation purposes.676 677    Example usage:678    ```python679    from typing_extensions import Self680 681    from pydantic import BaseModel, ValidationError, model_validator682 683    class Square(BaseModel):684        width: float685        height: float686 687        @model_validator(mode='after')688        def verify_square(self) -> Self:689            if self.width != self.height:690                raise ValueError('width and height do not match')691            return self692 693    s = Square(width=1, height=1)694    print(repr(s))695    #> Square(width=1.0, height=1.0)696 697    try:698        Square(width=1, height=2)699    except ValidationError as e:700        print(e)701        '''702        1 validation error for Square703          Value error, width and height do not match [type=value_error, input_value={'width': 1, 'height': 2}, input_type=dict]704        '''705    ```706 707    For more in depth examples, see [Model Validators](../concepts/validators.md#model-validators).708 709    Args:710        mode: A required string literal that specifies the validation mode.711            It can be one of the following: 'wrap', 'before', or 'after'.712 713    Returns:714        A decorator that can be used to decorate a function to be used as a model validator.715    """716 717    def dec(f: Any) -> _decorators.PydanticDescriptorProxy[Any]:718        # auto apply the @classmethod decorator. NOTE: in V3, do not apply the conversion for 'after' validators:719        f = _decorators.ensure_classmethod_based_on_signature(f)720        if mode == 'after' and isinstance(f, classmethod):721            warnings.warn(722                category=PydanticDeprecatedSince212,723                message=(724                    "Using `@model_validator` with mode='after' on a classmethod is deprecated. Instead, use an instance method. "725                    f'See the documentation at https://docs.pydantic.dev/{version_short()}/concepts/validators/#model-after-validator.'726                ),727                stacklevel=2,728            )729 730        dec_info = _decorators.ModelValidatorDecoratorInfo(mode=mode)731        return _decorators.PydanticDescriptorProxy(f, dec_info)732 733    return dec734 735 736AnyType = TypeVar('AnyType')737 738 739if TYPE_CHECKING:740    # If we add configurable attributes to IsInstance, we'd probably need to stop hiding it from type checkers like this741    InstanceOf = Annotated[AnyType, ...]  # `IsInstance[Sequence]` will be recognized by type checkers as `Sequence`742 743else:744 745    @dataclasses.dataclass(**_internal_dataclass.slots_true)746    class InstanceOf:747        '''Generic type for annotating a type that is an instance of a given class.748 749        Example:750            ```python751            from pydantic import BaseModel, InstanceOf752 753            class Foo:754                ...755 756            class Bar(BaseModel):757                foo: InstanceOf[Foo]758 759            Bar(foo=Foo())760            try:761                Bar(foo=42)762            except ValidationError as e:763                print(e)764                """765                [766                │   {767                │   │   'type': 'is_instance_of',768                │   │   'loc': ('foo',),769                │   │   'msg': 'Input should be an instance of Foo',770                │   │   'input': 42,771                │   │   'ctx': {'class': 'Foo'},772                │   │   'url': 'https://errors.pydantic.dev/0.38.0/v/is_instance_of'773                │   }774                ]775                """776            ```777        '''778 779        @classmethod780        def __class_getitem__(cls, item: AnyType) -> AnyType:781            return Annotated[item, cls()]782 783        @classmethod784        def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:785            from pydantic._internal._generate_schema import GENERATE_SCHEMA_ERRORS786 787            # use the generic _origin_ as the second argument to isinstance when appropriate788            instance_of_schema = core_schema.is_instance_schema(_generics.get_origin(source) or source)789 790            try:791                # Try to generate the "standard" schema, which will be used when loading from JSON792                original_schema = handler(source)793            except GENERATE_SCHEMA_ERRORS:794                # If that fails, just produce a schema that can validate from python795                return instance_of_schema796            else:797                # Use the "original" approach to serialization798                instance_of_schema['serialization'] = core_schema.wrap_serializer_function_ser_schema(799                    function=lambda v, h: h(v), schema=original_schema800                )801                return core_schema.json_or_python_schema(python_schema=instance_of_schema, json_schema=original_schema)802 803        __hash__ = object.__hash__804 805 806if TYPE_CHECKING:807    SkipValidation = Annotated[AnyType, ...]  # SkipValidation[list[str]] will be treated by type checkers as list[str]808else:809 810    @dataclasses.dataclass(**_internal_dataclass.slots_true)811    class SkipValidation:812        """If this is applied as an annotation (e.g., via `x: Annotated[int, SkipValidation]`), validation will be813            skipped. You can also use `SkipValidation[int]` as a shorthand for `Annotated[int, SkipValidation]`.814 815        This can be useful if you want to use a type annotation for documentation/IDE/type-checking purposes,816        and know that it is safe to skip validation for one or more of the fields.817 818        Because this converts the validation schema to `any_schema`, subsequent annotation-applied transformations819        may not have the expected effects. Therefore, when used, this annotation should generally be the final820        annotation applied to a type.821        """822 823        def __class_getitem__(cls, item: Any) -> Any:824            return Annotated[item, SkipValidation()]825 826        @classmethod827        def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:828            with warnings.catch_warnings():829                warnings.simplefilter('ignore', ArbitraryTypeWarning)830                original_schema = handler(source)831            metadata = {'pydantic_js_annotation_functions': [lambda _c, h: h(original_schema)]}832            return core_schema.any_schema(833                metadata=metadata,834                serialization=core_schema.wrap_serializer_function_ser_schema(835                    function=lambda v, h: h(v), schema=original_schema836                ),837            )838 839        __hash__ = object.__hash__840 841 842_FromTypeT = TypeVar('_FromTypeT')843 844 845class ValidateAs:846    """A helper class to validate a custom type from a type that is natively supported by Pydantic.847 848    Args:849        from_type: The type natively supported by Pydantic to use to perform validation.850        instantiation_hook: A callable taking the validated type as an argument, and returning851            the populated custom type.852 853    Example:854        ```python {lint="skip"}855        from typing import Annotated856 857        from pydantic import BaseModel, TypeAdapter, ValidateAs858 859        class MyCls:860            def __init__(self, a: int) -> None:861                self.a = a862 863            def __repr__(self) -> str:864                return f"MyCls(a={self.a})"865 866        class Model(BaseModel):867            a: int868 869 870        ta = TypeAdapter(871            Annotated[MyCls, ValidateAs(Model, lambda v: MyCls(a=v.a))]872        )873 874        print(ta.validate_python({'a': 1}))875        #> MyCls(a=1)876        ```877    """878 879    # TODO: make use of PEP 747880    def __init__(self, from_type: type[_FromTypeT], /, instantiation_hook: Callable[[_FromTypeT], Any]) -> None:881        self.from_type = from_type882        self.instantiation_hook = instantiation_hook883 884    def __get_pydantic_core_schema__(self, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:885        schema = handler(self.from_type)886        return core_schema.no_info_after_validator_function(887            self.instantiation_hook,888            schema=schema,889        )890 
codekingpro/portable-devtools · Team Ai