diff options
Diffstat (limited to '.venv/lib/python3.12/site-packages/pydantic/deprecated/class_validators.py')
-rw-r--r-- | .venv/lib/python3.12/site-packages/pydantic/deprecated/class_validators.py | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/pydantic/deprecated/class_validators.py b/.venv/lib/python3.12/site-packages/pydantic/deprecated/class_validators.py new file mode 100644 index 00000000..810b4687 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/pydantic/deprecated/class_validators.py @@ -0,0 +1,256 @@ +"""Old `@validator` and `@root_validator` function validators from V1.""" + +from __future__ import annotations as _annotations + +from functools import partial, partialmethod +from types import FunctionType +from typing import TYPE_CHECKING, Any, Callable, TypeVar, Union, overload +from warnings import warn + +from typing_extensions import Literal, Protocol, TypeAlias, deprecated + +from .._internal import _decorators, _decorators_v1 +from ..errors import PydanticUserError +from ..warnings import PydanticDeprecatedSince20 + +_ALLOW_REUSE_WARNING_MESSAGE = '`allow_reuse` is deprecated and will be ignored; it should no longer be necessary' + + +if TYPE_CHECKING: + + class _OnlyValueValidatorClsMethod(Protocol): + def __call__(self, __cls: Any, __value: Any) -> Any: ... + + class _V1ValidatorWithValuesClsMethod(Protocol): + def __call__(self, __cls: Any, __value: Any, values: dict[str, Any]) -> Any: ... + + class _V1ValidatorWithValuesKwOnlyClsMethod(Protocol): + def __call__(self, __cls: Any, __value: Any, *, values: dict[str, Any]) -> Any: ... + + class _V1ValidatorWithKwargsClsMethod(Protocol): + def __call__(self, __cls: Any, **kwargs: Any) -> Any: ... + + class _V1ValidatorWithValuesAndKwargsClsMethod(Protocol): + def __call__(self, __cls: Any, values: dict[str, Any], **kwargs: Any) -> Any: ... + + class _V1RootValidatorClsMethod(Protocol): + def __call__( + self, __cls: Any, __values: _decorators_v1.RootValidatorValues + ) -> _decorators_v1.RootValidatorValues: ... + + V1Validator = Union[ + _OnlyValueValidatorClsMethod, + _V1ValidatorWithValuesClsMethod, + _V1ValidatorWithValuesKwOnlyClsMethod, + _V1ValidatorWithKwargsClsMethod, + _V1ValidatorWithValuesAndKwargsClsMethod, + _decorators_v1.V1ValidatorWithValues, + _decorators_v1.V1ValidatorWithValuesKwOnly, + _decorators_v1.V1ValidatorWithKwargs, + _decorators_v1.V1ValidatorWithValuesAndKwargs, + ] + + V1RootValidator = Union[ + _V1RootValidatorClsMethod, + _decorators_v1.V1RootValidatorFunction, + ] + + _PartialClsOrStaticMethod: TypeAlias = Union[classmethod[Any, Any, Any], staticmethod[Any, Any], partialmethod[Any]] + + # Allow both a V1 (assumed pre=False) or V2 (assumed mode='after') validator + # We lie to type checkers and say we return the same thing we get + # but in reality we return a proxy object that _mostly_ behaves like the wrapped thing + _V1ValidatorType = TypeVar('_V1ValidatorType', V1Validator, _PartialClsOrStaticMethod) + _V1RootValidatorFunctionType = TypeVar( + '_V1RootValidatorFunctionType', + _decorators_v1.V1RootValidatorFunction, + _V1RootValidatorClsMethod, + _PartialClsOrStaticMethod, + ) +else: + # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915 + # and https://youtrack.jetbrains.com/issue/PY-51428 + DeprecationWarning = PydanticDeprecatedSince20 + + +@deprecated( + 'Pydantic V1 style `@validator` validators are deprecated.' + ' You should migrate to Pydantic V2 style `@field_validator` validators,' + ' see the migration guide for more details', + category=None, +) +def validator( + __field: str, + *fields: str, + pre: bool = False, + each_item: bool = False, + always: bool = False, + check_fields: bool | None = None, + allow_reuse: bool = False, +) -> Callable[[_V1ValidatorType], _V1ValidatorType]: + """Decorate methods on the class indicating that they should be used to validate fields. + + Args: + __field (str): The first field the validator should be called on; this is separate + from `fields` to ensure an error is raised if you don't pass at least one. + *fields (str): Additional field(s) the validator should be called on. + pre (bool, optional): Whether this validator should be called before the standard + validators (else after). Defaults to False. + each_item (bool, optional): For complex objects (sets, lists etc.) whether to validate + individual elements rather than the whole object. Defaults to False. + always (bool, optional): Whether this method and other validators should be called even if + the value is missing. Defaults to False. + check_fields (bool | None, optional): Whether to check that the fields actually exist on the model. + Defaults to None. + allow_reuse (bool, optional): Whether to track and raise an error if another validator refers to + the decorated function. Defaults to False. + + Returns: + Callable: A decorator that can be used to decorate a + function to be used as a validator. + """ + warn( + 'Pydantic V1 style `@validator` validators are deprecated.' + ' You should migrate to Pydantic V2 style `@field_validator` validators,' + ' see the migration guide for more details', + DeprecationWarning, + stacklevel=2, + ) + + if allow_reuse is True: # pragma: no cover + warn(_ALLOW_REUSE_WARNING_MESSAGE, DeprecationWarning) + fields = __field, *fields + if isinstance(fields[0], FunctionType): + raise PydanticUserError( + '`@validator` should be used with fields and keyword arguments, not bare. ' + "E.g. usage should be `@validator('<field_name>', ...)`", + code='validator-no-fields', + ) + elif not all(isinstance(field, str) for field in fields): + raise PydanticUserError( + '`@validator` fields should be passed as separate string args. ' + "E.g. usage should be `@validator('<field_name_1>', '<field_name_2>', ...)`", + code='validator-invalid-fields', + ) + + mode: Literal['before', 'after'] = 'before' if pre is True else 'after' + + def dec(f: Any) -> _decorators.PydanticDescriptorProxy[Any]: + if _decorators.is_instance_method_from_sig(f): + raise PydanticUserError( + '`@validator` cannot be applied to instance methods', code='validator-instance-method' + ) + # auto apply the @classmethod decorator + f = _decorators.ensure_classmethod_based_on_signature(f) + wrap = _decorators_v1.make_generic_v1_field_validator + validator_wrapper_info = _decorators.ValidatorDecoratorInfo( + fields=fields, + mode=mode, + each_item=each_item, + always=always, + check_fields=check_fields, + ) + return _decorators.PydanticDescriptorProxy(f, validator_wrapper_info, shim=wrap) + + return dec # type: ignore[return-value] + + +@overload +def root_validator( + *, + # if you don't specify `pre` the default is `pre=False` + # which means you need to specify `skip_on_failure=True` + skip_on_failure: Literal[True], + allow_reuse: bool = ..., +) -> Callable[ + [_V1RootValidatorFunctionType], + _V1RootValidatorFunctionType, +]: ... + + +@overload +def root_validator( + *, + # if you specify `pre=True` then you don't need to specify + # `skip_on_failure`, in fact it is not allowed as an argument! + pre: Literal[True], + allow_reuse: bool = ..., +) -> Callable[ + [_V1RootValidatorFunctionType], + _V1RootValidatorFunctionType, +]: ... + + +@overload +def root_validator( + *, + # if you explicitly specify `pre=False` then you + # MUST specify `skip_on_failure=True` + pre: Literal[False], + skip_on_failure: Literal[True], + allow_reuse: bool = ..., +) -> Callable[ + [_V1RootValidatorFunctionType], + _V1RootValidatorFunctionType, +]: ... + + +@deprecated( + 'Pydantic V1 style `@root_validator` validators are deprecated.' + ' You should migrate to Pydantic V2 style `@model_validator` validators,' + ' see the migration guide for more details', + category=None, +) +def root_validator( + *__args, + pre: bool = False, + skip_on_failure: bool = False, + allow_reuse: bool = False, +) -> Any: + """Decorate methods on a model indicating that they should be used to validate (and perhaps + modify) data either before or after standard model parsing/validation is performed. + + Args: + pre (bool, optional): Whether this validator should be called before the standard + validators (else after). Defaults to False. + skip_on_failure (bool, optional): Whether to stop validation and return as soon as a + failure is encountered. Defaults to False. + allow_reuse (bool, optional): Whether to track and raise an error if another validator + refers to the decorated function. Defaults to False. + + Returns: + Any: A decorator that can be used to decorate a function to be used as a root_validator. + """ + warn( + 'Pydantic V1 style `@root_validator` validators are deprecated.' + ' You should migrate to Pydantic V2 style `@model_validator` validators,' + ' see the migration guide for more details', + DeprecationWarning, + stacklevel=2, + ) + + if __args: + # Ensure a nice error is raised if someone attempts to use the bare decorator + return root_validator()(*__args) # type: ignore + + if allow_reuse is True: # pragma: no cover + warn(_ALLOW_REUSE_WARNING_MESSAGE, DeprecationWarning) + mode: Literal['before', 'after'] = 'before' if pre is True else 'after' + if pre is False and skip_on_failure is not True: + raise PydanticUserError( + 'If you use `@root_validator` with pre=False (the default) you MUST specify `skip_on_failure=True`.' + ' Note that `@root_validator` is deprecated and should be replaced with `@model_validator`.', + code='root-validator-pre-skip', + ) + + wrap = partial(_decorators_v1.make_v1_generic_root_validator, pre=pre) + + def dec(f: Callable[..., Any] | classmethod[Any, Any, Any] | staticmethod[Any, Any]) -> Any: + if _decorators.is_instance_method_from_sig(f): + raise TypeError('`@root_validator` cannot be applied to instance methods') + # auto apply the @classmethod decorator + res = _decorators.ensure_classmethod_based_on_signature(f) + dec_info = _decorators.RootValidatorDecoratorInfo(mode=mode) + return _decorators.PydanticDescriptorProxy(res, dec_info, shim=wrap) + + return dec |