Загрузить файлы в «venv/Lib/site-packages/pydantic/deprecated»

This commit is contained in:
2026-07-02 20:02:04 +00:00
parent 5a83992fbc
commit 9a70ea2e7e
5 changed files with 836 additions and 0 deletions

Binary file not shown.

View File

@@ -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, Literal, TypeVar, Union, overload
from warnings import warn
from typing_extensions import 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, stacklevel=2)
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='decorator-missing-arguments',
)
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='decorator-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, stacklevel=2)
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

View File

@@ -0,0 +1,72 @@
from __future__ import annotations as _annotations
import warnings
from typing import TYPE_CHECKING, Any, Literal
from typing_extensions import deprecated
from .._internal import _config
from ..warnings import PydanticDeprecatedSince20
if not TYPE_CHECKING:
# See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915
# and https://youtrack.jetbrains.com/issue/PY-51428
DeprecationWarning = PydanticDeprecatedSince20
__all__ = 'BaseConfig', 'Extra'
class _ConfigMetaclass(type):
def __getattr__(self, item: str) -> Any:
try:
obj = _config.config_defaults[item]
warnings.warn(_config.DEPRECATION_MESSAGE, DeprecationWarning)
return obj
except KeyError as exc:
raise AttributeError(f"type object '{self.__name__}' has no attribute {exc}") from exc
@deprecated('BaseConfig is deprecated. Use the `pydantic.ConfigDict` instead.', category=PydanticDeprecatedSince20)
class BaseConfig(metaclass=_ConfigMetaclass):
"""This class is only retained for backwards compatibility.
!!! Warning "Deprecated"
BaseConfig is deprecated. Use the [`pydantic.ConfigDict`][pydantic.ConfigDict] instead.
"""
def __getattr__(self, item: str) -> Any:
try:
obj = super().__getattribute__(item)
warnings.warn(_config.DEPRECATION_MESSAGE, DeprecationWarning)
return obj
except AttributeError as exc:
try:
return getattr(type(self), item)
except AttributeError:
# re-raising changes the displayed text to reflect that `self` is not a type
raise AttributeError(str(exc)) from exc
def __init_subclass__(cls, **kwargs: Any) -> None:
warnings.warn(_config.DEPRECATION_MESSAGE, DeprecationWarning)
return super().__init_subclass__(**kwargs)
class _ExtraMeta(type):
def __getattribute__(self, __name: str) -> Any:
# The @deprecated decorator accesses other attributes, so we only emit a warning for the expected ones
if __name in {'allow', 'ignore', 'forbid'}:
warnings.warn(
"`pydantic.config.Extra` is deprecated, use literal values instead (e.g. `extra='allow'`)",
DeprecationWarning,
stacklevel=2,
)
return super().__getattribute__(__name)
@deprecated(
"Extra is deprecated. Use literal values instead (e.g. `extra='allow'`)", category=PydanticDeprecatedSince20
)
class Extra(metaclass=_ExtraMeta):
allow: Literal['allow'] = 'allow'
ignore: Literal['ignore'] = 'ignore'
forbid: Literal['forbid'] = 'forbid'

View File

@@ -0,0 +1,224 @@
from __future__ import annotations as _annotations
import typing
from copy import deepcopy
from enum import Enum
from typing import Any
import typing_extensions
from .._internal import (
_model_construction,
_typing_extra,
_utils,
)
if typing.TYPE_CHECKING:
from .. import BaseModel
from .._internal._utils import AbstractSetIntStr, MappingIntStrAny
AnyClassMethod = classmethod[Any, Any, Any]
TupleGenerator = typing.Generator[tuple[str, Any], None, None]
Model = typing.TypeVar('Model', bound='BaseModel')
# should be `set[int] | set[str] | dict[int, IncEx] | dict[str, IncEx] | None`, but mypy can't cope
IncEx: typing_extensions.TypeAlias = 'set[int] | set[str] | dict[int, Any] | dict[str, Any] | None'
_object_setattr = _model_construction.object_setattr
def _iter(
self: BaseModel,
to_dict: bool = False,
by_alias: bool = False,
include: AbstractSetIntStr | MappingIntStrAny | None = None,
exclude: AbstractSetIntStr | MappingIntStrAny | None = None,
exclude_unset: bool = False,
exclude_defaults: bool = False,
exclude_none: bool = False,
) -> TupleGenerator:
# Merge field set excludes with explicit exclude parameter with explicit overriding field set options.
# The extra "is not None" guards are not logically necessary but optimizes performance for the simple case.
if exclude is not None:
exclude = _utils.ValueItems.merge(
{k: v.exclude for k, v in self.__pydantic_fields__.items() if v.exclude is not None}, exclude
)
if include is not None:
include = _utils.ValueItems.merge(dict.fromkeys(self.__pydantic_fields__, True), include, intersect=True)
allowed_keys = _calculate_keys(self, include=include, exclude=exclude, exclude_unset=exclude_unset) # type: ignore
if allowed_keys is None and not (to_dict or by_alias or exclude_unset or exclude_defaults or exclude_none):
# huge boost for plain _iter()
yield from self.__dict__.items()
if self.__pydantic_extra__:
yield from self.__pydantic_extra__.items()
return
value_exclude = _utils.ValueItems(self, exclude) if exclude is not None else None
value_include = _utils.ValueItems(self, include) if include is not None else None
if self.__pydantic_extra__ is None:
items = self.__dict__.items()
else:
items = list(self.__dict__.items()) + list(self.__pydantic_extra__.items())
for field_key, v in items:
if (allowed_keys is not None and field_key not in allowed_keys) or (exclude_none and v is None):
continue
if exclude_defaults:
try:
field = self.__pydantic_fields__[field_key]
except KeyError:
pass
else:
if not field.is_required() and field.default == v:
continue
if by_alias and field_key in self.__pydantic_fields__:
dict_key = self.__pydantic_fields__[field_key].alias or field_key
else:
dict_key = field_key
if to_dict or value_include or value_exclude:
v = _get_value(
type(self),
v,
to_dict=to_dict,
by_alias=by_alias,
include=value_include and value_include.for_element(field_key),
exclude=value_exclude and value_exclude.for_element(field_key),
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
exclude_none=exclude_none,
)
yield dict_key, v
def _copy_and_set_values(
self: Model,
values: dict[str, Any],
fields_set: set[str],
extra: dict[str, Any] | None = None,
private: dict[str, Any] | None = None,
*,
deep: bool, # UP006
) -> Model:
if deep:
# chances of having empty dict here are quite low for using smart_deepcopy
values = deepcopy(values)
extra = deepcopy(extra)
private = deepcopy(private)
cls = self.__class__
m = cls.__new__(cls)
_object_setattr(m, '__dict__', values)
_object_setattr(m, '__pydantic_extra__', extra)
_object_setattr(m, '__pydantic_fields_set__', fields_set)
_object_setattr(m, '__pydantic_private__', private)
return m
@typing.no_type_check
def _get_value(
cls: type[BaseModel],
v: Any,
to_dict: bool,
by_alias: bool,
include: AbstractSetIntStr | MappingIntStrAny | None,
exclude: AbstractSetIntStr | MappingIntStrAny | None,
exclude_unset: bool,
exclude_defaults: bool,
exclude_none: bool,
) -> Any:
from .. import BaseModel
if isinstance(v, BaseModel):
if to_dict:
return v.model_dump(
by_alias=by_alias,
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
include=include, # type: ignore
exclude=exclude, # type: ignore
exclude_none=exclude_none,
)
else:
return v.copy(include=include, exclude=exclude)
value_exclude = _utils.ValueItems(v, exclude) if exclude else None
value_include = _utils.ValueItems(v, include) if include else None
if isinstance(v, dict):
return {
k_: _get_value(
cls,
v_,
to_dict=to_dict,
by_alias=by_alias,
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
include=value_include and value_include.for_element(k_),
exclude=value_exclude and value_exclude.for_element(k_),
exclude_none=exclude_none,
)
for k_, v_ in v.items()
if (not value_exclude or not value_exclude.is_excluded(k_))
and (not value_include or value_include.is_included(k_))
}
elif _utils.sequence_like(v):
seq_args = (
_get_value(
cls,
v_,
to_dict=to_dict,
by_alias=by_alias,
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
include=value_include and value_include.for_element(i),
exclude=value_exclude and value_exclude.for_element(i),
exclude_none=exclude_none,
)
for i, v_ in enumerate(v)
if (not value_exclude or not value_exclude.is_excluded(i))
and (not value_include or value_include.is_included(i))
)
return v.__class__(*seq_args) if _typing_extra.is_namedtuple(v.__class__) else v.__class__(seq_args)
elif isinstance(v, Enum) and getattr(cls.model_config, 'use_enum_values', False):
return v.value
else:
return v
def _calculate_keys(
self: BaseModel,
include: MappingIntStrAny | None,
exclude: MappingIntStrAny | None,
exclude_unset: bool,
update: dict[str, Any] | None = None, # noqa UP006
) -> typing.AbstractSet[str] | None:
if include is None and exclude is None and exclude_unset is False:
return None
keys: typing.AbstractSet[str]
if exclude_unset:
keys = self.__pydantic_fields_set__.copy()
else:
keys = set(self.__dict__.keys())
keys = keys | (self.__pydantic_extra__ or {}).keys()
if include is not None:
keys &= include.keys()
if update:
keys -= update.keys()
if exclude:
keys -= {k for k, v in exclude.items() if _utils.ValueItems.is_true(v)}
return keys

View File

@@ -0,0 +1,284 @@
import warnings
from collections.abc import Mapping
from functools import wraps
from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union, overload
from typing_extensions import deprecated
from .._internal import _config, _typing_extra
from ..alias_generators import to_pascal
from ..errors import PydanticUserError
from ..functional_validators import field_validator
from ..main import BaseModel, create_model
from ..warnings import PydanticDeprecatedSince20
if not TYPE_CHECKING:
# See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915
# and https://youtrack.jetbrains.com/issue/PY-51428
DeprecationWarning = PydanticDeprecatedSince20
__all__ = ('validate_arguments',)
if TYPE_CHECKING:
AnyCallable = Callable[..., Any]
AnyCallableT = TypeVar('AnyCallableT', bound=AnyCallable)
ConfigType = Union[None, type[Any], dict[str, Any]]
@overload
def validate_arguments(
func: None = None, *, config: 'ConfigType' = None
) -> Callable[['AnyCallableT'], 'AnyCallableT']: ...
@overload
def validate_arguments(func: 'AnyCallableT') -> 'AnyCallableT': ...
@deprecated(
'The `validate_arguments` method is deprecated; use `validate_call` instead.',
category=None,
)
def validate_arguments(func: Optional['AnyCallableT'] = None, *, config: 'ConfigType' = None) -> Any:
"""Decorator to validate the arguments passed to a function."""
warnings.warn(
'The `validate_arguments` method is deprecated; use `validate_call` instead.',
PydanticDeprecatedSince20,
stacklevel=2,
)
def validate(_func: 'AnyCallable') -> 'AnyCallable':
vd = ValidatedFunction(_func, config)
@wraps(_func)
def wrapper_function(*args: Any, **kwargs: Any) -> Any:
return vd.call(*args, **kwargs)
wrapper_function.vd = vd # type: ignore
wrapper_function.validate = vd.init_model_instance # type: ignore
wrapper_function.raw_function = vd.raw_function # type: ignore
wrapper_function.model = vd.model # type: ignore
return wrapper_function
if func:
return validate(func)
else:
return validate
ALT_V_ARGS = 'v__args'
ALT_V_KWARGS = 'v__kwargs'
V_POSITIONAL_ONLY_NAME = 'v__positional_only'
V_DUPLICATE_KWARGS = 'v__duplicate_kwargs'
class ValidatedFunction:
def __init__(self, function: 'AnyCallable', config: 'ConfigType'):
from inspect import Parameter, signature
parameters: Mapping[str, Parameter] = signature(function).parameters
if parameters.keys() & {ALT_V_ARGS, ALT_V_KWARGS, V_POSITIONAL_ONLY_NAME, V_DUPLICATE_KWARGS}:
raise PydanticUserError(
f'"{ALT_V_ARGS}", "{ALT_V_KWARGS}", "{V_POSITIONAL_ONLY_NAME}" and "{V_DUPLICATE_KWARGS}" '
f'are not permitted as argument names when using the "{validate_arguments.__name__}" decorator',
code=None,
)
self.raw_function = function
self.arg_mapping: dict[int, str] = {}
self.positional_only_args: set[str] = set()
self.v_args_name = 'args'
self.v_kwargs_name = 'kwargs'
type_hints = _typing_extra.get_type_hints(function, include_extras=True)
takes_args = False
takes_kwargs = False
fields: dict[str, tuple[Any, Any]] = {}
for i, (name, p) in enumerate(parameters.items()):
if p.annotation is p.empty:
annotation = Any
else:
annotation = type_hints[name]
default = ... if p.default is p.empty else p.default
if p.kind == Parameter.POSITIONAL_ONLY:
self.arg_mapping[i] = name
fields[name] = annotation, default
fields[V_POSITIONAL_ONLY_NAME] = list[str], None
self.positional_only_args.add(name)
elif p.kind == Parameter.POSITIONAL_OR_KEYWORD:
self.arg_mapping[i] = name
fields[name] = annotation, default
fields[V_DUPLICATE_KWARGS] = list[str], None
elif p.kind == Parameter.KEYWORD_ONLY:
fields[name] = annotation, default
elif p.kind == Parameter.VAR_POSITIONAL:
self.v_args_name = name
fields[name] = tuple[annotation, ...], None
takes_args = True
else:
assert p.kind == Parameter.VAR_KEYWORD, p.kind
self.v_kwargs_name = name
fields[name] = dict[str, annotation], None
takes_kwargs = True
# these checks avoid a clash between "args" and a field with that name
if not takes_args and self.v_args_name in fields:
self.v_args_name = ALT_V_ARGS
# same with "kwargs"
if not takes_kwargs and self.v_kwargs_name in fields:
self.v_kwargs_name = ALT_V_KWARGS
if not takes_args:
# we add the field so validation below can raise the correct exception
fields[self.v_args_name] = list[Any], None
if not takes_kwargs:
# same with kwargs
fields[self.v_kwargs_name] = dict[Any, Any], None
self.create_model(fields, takes_args, takes_kwargs, config)
def init_model_instance(self, *args: Any, **kwargs: Any) -> BaseModel:
values = self.build_values(args, kwargs)
return self.model(**values)
def call(self, *args: Any, **kwargs: Any) -> Any:
m = self.init_model_instance(*args, **kwargs)
return self.execute(m)
def build_values(self, args: tuple[Any, ...], kwargs: dict[str, Any]) -> dict[str, Any]:
values: dict[str, Any] = {}
if args:
arg_iter = enumerate(args)
while True:
try:
i, a = next(arg_iter)
except StopIteration:
break
arg_name = self.arg_mapping.get(i)
if arg_name is not None:
values[arg_name] = a
else:
values[self.v_args_name] = [a] + [a for _, a in arg_iter]
break
var_kwargs: dict[str, Any] = {}
wrong_positional_args = []
duplicate_kwargs = []
fields_alias = [
field.alias
for name, field in self.model.__pydantic_fields__.items()
if name not in (self.v_args_name, self.v_kwargs_name)
]
non_var_fields = set(self.model.__pydantic_fields__) - {self.v_args_name, self.v_kwargs_name}
for k, v in kwargs.items():
if k in non_var_fields or k in fields_alias:
if k in self.positional_only_args:
wrong_positional_args.append(k)
if k in values:
duplicate_kwargs.append(k)
values[k] = v
else:
var_kwargs[k] = v
if var_kwargs:
values[self.v_kwargs_name] = var_kwargs
if wrong_positional_args:
values[V_POSITIONAL_ONLY_NAME] = wrong_positional_args
if duplicate_kwargs:
values[V_DUPLICATE_KWARGS] = duplicate_kwargs
return values
def execute(self, m: BaseModel) -> Any:
d = {
k: v
for k, v in m.__dict__.items()
if k in m.__pydantic_fields_set__ or m.__pydantic_fields__[k].default_factory
}
var_kwargs = d.pop(self.v_kwargs_name, {})
if self.v_args_name in d:
args_: list[Any] = []
in_kwargs = False
kwargs = {}
for name, value in d.items():
if in_kwargs:
kwargs[name] = value
elif name == self.v_args_name:
args_ += value
in_kwargs = True
else:
args_.append(value)
return self.raw_function(*args_, **kwargs, **var_kwargs)
elif self.positional_only_args:
args_ = []
kwargs = {}
for name, value in d.items():
if name in self.positional_only_args:
args_.append(value)
else:
kwargs[name] = value
return self.raw_function(*args_, **kwargs, **var_kwargs)
else:
return self.raw_function(**d, **var_kwargs)
def create_model(self, fields: dict[str, Any], takes_args: bool, takes_kwargs: bool, config: 'ConfigType') -> None:
pos_args = len(self.arg_mapping)
config_wrapper = _config.ConfigWrapper(config)
if config_wrapper.alias_generator:
raise PydanticUserError(
'Setting the "alias_generator" property on custom Config for '
'@validate_arguments is not yet supported, please remove.',
code=None,
)
if config_wrapper.extra is None:
config_wrapper.config_dict['extra'] = 'forbid'
class DecoratorBaseModel(BaseModel):
@field_validator(self.v_args_name, check_fields=False)
@classmethod
def check_args(cls, v: Optional[list[Any]]) -> Optional[list[Any]]:
if takes_args or v is None:
return v
raise TypeError(f'{pos_args} positional arguments expected but {pos_args + len(v)} given')
@field_validator(self.v_kwargs_name, check_fields=False)
@classmethod
def check_kwargs(cls, v: Optional[dict[str, Any]]) -> Optional[dict[str, Any]]:
if takes_kwargs or v is None:
return v
plural = '' if len(v) == 1 else 's'
keys = ', '.join(map(repr, v.keys()))
raise TypeError(f'unexpected keyword argument{plural}: {keys}')
@field_validator(V_POSITIONAL_ONLY_NAME, check_fields=False)
@classmethod
def check_positional_only(cls, v: Optional[list[str]]) -> None:
if v is None:
return
plural = '' if len(v) == 1 else 's'
keys = ', '.join(map(repr, v))
raise TypeError(f'positional-only argument{plural} passed as keyword argument{plural}: {keys}')
@field_validator(V_DUPLICATE_KWARGS, check_fields=False)
@classmethod
def check_duplicate_kwargs(cls, v: Optional[list[str]]) -> None:
if v is None:
return
plural = '' if len(v) == 1 else 's'
keys = ', '.join(map(repr, v))
raise TypeError(f'multiple values for argument{plural}: {keys}')
model_config = config_wrapper.config_dict
self.model = create_model(to_pascal(self.raw_function.__name__), __base__=DecoratorBaseModel, **fields)