This commit is contained in:
@@ -4,10 +4,10 @@ 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 typing import TYPE_CHECKING, Any, Callable, Literal, TypeVar, Union, overload
|
||||
from warnings import warn
|
||||
|
||||
from typing_extensions import Literal, Protocol, TypeAlias
|
||||
from typing_extensions import Protocol, TypeAlias, deprecated
|
||||
|
||||
from .._internal import _decorators, _decorators_v1
|
||||
from ..errors import PydanticUserError
|
||||
@@ -19,30 +19,24 @@ _ALLOW_REUSE_WARNING_MESSAGE = '`allow_reuse` is deprecated and will be ignored;
|
||||
if TYPE_CHECKING:
|
||||
|
||||
class _OnlyValueValidatorClsMethod(Protocol):
|
||||
def __call__(self, __cls: Any, __value: Any) -> Any:
|
||||
...
|
||||
def __call__(self, __cls: Any, __value: Any) -> Any: ...
|
||||
|
||||
class _V1ValidatorWithValuesClsMethod(Protocol):
|
||||
def __call__(self, __cls: Any, __value: Any, values: dict[str, Any]) -> Any:
|
||||
...
|
||||
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:
|
||||
...
|
||||
def __call__(self, __cls: Any, __value: Any, *, values: dict[str, Any]) -> Any: ...
|
||||
|
||||
class _V1ValidatorWithKwargsClsMethod(Protocol):
|
||||
def __call__(self, __cls: Any, **kwargs: Any) -> Any:
|
||||
...
|
||||
def __call__(self, __cls: Any, **kwargs: Any) -> Any: ...
|
||||
|
||||
class _V1ValidatorWithValuesAndKwargsClsMethod(Protocol):
|
||||
def __call__(self, __cls: Any, values: dict[str, Any], **kwargs: Any) -> Any:
|
||||
...
|
||||
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:
|
||||
...
|
||||
) -> _decorators_v1.RootValidatorValues: ...
|
||||
|
||||
V1Validator = Union[
|
||||
_OnlyValueValidatorClsMethod,
|
||||
@@ -79,6 +73,12 @@ else:
|
||||
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,
|
||||
@@ -94,7 +94,7 @@ def validator(
|
||||
__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 or not this validator should be called before the standard
|
||||
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.
|
||||
@@ -109,22 +109,6 @@ def validator(
|
||||
Callable: A decorator that can be used to decorate a
|
||||
function to be used as a validator.
|
||||
"""
|
||||
if allow_reuse is True: # pragma: no cover
|
||||
warn(_ALLOW_REUSE_WARNING_MESSAGE, DeprecationWarning)
|
||||
fields = tuple((__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',
|
||||
)
|
||||
|
||||
warn(
|
||||
'Pydantic V1 style `@validator` validators are deprecated.'
|
||||
' You should migrate to Pydantic V2 style `@field_validator` validators,'
|
||||
@@ -133,6 +117,22 @@ def validator(
|
||||
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]:
|
||||
@@ -162,8 +162,10 @@ def root_validator(
|
||||
# which means you need to specify `skip_on_failure=True`
|
||||
skip_on_failure: Literal[True],
|
||||
allow_reuse: bool = ...,
|
||||
) -> Callable[[_V1RootValidatorFunctionType], _V1RootValidatorFunctionType,]:
|
||||
...
|
||||
) -> Callable[
|
||||
[_V1RootValidatorFunctionType],
|
||||
_V1RootValidatorFunctionType,
|
||||
]: ...
|
||||
|
||||
|
||||
@overload
|
||||
@@ -173,8 +175,10 @@ def root_validator(
|
||||
# `skip_on_failure`, in fact it is not allowed as an argument!
|
||||
pre: Literal[True],
|
||||
allow_reuse: bool = ...,
|
||||
) -> Callable[[_V1RootValidatorFunctionType], _V1RootValidatorFunctionType,]:
|
||||
...
|
||||
) -> Callable[
|
||||
[_V1RootValidatorFunctionType],
|
||||
_V1RootValidatorFunctionType,
|
||||
]: ...
|
||||
|
||||
|
||||
@overload
|
||||
@@ -185,10 +189,18 @@ def root_validator(
|
||||
pre: Literal[False],
|
||||
skip_on_failure: Literal[True],
|
||||
allow_reuse: bool = ...,
|
||||
) -> Callable[[_V1RootValidatorFunctionType], _V1RootValidatorFunctionType,]:
|
||||
...
|
||||
) -> 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,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from __future__ import annotations as _annotations
|
||||
|
||||
import warnings
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from typing import TYPE_CHECKING, Any, Literal
|
||||
|
||||
from typing_extensions import Literal, deprecated
|
||||
from typing_extensions import deprecated
|
||||
|
||||
from .._internal import _config
|
||||
from ..warnings import PydanticDeprecatedSince20
|
||||
@@ -18,10 +18,10 @@ __all__ = 'BaseConfig', 'Extra'
|
||||
|
||||
class _ConfigMetaclass(type):
|
||||
def __getattr__(self, item: str) -> Any:
|
||||
warnings.warn(_config.DEPRECATION_MESSAGE, DeprecationWarning)
|
||||
|
||||
try:
|
||||
return _config.config_defaults[item]
|
||||
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
|
||||
|
||||
@@ -35,9 +35,10 @@ class BaseConfig(metaclass=_ConfigMetaclass):
|
||||
"""
|
||||
|
||||
def __getattr__(self, item: str) -> Any:
|
||||
warnings.warn(_config.DEPRECATION_MESSAGE, DeprecationWarning)
|
||||
try:
|
||||
return super().__getattribute__(item)
|
||||
obj = super().__getattribute__(item)
|
||||
warnings.warn(_config.DEPRECATION_MESSAGE, DeprecationWarning)
|
||||
return obj
|
||||
except AttributeError as exc:
|
||||
try:
|
||||
return getattr(type(self), item)
|
||||
|
||||
@@ -3,7 +3,7 @@ from __future__ import annotations as _annotations
|
||||
import typing
|
||||
from copy import deepcopy
|
||||
from enum import Enum
|
||||
from typing import Any, Tuple
|
||||
from typing import Any
|
||||
|
||||
import typing_extensions
|
||||
|
||||
@@ -18,7 +18,7 @@ if typing.TYPE_CHECKING:
|
||||
from .._internal._utils import AbstractSetIntStr, MappingIntStrAny
|
||||
|
||||
AnyClassMethod = classmethod[Any, Any, Any]
|
||||
TupleGenerator = typing.Generator[Tuple[str, Any], None, None]
|
||||
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'
|
||||
@@ -40,11 +40,11 @@ def _iter(
|
||||
# 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.model_fields.items() if v.exclude is not None}, exclude
|
||||
{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({k: True for k in self.model_fields}, include, intersect=True)
|
||||
include = _utils.ValueItems.merge({k: True for k in self.__pydantic_fields__}, 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):
|
||||
@@ -68,15 +68,15 @@ def _iter(
|
||||
|
||||
if exclude_defaults:
|
||||
try:
|
||||
field = self.model_fields[field_key]
|
||||
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.model_fields:
|
||||
dict_key = self.model_fields[field_key].alias or field_key
|
||||
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
|
||||
|
||||
@@ -200,7 +200,7 @@ def _calculate_keys(
|
||||
include: MappingIntStrAny | None,
|
||||
exclude: MappingIntStrAny | None,
|
||||
exclude_unset: bool,
|
||||
update: typing.Dict[str, Any] | None = None, # noqa UP006
|
||||
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
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import warnings
|
||||
from collections.abc import Mapping
|
||||
from functools import wraps
|
||||
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Mapping, Optional, Tuple, Type, TypeVar, Union, overload
|
||||
from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union, overload
|
||||
|
||||
from typing_extensions import deprecated
|
||||
|
||||
@@ -22,29 +23,29 @@ if TYPE_CHECKING:
|
||||
AnyCallable = Callable[..., Any]
|
||||
|
||||
AnyCallableT = TypeVar('AnyCallableT', bound=AnyCallable)
|
||||
ConfigType = Union[None, Type[Any], Dict[str, Any]]
|
||||
ConfigType = Union[None, type[Any], dict[str, Any]]
|
||||
|
||||
|
||||
@overload
|
||||
@deprecated(
|
||||
'The `validate_arguments` method is deprecated; use `validate_call` instead.', category=PydanticDeprecatedSince20
|
||||
)
|
||||
def validate_arguments(func: None = None, *, config: 'ConfigType' = None) -> Callable[['AnyCallableT'], 'AnyCallableT']:
|
||||
...
|
||||
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=PydanticDeprecatedSince20
|
||||
'The `validate_arguments` method is deprecated; use `validate_call` instead.',
|
||||
category=None,
|
||||
)
|
||||
def validate_arguments(func: 'AnyCallableT') -> 'AnyCallableT':
|
||||
...
|
||||
|
||||
|
||||
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.', DeprecationWarning, stacklevel=2
|
||||
'The `validate_arguments` method is deprecated; use `validate_call` instead.',
|
||||
PydanticDeprecatedSince20,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
def validate(_func: 'AnyCallable') -> 'AnyCallable':
|
||||
@@ -86,7 +87,7 @@ class ValidatedFunction:
|
||||
)
|
||||
|
||||
self.raw_function = function
|
||||
self.arg_mapping: Dict[int, str] = {}
|
||||
self.arg_mapping: dict[int, str] = {}
|
||||
self.positional_only_args: set[str] = set()
|
||||
self.v_args_name = 'args'
|
||||
self.v_kwargs_name = 'kwargs'
|
||||
@@ -94,7 +95,7 @@ class ValidatedFunction:
|
||||
type_hints = _typing_extra.get_type_hints(function, include_extras=True)
|
||||
takes_args = False
|
||||
takes_kwargs = False
|
||||
fields: Dict[str, Tuple[Any, Any]] = {}
|
||||
fields: dict[str, tuple[Any, Any]] = {}
|
||||
for i, (name, p) in enumerate(parameters.items()):
|
||||
if p.annotation is p.empty:
|
||||
annotation = Any
|
||||
@@ -105,22 +106,22 @@ class ValidatedFunction:
|
||||
if p.kind == Parameter.POSITIONAL_ONLY:
|
||||
self.arg_mapping[i] = name
|
||||
fields[name] = annotation, default
|
||||
fields[V_POSITIONAL_ONLY_NAME] = List[str], None
|
||||
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
|
||||
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
|
||||
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
|
||||
fields[name] = dict[str, annotation], None
|
||||
takes_kwargs = True
|
||||
|
||||
# these checks avoid a clash between "args" and a field with that name
|
||||
@@ -133,11 +134,11 @@ class ValidatedFunction:
|
||||
|
||||
if not takes_args:
|
||||
# we add the field so validation below can raise the correct exception
|
||||
fields[self.v_args_name] = List[Any], None
|
||||
fields[self.v_args_name] = list[Any], None
|
||||
|
||||
if not takes_kwargs:
|
||||
# same with kwargs
|
||||
fields[self.v_kwargs_name] = Dict[Any, Any], None
|
||||
fields[self.v_kwargs_name] = dict[Any, Any], None
|
||||
|
||||
self.create_model(fields, takes_args, takes_kwargs, config)
|
||||
|
||||
@@ -149,8 +150,8 @@ class ValidatedFunction:
|
||||
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] = {}
|
||||
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:
|
||||
@@ -165,15 +166,15 @@ class ValidatedFunction:
|
||||
values[self.v_args_name] = [a] + [a for _, a in arg_iter]
|
||||
break
|
||||
|
||||
var_kwargs: Dict[str, Any] = {}
|
||||
var_kwargs: dict[str, Any] = {}
|
||||
wrong_positional_args = []
|
||||
duplicate_kwargs = []
|
||||
fields_alias = [
|
||||
field.alias
|
||||
for name, field in self.model.model_fields.items()
|
||||
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.model_fields) - {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:
|
||||
@@ -193,11 +194,15 @@ class ValidatedFunction:
|
||||
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.model_fields[k].default_factory}
|
||||
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] = []
|
||||
args_: list[Any] = []
|
||||
in_kwargs = False
|
||||
kwargs = {}
|
||||
for name, value in d.items():
|
||||
@@ -221,7 +226,7 @@ class ValidatedFunction:
|
||||
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:
|
||||
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)
|
||||
@@ -238,7 +243,7 @@ class ValidatedFunction:
|
||||
class DecoratorBaseModel(BaseModel):
|
||||
@field_validator(self.v_args_name, check_fields=False)
|
||||
@classmethod
|
||||
def check_args(cls, v: Optional[List[Any]]) -> Optional[List[Any]]:
|
||||
def check_args(cls, v: Optional[list[Any]]) -> Optional[list[Any]]:
|
||||
if takes_args or v is None:
|
||||
return v
|
||||
|
||||
@@ -246,7 +251,7 @@ class ValidatedFunction:
|
||||
|
||||
@field_validator(self.v_kwargs_name, check_fields=False)
|
||||
@classmethod
|
||||
def check_kwargs(cls, v: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
|
||||
def check_kwargs(cls, v: Optional[dict[str, Any]]) -> Optional[dict[str, Any]]:
|
||||
if takes_kwargs or v is None:
|
||||
return v
|
||||
|
||||
@@ -256,7 +261,7 @@ class ValidatedFunction:
|
||||
|
||||
@field_validator(V_POSITIONAL_ONLY_NAME, check_fields=False)
|
||||
@classmethod
|
||||
def check_positional_only(cls, v: Optional[List[str]]) -> None:
|
||||
def check_positional_only(cls, v: Optional[list[str]]) -> None:
|
||||
if v is None:
|
||||
return
|
||||
|
||||
@@ -266,7 +271,7 @@ class ValidatedFunction:
|
||||
|
||||
@field_validator(V_DUPLICATE_KWARGS, check_fields=False)
|
||||
@classmethod
|
||||
def check_duplicate_kwargs(cls, v: Optional[List[str]]) -> None:
|
||||
def check_duplicate_kwargs(cls, v: Optional[list[str]]) -> None:
|
||||
if v is None:
|
||||
return
|
||||
|
||||
|
||||
@@ -7,11 +7,12 @@ from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6
|
||||
from pathlib import Path
|
||||
from re import Pattern
|
||||
from types import GeneratorType
|
||||
from typing import TYPE_CHECKING, Any, Callable, Dict, Type, Union
|
||||
from typing import TYPE_CHECKING, Any, Callable, Union
|
||||
from uuid import UUID
|
||||
|
||||
from typing_extensions import deprecated
|
||||
|
||||
from .._internal._import_utils import import_cached_base_model
|
||||
from ..color import Color
|
||||
from ..networks import NameEmail
|
||||
from ..types import SecretBytes, SecretStr
|
||||
@@ -50,7 +51,7 @@ def decimal_encoder(dec_value: Decimal) -> Union[int, float]:
|
||||
return float(dec_value)
|
||||
|
||||
|
||||
ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = {
|
||||
ENCODERS_BY_TYPE: dict[type[Any], Callable[[Any], Any]] = {
|
||||
bytes: lambda o: o.decode(),
|
||||
Color: str,
|
||||
datetime.date: isoformat,
|
||||
@@ -79,18 +80,23 @@ ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = {
|
||||
|
||||
|
||||
@deprecated(
|
||||
'pydantic_encoder is deprecated, use pydantic_core.to_jsonable_python instead.', category=PydanticDeprecatedSince20
|
||||
'`pydantic_encoder` is deprecated, use `pydantic_core.to_jsonable_python` instead.',
|
||||
category=None,
|
||||
)
|
||||
def pydantic_encoder(obj: Any) -> Any:
|
||||
warnings.warn(
|
||||
'`pydantic_encoder` is deprecated, use `pydantic_core.to_jsonable_python` instead.',
|
||||
category=PydanticDeprecatedSince20,
|
||||
stacklevel=2,
|
||||
)
|
||||
from dataclasses import asdict, is_dataclass
|
||||
|
||||
from ..main import BaseModel
|
||||
BaseModel = import_cached_base_model()
|
||||
|
||||
warnings.warn('pydantic_encoder is deprecated, use BaseModel.model_dump instead.', DeprecationWarning, stacklevel=2)
|
||||
if isinstance(obj, BaseModel):
|
||||
return obj.model_dump()
|
||||
elif is_dataclass(obj):
|
||||
return asdict(obj)
|
||||
return asdict(obj) # type: ignore
|
||||
|
||||
# Check the class type and its superclasses for a matching encoder
|
||||
for base in obj.__class__.__mro__[:-1]:
|
||||
@@ -104,12 +110,17 @@ def pydantic_encoder(obj: Any) -> Any:
|
||||
|
||||
|
||||
# TODO: Add a suggested migration path once there is a way to use custom encoders
|
||||
@deprecated('custom_pydantic_encoder is deprecated.', category=PydanticDeprecatedSince20)
|
||||
def custom_pydantic_encoder(type_encoders: Dict[Any, Callable[[Type[Any]], Any]], obj: Any) -> Any:
|
||||
# Check the class type and its superclasses for a matching encoder
|
||||
@deprecated(
|
||||
'`custom_pydantic_encoder` is deprecated, use `BaseModel.model_dump` instead.',
|
||||
category=None,
|
||||
)
|
||||
def custom_pydantic_encoder(type_encoders: dict[Any, Callable[[type[Any]], Any]], obj: Any) -> Any:
|
||||
warnings.warn(
|
||||
'custom_pydantic_encoder is deprecated, use BaseModel.model_dump instead.', DeprecationWarning, stacklevel=2
|
||||
'`custom_pydantic_encoder` is deprecated, use `BaseModel.model_dump` instead.',
|
||||
category=PydanticDeprecatedSince20,
|
||||
stacklevel=2,
|
||||
)
|
||||
# Check the class type and its superclasses for a matching encoder
|
||||
for base in obj.__class__.__mro__[:-1]:
|
||||
try:
|
||||
encoder = type_encoders[base]
|
||||
@@ -121,10 +132,10 @@ def custom_pydantic_encoder(type_encoders: Dict[Any, Callable[[Type[Any]], Any]]
|
||||
return pydantic_encoder(obj)
|
||||
|
||||
|
||||
@deprecated('timedelta_isoformat is deprecated.', category=PydanticDeprecatedSince20)
|
||||
@deprecated('`timedelta_isoformat` is deprecated.', category=None)
|
||||
def timedelta_isoformat(td: datetime.timedelta) -> str:
|
||||
"""ISO 8601 encoding for Python timedelta object."""
|
||||
warnings.warn('timedelta_isoformat is deprecated.', DeprecationWarning, stacklevel=2)
|
||||
warnings.warn('`timedelta_isoformat` is deprecated.', category=PydanticDeprecatedSince20, stacklevel=2)
|
||||
minutes, seconds = divmod(td.seconds, 60)
|
||||
hours, minutes = divmod(minutes, 60)
|
||||
return f'{"-" if td.days < 0 else ""}P{abs(td.days)}DT{hours:d}H{minutes:d}M{seconds:d}.{td.microseconds:06d}S'
|
||||
|
||||
@@ -22,7 +22,7 @@ class Protocol(str, Enum):
|
||||
pickle = 'pickle'
|
||||
|
||||
|
||||
@deprecated('load_str_bytes is deprecated.', category=PydanticDeprecatedSince20)
|
||||
@deprecated('`load_str_bytes` is deprecated.', category=None)
|
||||
def load_str_bytes(
|
||||
b: str | bytes,
|
||||
*,
|
||||
@@ -32,7 +32,7 @@ def load_str_bytes(
|
||||
allow_pickle: bool = False,
|
||||
json_loads: Callable[[str], Any] = json.loads,
|
||||
) -> Any:
|
||||
warnings.warn('load_str_bytes is deprecated.', DeprecationWarning, stacklevel=2)
|
||||
warnings.warn('`load_str_bytes` is deprecated.', category=PydanticDeprecatedSince20, stacklevel=2)
|
||||
if proto is None and content_type:
|
||||
if content_type.endswith(('json', 'javascript')):
|
||||
pass
|
||||
@@ -46,17 +46,17 @@ def load_str_bytes(
|
||||
if proto == Protocol.json:
|
||||
if isinstance(b, bytes):
|
||||
b = b.decode(encoding)
|
||||
return json_loads(b)
|
||||
return json_loads(b) # type: ignore
|
||||
elif proto == Protocol.pickle:
|
||||
if not allow_pickle:
|
||||
raise RuntimeError('Trying to decode with pickle with allow_pickle=False')
|
||||
bb = b if isinstance(b, bytes) else b.encode()
|
||||
bb = b if isinstance(b, bytes) else b.encode() # type: ignore
|
||||
return pickle.loads(bb)
|
||||
else:
|
||||
raise TypeError(f'Unknown protocol: {proto}')
|
||||
|
||||
|
||||
@deprecated('load_file is deprecated.', category=PydanticDeprecatedSince20)
|
||||
@deprecated('`load_file` is deprecated.', category=None)
|
||||
def load_file(
|
||||
path: str | Path,
|
||||
*,
|
||||
@@ -66,7 +66,7 @@ def load_file(
|
||||
allow_pickle: bool = False,
|
||||
json_loads: Callable[[str], Any] = json.loads,
|
||||
) -> Any:
|
||||
warnings.warn('load_file is deprecated.', DeprecationWarning, stacklevel=2)
|
||||
warnings.warn('`load_file` is deprecated.', category=PydanticDeprecatedSince20, stacklevel=2)
|
||||
path = Path(path)
|
||||
b = path.read_bytes()
|
||||
if content_type is None:
|
||||
|
||||
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import json
|
||||
import warnings
|
||||
from typing import TYPE_CHECKING, Any, Callable, Type, TypeVar, Union
|
||||
from typing import TYPE_CHECKING, Any, Callable, TypeVar, Union
|
||||
|
||||
from typing_extensions import deprecated
|
||||
|
||||
@@ -17,19 +17,20 @@ if not TYPE_CHECKING:
|
||||
|
||||
__all__ = 'parse_obj_as', 'schema_of', 'schema_json_of'
|
||||
|
||||
NameFactory = Union[str, Callable[[Type[Any]], str]]
|
||||
NameFactory = Union[str, Callable[[type[Any]], str]]
|
||||
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
|
||||
@deprecated(
|
||||
'parse_obj_as is deprecated. Use pydantic.TypeAdapter.validate_python instead.', category=PydanticDeprecatedSince20
|
||||
'`parse_obj_as` is deprecated. Use `pydantic.TypeAdapter.validate_python` instead.',
|
||||
category=None,
|
||||
)
|
||||
def parse_obj_as(type_: type[T], obj: Any, type_name: NameFactory | None = None) -> T:
|
||||
warnings.warn(
|
||||
'parse_obj_as is deprecated. Use pydantic.TypeAdapter.validate_python instead.',
|
||||
DeprecationWarning,
|
||||
'`parse_obj_as` is deprecated. Use `pydantic.TypeAdapter.validate_python` instead.',
|
||||
category=PydanticDeprecatedSince20,
|
||||
stacklevel=2,
|
||||
)
|
||||
if type_name is not None: # pragma: no cover
|
||||
@@ -42,7 +43,8 @@ def parse_obj_as(type_: type[T], obj: Any, type_name: NameFactory | None = None)
|
||||
|
||||
|
||||
@deprecated(
|
||||
'schema_of is deprecated. Use pydantic.TypeAdapter.json_schema instead.', category=PydanticDeprecatedSince20
|
||||
'`schema_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.',
|
||||
category=None,
|
||||
)
|
||||
def schema_of(
|
||||
type_: Any,
|
||||
@@ -54,7 +56,9 @@ def schema_of(
|
||||
) -> dict[str, Any]:
|
||||
"""Generate a JSON schema (as dict) for the passed model or dynamically generated one."""
|
||||
warnings.warn(
|
||||
'schema_of is deprecated. Use pydantic.TypeAdapter.json_schema instead.', DeprecationWarning, stacklevel=2
|
||||
'`schema_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.',
|
||||
category=PydanticDeprecatedSince20,
|
||||
stacklevel=2,
|
||||
)
|
||||
res = TypeAdapter(type_).json_schema(
|
||||
by_alias=by_alias,
|
||||
@@ -75,7 +79,8 @@ def schema_of(
|
||||
|
||||
|
||||
@deprecated(
|
||||
'schema_json_of is deprecated. Use pydantic.TypeAdapter.json_schema instead.', category=PydanticDeprecatedSince20
|
||||
'`schema_json_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.',
|
||||
category=None,
|
||||
)
|
||||
def schema_json_of(
|
||||
type_: Any,
|
||||
@@ -88,7 +93,9 @@ def schema_json_of(
|
||||
) -> str:
|
||||
"""Generate a JSON schema (as JSON) for the passed model or dynamically generated one."""
|
||||
warnings.warn(
|
||||
'schema_json_of is deprecated. Use pydantic.TypeAdapter.json_schema instead.', DeprecationWarning, stacklevel=2
|
||||
'`schema_json_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.',
|
||||
category=PydanticDeprecatedSince20,
|
||||
stacklevel=2,
|
||||
)
|
||||
return json.dumps(
|
||||
schema_of(type_, title=title, by_alias=by_alias, ref_template=ref_template, schema_generator=schema_generator),
|
||||
|
||||
Reference in New Issue
Block a user