Загрузить файлы в «venv/Lib/site-packages/pydantic»
This commit is contained in:
157
venv/Lib/site-packages/pydantic/root_model.py
Normal file
157
venv/Lib/site-packages/pydantic/root_model.py
Normal file
@@ -0,0 +1,157 @@
|
||||
"""RootModel class and type definitions."""
|
||||
|
||||
from __future__ import annotations as _annotations
|
||||
|
||||
from copy import copy, deepcopy
|
||||
from typing import TYPE_CHECKING, Any, Generic, Literal, TypeVar
|
||||
|
||||
from pydantic_core import PydanticUndefined
|
||||
from typing_extensions import Self, dataclass_transform
|
||||
|
||||
from . import PydanticUserError
|
||||
from ._internal import _model_construction, _repr
|
||||
from .main import BaseModel, _object_setattr
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .fields import Field as PydanticModelField
|
||||
from .fields import PrivateAttr as PydanticModelPrivateAttr
|
||||
|
||||
# dataclass_transform could be applied to RootModel directly, but `ModelMetaclass`'s dataclass_transform
|
||||
# takes priority (at least with pyright). We trick type checkers into thinking we apply dataclass_transform
|
||||
# on a new metaclass.
|
||||
@dataclass_transform(kw_only_default=False, field_specifiers=(PydanticModelField, PydanticModelPrivateAttr))
|
||||
class _RootModelMetaclass(_model_construction.ModelMetaclass): ...
|
||||
else:
|
||||
_RootModelMetaclass = _model_construction.ModelMetaclass
|
||||
|
||||
__all__ = ('RootModel',)
|
||||
|
||||
RootModelRootType = TypeVar('RootModelRootType')
|
||||
|
||||
|
||||
class RootModel(BaseModel, Generic[RootModelRootType], metaclass=_RootModelMetaclass):
|
||||
"""!!! abstract "Usage Documentation"
|
||||
[`RootModel` and Custom Root Types](../concepts/models.md#rootmodel-and-custom-root-types)
|
||||
|
||||
A Pydantic `BaseModel` for the root object of the model.
|
||||
|
||||
Attributes:
|
||||
root: The root object of the model.
|
||||
__pydantic_root_model__: Whether the model is a RootModel.
|
||||
__pydantic_private__: Private fields in the model.
|
||||
__pydantic_extra__: Extra fields in the model.
|
||||
|
||||
"""
|
||||
|
||||
__pydantic_root_model__ = True
|
||||
__pydantic_private__ = None
|
||||
__pydantic_extra__ = None
|
||||
|
||||
root: RootModelRootType
|
||||
|
||||
def __init_subclass__(cls, **kwargs):
|
||||
extra = cls.model_config.get('extra')
|
||||
if extra is not None:
|
||||
raise PydanticUserError(
|
||||
"`RootModel` does not support setting `model_config['extra']`", code='root-model-extra'
|
||||
)
|
||||
super().__init_subclass__(**kwargs)
|
||||
|
||||
def __init__(self, /, root: RootModelRootType = PydanticUndefined, **data) -> None: # type: ignore
|
||||
__tracebackhide__ = True
|
||||
if data:
|
||||
if root is not PydanticUndefined:
|
||||
raise ValueError(
|
||||
'"RootModel.__init__" accepts either a single positional argument or arbitrary keyword arguments'
|
||||
)
|
||||
root = data # type: ignore
|
||||
self.__pydantic_validator__.validate_python(root, self_instance=self)
|
||||
|
||||
__init__.__pydantic_base_init__ = True # pyright: ignore[reportFunctionMemberAccess]
|
||||
|
||||
@classmethod
|
||||
def model_construct(cls, root: RootModelRootType, _fields_set: set[str] | None = None) -> Self: # type: ignore
|
||||
"""Create a new model using the provided root object and update fields set.
|
||||
|
||||
Args:
|
||||
root: The root object of the model.
|
||||
_fields_set: The set of fields to be updated.
|
||||
|
||||
Returns:
|
||||
The new model.
|
||||
|
||||
Raises:
|
||||
NotImplemented: If the model is not a subclass of `RootModel`.
|
||||
"""
|
||||
return super().model_construct(root=root, _fields_set=_fields_set)
|
||||
|
||||
def __getstate__(self) -> dict[Any, Any]:
|
||||
return {
|
||||
'__dict__': self.__dict__,
|
||||
'__pydantic_fields_set__': self.__pydantic_fields_set__,
|
||||
}
|
||||
|
||||
def __setstate__(self, state: dict[Any, Any]) -> None:
|
||||
_object_setattr(self, '__pydantic_fields_set__', state['__pydantic_fields_set__'])
|
||||
_object_setattr(self, '__dict__', state['__dict__'])
|
||||
|
||||
def __copy__(self) -> Self:
|
||||
"""Returns a shallow copy of the model."""
|
||||
cls = type(self)
|
||||
m = cls.__new__(cls)
|
||||
new_dict = copy(self.__dict__)
|
||||
new_dict['root'] = copy(self.__dict__['root'])
|
||||
_object_setattr(m, '__dict__', new_dict)
|
||||
_object_setattr(m, '__pydantic_fields_set__', copy(self.__pydantic_fields_set__))
|
||||
return m
|
||||
|
||||
def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Self:
|
||||
"""Returns a deep copy of the model."""
|
||||
cls = type(self)
|
||||
m = cls.__new__(cls)
|
||||
_object_setattr(m, '__dict__', deepcopy(self.__dict__, memo=memo))
|
||||
# This next line doesn't need a deepcopy because __pydantic_fields_set__ is a set[str],
|
||||
# and attempting a deepcopy would be marginally slower.
|
||||
_object_setattr(m, '__pydantic_fields_set__', copy(self.__pydantic_fields_set__))
|
||||
return m
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
||||
def model_dump( # type: ignore
|
||||
self,
|
||||
*,
|
||||
mode: Literal['json', 'python'] | str = 'python',
|
||||
include: Any = None,
|
||||
exclude: Any = None,
|
||||
context: dict[str, Any] | None = None,
|
||||
by_alias: bool | None = None,
|
||||
exclude_unset: bool = False,
|
||||
exclude_defaults: bool = False,
|
||||
exclude_none: bool = False,
|
||||
exclude_computed_fields: bool = False,
|
||||
round_trip: bool = False,
|
||||
warnings: bool | Literal['none', 'warn', 'error'] = True,
|
||||
serialize_as_any: bool = False,
|
||||
) -> Any:
|
||||
"""This method is included just to get a more accurate return type for type checkers.
|
||||
It is included in this `if TYPE_CHECKING:` block since no override is actually necessary.
|
||||
|
||||
See the documentation of `BaseModel.model_dump` for more details about the arguments.
|
||||
|
||||
Generally, this method will have a return type of `RootModelRootType`, assuming that `RootModelRootType` is
|
||||
not a `BaseModel` subclass. If `RootModelRootType` is a `BaseModel` subclass, then the return
|
||||
type will likely be `dict[str, Any]`, as `model_dump` calls are recursive. The return type could
|
||||
even be something different, in the case of a custom serializer.
|
||||
Thus, `Any` is used here to catch all of these cases.
|
||||
"""
|
||||
...
|
||||
|
||||
def __eq__(self, other: Any) -> bool:
|
||||
if not isinstance(other, RootModel):
|
||||
return NotImplemented
|
||||
return self.__pydantic_fields__['root'].annotation == other.__pydantic_fields__[
|
||||
'root'
|
||||
].annotation and super().__eq__(other)
|
||||
|
||||
def __repr_args__(self) -> _repr.ReprArgs:
|
||||
yield 'root', self.root
|
||||
5
venv/Lib/site-packages/pydantic/schema.py
Normal file
5
venv/Lib/site-packages/pydantic/schema.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""The `schema` module is a backport module from V1."""
|
||||
|
||||
from ._migration import getattr_migration
|
||||
|
||||
__getattr__ = getattr_migration(__name__)
|
||||
5
venv/Lib/site-packages/pydantic/tools.py
Normal file
5
venv/Lib/site-packages/pydantic/tools.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""The `tools` module is a backport module from V1."""
|
||||
|
||||
from ._migration import getattr_migration
|
||||
|
||||
__getattr__ = getattr_migration(__name__)
|
||||
801
venv/Lib/site-packages/pydantic/type_adapter.py
Normal file
801
venv/Lib/site-packages/pydantic/type_adapter.py
Normal file
@@ -0,0 +1,801 @@
|
||||
"""Type adapter specification."""
|
||||
|
||||
from __future__ import annotations as _annotations
|
||||
|
||||
import sys
|
||||
import types
|
||||
from collections.abc import Callable, Iterable
|
||||
from dataclasses import is_dataclass
|
||||
from types import FrameType
|
||||
from typing import (
|
||||
Any,
|
||||
Generic,
|
||||
Literal,
|
||||
TypeVar,
|
||||
cast,
|
||||
final,
|
||||
overload,
|
||||
)
|
||||
|
||||
from pydantic_core import CoreSchema, SchemaSerializer, SchemaValidator, Some
|
||||
from typing_extensions import ParamSpec, is_typeddict
|
||||
|
||||
from pydantic.errors import PydanticUserError
|
||||
from pydantic.main import BaseModel, IncEx
|
||||
|
||||
from ._internal import _config, _generate_schema, _mock_val_ser, _namespace_utils, _repr, _typing_extra, _utils
|
||||
from .config import ConfigDict, ExtraValues
|
||||
from .errors import PydanticUndefinedAnnotation
|
||||
from .json_schema import (
|
||||
DEFAULT_REF_TEMPLATE,
|
||||
GenerateJsonSchema,
|
||||
JsonSchemaKeyT,
|
||||
JsonSchemaMode,
|
||||
JsonSchemaValue,
|
||||
)
|
||||
from .plugin._schema_validator import PluggableSchemaValidator, create_schema_validator
|
||||
|
||||
T = TypeVar('T')
|
||||
R = TypeVar('R')
|
||||
P = ParamSpec('P')
|
||||
TypeAdapterT = TypeVar('TypeAdapterT', bound='TypeAdapter')
|
||||
|
||||
|
||||
def _getattr_no_parents(obj: Any, attribute: str) -> Any:
|
||||
"""Returns the attribute value without attempting to look up attributes from parent types."""
|
||||
if hasattr(obj, '__dict__'):
|
||||
try:
|
||||
return obj.__dict__[attribute]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
slots = getattr(obj, '__slots__', None)
|
||||
if slots is not None and attribute in slots:
|
||||
return getattr(obj, attribute)
|
||||
else:
|
||||
raise AttributeError(attribute)
|
||||
|
||||
|
||||
def _type_has_config(type_: Any) -> bool:
|
||||
"""Returns whether the type has config."""
|
||||
type_ = _typing_extra.annotated_type(type_) or type_
|
||||
try:
|
||||
return issubclass(type_, BaseModel) or is_dataclass(type_) or is_typeddict(type_)
|
||||
except TypeError:
|
||||
# type is not a class
|
||||
return False
|
||||
|
||||
|
||||
@final
|
||||
class TypeAdapter(Generic[T]):
|
||||
"""!!! abstract "Usage Documentation"
|
||||
[`TypeAdapter`](../concepts/type_adapter.md)
|
||||
|
||||
Type adapters provide a flexible way to perform validation and serialization based on a Python type.
|
||||
|
||||
A `TypeAdapter` instance exposes some of the functionality from `BaseModel` instance methods
|
||||
for types that do not have such methods (such as dataclasses, primitive types, and more).
|
||||
|
||||
**Note:** `TypeAdapter` instances are not types, and cannot be used as type annotations for fields.
|
||||
|
||||
Args:
|
||||
type: The type associated with the `TypeAdapter`.
|
||||
config: Configuration for the `TypeAdapter`, should be a dictionary conforming to
|
||||
[`ConfigDict`][pydantic.config.ConfigDict].
|
||||
|
||||
!!! note
|
||||
You cannot provide a configuration when instantiating a `TypeAdapter` if the type you're using
|
||||
has its own config that cannot be overridden (ex: `BaseModel`, `TypedDict`, and `dataclass`). A
|
||||
[`type-adapter-config-unused`](../errors/usage_errors.md#type-adapter-config-unused) error will
|
||||
be raised in this case.
|
||||
_parent_depth: Depth at which to search for the [parent frame][frame-objects]. This frame is used when
|
||||
resolving forward annotations during schema building, by looking for the globals and locals of this
|
||||
frame. Defaults to 2, which will result in the frame where the `TypeAdapter` was instantiated.
|
||||
|
||||
!!! note
|
||||
This parameter is named with an underscore to suggest its private nature and discourage use.
|
||||
It may be deprecated in a minor version, so we only recommend using it if you're comfortable
|
||||
with potential change in behavior/support. It's default value is 2 because internally,
|
||||
the `TypeAdapter` class makes another call to fetch the frame.
|
||||
module: The module that passes to plugin if provided.
|
||||
|
||||
Attributes:
|
||||
core_schema: The core schema for the type.
|
||||
validator: The schema validator for the type.
|
||||
serializer: The schema serializer for the type.
|
||||
pydantic_complete: Whether the core schema for the type is successfully built.
|
||||
|
||||
??? tip "Compatibility with `mypy`"
|
||||
Depending on the type used, `mypy` might raise an error when instantiating a `TypeAdapter`. As a workaround, you can explicitly
|
||||
annotate your variable:
|
||||
|
||||
```py
|
||||
from typing import Union
|
||||
|
||||
from pydantic import TypeAdapter
|
||||
|
||||
ta: TypeAdapter[Union[str, int]] = TypeAdapter(Union[str, int]) # type: ignore[arg-type]
|
||||
```
|
||||
|
||||
??? info "Namespace management nuances and implementation details"
|
||||
|
||||
Here, we collect some notes on namespace management, and subtle differences from `BaseModel`:
|
||||
|
||||
`BaseModel` uses its own `__module__` to find out where it was defined
|
||||
and then looks for symbols to resolve forward references in those globals.
|
||||
On the other hand, `TypeAdapter` can be initialized with arbitrary objects,
|
||||
which may not be types and thus do not have a `__module__` available.
|
||||
So instead we look at the globals in our parent stack frame.
|
||||
|
||||
It is expected that the `ns_resolver` passed to this function will have the correct
|
||||
namespace for the type we're adapting. See the source code for `TypeAdapter.__init__`
|
||||
and `TypeAdapter.rebuild` for various ways to construct this namespace.
|
||||
|
||||
This works for the case where this function is called in a module that
|
||||
has the target of forward references in its scope, but
|
||||
does not always work for more complex cases.
|
||||
|
||||
For example, take the following:
|
||||
|
||||
```python {title="a.py"}
|
||||
IntList = list[int]
|
||||
OuterDict = dict[str, 'IntList']
|
||||
```
|
||||
|
||||
```python {test="skip" title="b.py"}
|
||||
from a import OuterDict
|
||||
|
||||
from pydantic import TypeAdapter
|
||||
|
||||
IntList = int # replaces the symbol the forward reference is looking for
|
||||
v = TypeAdapter(OuterDict)
|
||||
v({'x': 1}) # should fail but doesn't
|
||||
```
|
||||
|
||||
If `OuterDict` were a `BaseModel`, this would work because it would resolve
|
||||
the forward reference within the `a.py` namespace.
|
||||
But `TypeAdapter(OuterDict)` can't determine what module `OuterDict` came from.
|
||||
|
||||
In other words, the assumption that _all_ forward references exist in the
|
||||
module we are being called from is not technically always true.
|
||||
Although most of the time it is and it works fine for recursive models and such,
|
||||
`BaseModel`'s behavior isn't perfect either and _can_ break in similar ways,
|
||||
so there is no right or wrong between the two.
|
||||
|
||||
But at the very least this behavior is _subtly_ different from `BaseModel`'s.
|
||||
"""
|
||||
|
||||
core_schema: CoreSchema
|
||||
validator: SchemaValidator | PluggableSchemaValidator
|
||||
serializer: SchemaSerializer
|
||||
pydantic_complete: bool
|
||||
|
||||
@overload
|
||||
def __init__(
|
||||
self,
|
||||
type: type[T],
|
||||
*,
|
||||
config: ConfigDict | None = ...,
|
||||
_parent_depth: int = ...,
|
||||
module: str | None = ...,
|
||||
) -> None: ...
|
||||
|
||||
# This second overload is for unsupported special forms (such as Annotated, Union, etc.)
|
||||
# Currently there is no way to type this correctly
|
||||
# See https://github.com/python/typing/pull/1618
|
||||
@overload
|
||||
def __init__(
|
||||
self,
|
||||
type: Any,
|
||||
*,
|
||||
config: ConfigDict | None = ...,
|
||||
_parent_depth: int = ...,
|
||||
module: str | None = ...,
|
||||
) -> None: ...
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
type: Any,
|
||||
*,
|
||||
config: ConfigDict | None = None,
|
||||
_parent_depth: int = 2,
|
||||
module: str | None = None,
|
||||
) -> None:
|
||||
if _type_has_config(type) and config is not None:
|
||||
raise PydanticUserError(
|
||||
'Cannot use `config` when the type is a BaseModel, dataclass or TypedDict.'
|
||||
' These types can have their own config and setting the config via the `config`'
|
||||
' parameter to TypeAdapter will not override it, thus the `config` you passed to'
|
||||
' TypeAdapter becomes meaningless, which is probably not what you want.',
|
||||
code='type-adapter-config-unused',
|
||||
)
|
||||
|
||||
self._type = type
|
||||
self._config = config
|
||||
self._parent_depth = _parent_depth
|
||||
self.pydantic_complete = False
|
||||
|
||||
parent_frame = self._fetch_parent_frame()
|
||||
if isinstance(type, types.FunctionType):
|
||||
# Special case functions, which are *not* pushed to the `NsResolver` stack and without this special case
|
||||
# would only have access to the parent namespace where the `TypeAdapter` was instantiated (if the function is defined
|
||||
# in another module, we need to look at that module's globals).
|
||||
if parent_frame is not None:
|
||||
# `f_locals` is the namespace where the type adapter was instantiated (~ to `f_globals` if at the module level):
|
||||
parent_ns = parent_frame.f_locals
|
||||
else: # pragma: no cover
|
||||
parent_ns = None
|
||||
globalns, localns = _namespace_utils.ns_for_function(
|
||||
type,
|
||||
parent_namespace=parent_ns,
|
||||
)
|
||||
parent_namespace = None
|
||||
else:
|
||||
if parent_frame is not None:
|
||||
globalns = parent_frame.f_globals
|
||||
# Do not provide a local ns if the type adapter happens to be instantiated at the module level:
|
||||
localns = parent_frame.f_locals if parent_frame.f_locals is not globalns else {}
|
||||
else: # pragma: no cover
|
||||
globalns = {}
|
||||
localns = {}
|
||||
parent_namespace = localns
|
||||
|
||||
self._module_name = module or cast(str, globalns.get('__name__', ''))
|
||||
self._init_core_attrs(
|
||||
ns_resolver=_namespace_utils.NsResolver(
|
||||
namespaces_tuple=_namespace_utils.NamespacesTuple(locals=localns, globals=globalns),
|
||||
parent_namespace=parent_namespace,
|
||||
),
|
||||
force=False,
|
||||
)
|
||||
|
||||
def _fetch_parent_frame(self) -> FrameType | None:
|
||||
frame = sys._getframe(self._parent_depth)
|
||||
if frame.f_globals.get('__name__') == 'typing':
|
||||
# Because `TypeAdapter` is generic, explicitly parametrizing the class results
|
||||
# in a `typing._GenericAlias` instance, which proxies instantiation calls to the
|
||||
# "real" `TypeAdapter` class and thus adding an extra frame to the call. To avoid
|
||||
# pulling anything from the `typing` module, use the correct frame (the one before):
|
||||
return frame.f_back
|
||||
|
||||
return frame
|
||||
|
||||
def _init_core_attrs(
|
||||
self, ns_resolver: _namespace_utils.NsResolver, force: bool, raise_errors: bool = False
|
||||
) -> bool:
|
||||
"""Initialize the core schema, validator, and serializer for the type.
|
||||
|
||||
Args:
|
||||
ns_resolver: The namespace resolver to use when building the core schema for the adapted type.
|
||||
force: Whether to force the construction of the core schema, validator, and serializer.
|
||||
If `force` is set to `False` and `_defer_build` is `True`, the core schema, validator, and serializer will be set to mocks.
|
||||
raise_errors: Whether to raise errors if initializing any of the core attrs fails.
|
||||
|
||||
Returns:
|
||||
`True` if the core schema, validator, and serializer were successfully initialized, otherwise `False`.
|
||||
|
||||
Raises:
|
||||
PydanticUndefinedAnnotation: If `PydanticUndefinedAnnotation` occurs in`__get_pydantic_core_schema__`
|
||||
and `raise_errors=True`.
|
||||
"""
|
||||
if not force and self._defer_build:
|
||||
_mock_val_ser.set_type_adapter_mocks(self)
|
||||
self.pydantic_complete = False
|
||||
return False
|
||||
|
||||
try:
|
||||
self.core_schema = _getattr_no_parents(self._type, '__pydantic_core_schema__')
|
||||
self.validator = _getattr_no_parents(self._type, '__pydantic_validator__')
|
||||
self.serializer = _getattr_no_parents(self._type, '__pydantic_serializer__')
|
||||
|
||||
# TODO: we don't go through the rebuild logic here directly because we don't want
|
||||
# to repeat all of the namespace fetching logic that we've already done
|
||||
# so we simply skip to the block below that does the actual schema generation
|
||||
if (
|
||||
isinstance(self.core_schema, _mock_val_ser.MockCoreSchema)
|
||||
or isinstance(self.validator, _mock_val_ser.MockValSer)
|
||||
or isinstance(self.serializer, _mock_val_ser.MockValSer)
|
||||
):
|
||||
raise AttributeError()
|
||||
except AttributeError:
|
||||
config_wrapper = _config.ConfigWrapper(self._config)
|
||||
|
||||
schema_generator = _generate_schema.GenerateSchema(config_wrapper, ns_resolver=ns_resolver)
|
||||
|
||||
try:
|
||||
core_schema = schema_generator.generate_schema(self._type)
|
||||
except PydanticUndefinedAnnotation:
|
||||
if raise_errors:
|
||||
raise
|
||||
_mock_val_ser.set_type_adapter_mocks(self)
|
||||
return False
|
||||
|
||||
try:
|
||||
self.core_schema = schema_generator.clean_schema(core_schema)
|
||||
except _generate_schema.InvalidSchemaError:
|
||||
_mock_val_ser.set_type_adapter_mocks(self)
|
||||
return False
|
||||
|
||||
core_config = config_wrapper.core_config(None)
|
||||
|
||||
self.validator = create_schema_validator(
|
||||
schema=self.core_schema,
|
||||
schema_type=self._type,
|
||||
schema_type_module=self._module_name,
|
||||
schema_type_name=str(self._type),
|
||||
schema_kind='TypeAdapter',
|
||||
config=core_config,
|
||||
plugin_settings=config_wrapper.plugin_settings,
|
||||
)
|
||||
self.serializer = SchemaSerializer(self.core_schema, core_config)
|
||||
|
||||
self.pydantic_complete = True
|
||||
return True
|
||||
|
||||
@property
|
||||
def _defer_build(self) -> bool:
|
||||
config = self._config if self._config is not None else self._model_config
|
||||
if config:
|
||||
return config.get('defer_build') is True
|
||||
return False
|
||||
|
||||
@property
|
||||
def _model_config(self) -> ConfigDict | None:
|
||||
type_: Any = _typing_extra.annotated_type(self._type) or self._type # Eg FastAPI heavily uses Annotated
|
||||
if _utils.lenient_issubclass(type_, BaseModel):
|
||||
return type_.model_config
|
||||
return getattr(type_, '__pydantic_config__', None)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'TypeAdapter({_repr.display_as_type(self._type)})'
|
||||
|
||||
def rebuild(
|
||||
self,
|
||||
*,
|
||||
force: bool = False,
|
||||
raise_errors: bool = True,
|
||||
_parent_namespace_depth: int = 2,
|
||||
_types_namespace: _namespace_utils.MappingNamespace | None = None,
|
||||
) -> bool | None:
|
||||
"""Try to rebuild the pydantic-core schema for the adapter's type.
|
||||
|
||||
This may be necessary when one of the annotations is a ForwardRef which could not be resolved during
|
||||
the initial attempt to build the schema, and automatic rebuilding fails.
|
||||
|
||||
Args:
|
||||
force: Whether to force the rebuilding of the type adapter's schema, defaults to `False`.
|
||||
raise_errors: Whether to raise errors, defaults to `True`.
|
||||
_parent_namespace_depth: Depth at which to search for the [parent frame][frame-objects]. This
|
||||
frame is used when resolving forward annotations during schema rebuilding, by looking for
|
||||
the locals of this frame. Defaults to 2, which will result in the frame where the method
|
||||
was called.
|
||||
_types_namespace: An explicit types namespace to use, instead of using the local namespace
|
||||
from the parent frame. Defaults to `None`.
|
||||
|
||||
Returns:
|
||||
Returns `None` if the schema is already "complete" and rebuilding was not required.
|
||||
If rebuilding _was_ required, returns `True` if rebuilding was successful, otherwise `False`.
|
||||
"""
|
||||
if not force and self.pydantic_complete:
|
||||
return None
|
||||
|
||||
if _types_namespace is not None:
|
||||
rebuild_ns = _types_namespace
|
||||
elif _parent_namespace_depth > 0:
|
||||
rebuild_ns = _typing_extra.parent_frame_namespace(parent_depth=_parent_namespace_depth, force=True) or {}
|
||||
else:
|
||||
rebuild_ns = {}
|
||||
|
||||
# we have to manually fetch globals here because there's no type on the stack of the NsResolver
|
||||
# and so we skip the globalns = get_module_ns_of(typ) call that would normally happen
|
||||
globalns = sys._getframe(max(_parent_namespace_depth - 1, 1)).f_globals
|
||||
ns_resolver = _namespace_utils.NsResolver(
|
||||
namespaces_tuple=_namespace_utils.NamespacesTuple(locals=rebuild_ns, globals=globalns),
|
||||
parent_namespace=rebuild_ns,
|
||||
)
|
||||
return self._init_core_attrs(ns_resolver=ns_resolver, force=True, raise_errors=raise_errors)
|
||||
|
||||
def validate_python(
|
||||
self,
|
||||
object: Any,
|
||||
/,
|
||||
*,
|
||||
strict: bool | None = None,
|
||||
extra: ExtraValues | None = None,
|
||||
from_attributes: bool | None = None,
|
||||
context: Any | None = None,
|
||||
experimental_allow_partial: bool | Literal['off', 'on', 'trailing-strings'] = False,
|
||||
by_alias: bool | None = None,
|
||||
by_name: bool | None = None,
|
||||
) -> T:
|
||||
"""Validate a Python object against the model.
|
||||
|
||||
Args:
|
||||
object: The Python object to validate against the model.
|
||||
strict: Whether to strictly check types.
|
||||
extra: Whether to ignore, allow, or forbid extra data during model validation.
|
||||
See the [`extra` configuration value][pydantic.ConfigDict.extra] for details.
|
||||
from_attributes: Whether to extract data from object attributes.
|
||||
context: Additional context to pass to the validator.
|
||||
experimental_allow_partial: **Experimental** whether to enable
|
||||
[partial validation](../concepts/experimental.md#partial-validation), e.g. to process streams.
|
||||
* False / 'off': Default behavior, no partial validation.
|
||||
* True / 'on': Enable partial validation.
|
||||
* 'trailing-strings': Enable partial validation and allow trailing strings in the input.
|
||||
by_alias: Whether to use the field's alias when validating against the provided input data.
|
||||
by_name: Whether to use the field's name when validating against the provided input data.
|
||||
|
||||
!!! note
|
||||
When using `TypeAdapter` with a Pydantic `dataclass`, the use of the `from_attributes`
|
||||
argument is not supported.
|
||||
|
||||
Returns:
|
||||
The validated object.
|
||||
"""
|
||||
if by_alias is False and by_name is not True:
|
||||
raise PydanticUserError(
|
||||
'At least one of `by_alias` or `by_name` must be set to True.',
|
||||
code='validate-by-alias-and-name-false',
|
||||
)
|
||||
|
||||
return self.validator.validate_python(
|
||||
object,
|
||||
strict=strict,
|
||||
extra=extra,
|
||||
from_attributes=from_attributes,
|
||||
context=context,
|
||||
allow_partial=experimental_allow_partial,
|
||||
by_alias=by_alias,
|
||||
by_name=by_name,
|
||||
)
|
||||
|
||||
def validate_json(
|
||||
self,
|
||||
data: str | bytes | bytearray,
|
||||
/,
|
||||
*,
|
||||
strict: bool | None = None,
|
||||
extra: ExtraValues | None = None,
|
||||
context: Any | None = None,
|
||||
experimental_allow_partial: bool | Literal['off', 'on', 'trailing-strings'] = False,
|
||||
by_alias: bool | None = None,
|
||||
by_name: bool | None = None,
|
||||
) -> T:
|
||||
"""!!! abstract "Usage Documentation"
|
||||
[JSON Parsing](../concepts/json.md#json-parsing)
|
||||
|
||||
Validate a JSON string or bytes against the model.
|
||||
|
||||
Args:
|
||||
data: The JSON data to validate against the model.
|
||||
strict: Whether to strictly check types.
|
||||
extra: Whether to ignore, allow, or forbid extra data during model validation.
|
||||
See the [`extra` configuration value][pydantic.ConfigDict.extra] for details.
|
||||
context: Additional context to use during validation.
|
||||
experimental_allow_partial: **Experimental** whether to enable
|
||||
[partial validation](../concepts/experimental.md#partial-validation), e.g. to process streams.
|
||||
* False / 'off': Default behavior, no partial validation.
|
||||
* True / 'on': Enable partial validation.
|
||||
* 'trailing-strings': Enable partial validation and allow trailing strings in the input.
|
||||
by_alias: Whether to use the field's alias when validating against the provided input data.
|
||||
by_name: Whether to use the field's name when validating against the provided input data.
|
||||
|
||||
Returns:
|
||||
The validated object.
|
||||
"""
|
||||
if by_alias is False and by_name is not True:
|
||||
raise PydanticUserError(
|
||||
'At least one of `by_alias` or `by_name` must be set to True.',
|
||||
code='validate-by-alias-and-name-false',
|
||||
)
|
||||
|
||||
return self.validator.validate_json(
|
||||
data,
|
||||
strict=strict,
|
||||
extra=extra,
|
||||
context=context,
|
||||
allow_partial=experimental_allow_partial,
|
||||
by_alias=by_alias,
|
||||
by_name=by_name,
|
||||
)
|
||||
|
||||
def validate_strings(
|
||||
self,
|
||||
obj: Any,
|
||||
/,
|
||||
*,
|
||||
strict: bool | None = None,
|
||||
extra: ExtraValues | None = None,
|
||||
context: Any | None = None,
|
||||
experimental_allow_partial: bool | Literal['off', 'on', 'trailing-strings'] = False,
|
||||
by_alias: bool | None = None,
|
||||
by_name: bool | None = None,
|
||||
) -> T:
|
||||
"""Validate object contains string data against the model.
|
||||
|
||||
Args:
|
||||
obj: The object contains string data to validate.
|
||||
strict: Whether to strictly check types.
|
||||
extra: Whether to ignore, allow, or forbid extra data during model validation.
|
||||
See the [`extra` configuration value][pydantic.ConfigDict.extra] for details.
|
||||
context: Additional context to use during validation.
|
||||
experimental_allow_partial: **Experimental** whether to enable
|
||||
[partial validation](../concepts/experimental.md#partial-validation), e.g. to process streams.
|
||||
* False / 'off': Default behavior, no partial validation.
|
||||
* True / 'on': Enable partial validation.
|
||||
* 'trailing-strings': Enable partial validation and allow trailing strings in the input.
|
||||
by_alias: Whether to use the field's alias when validating against the provided input data.
|
||||
by_name: Whether to use the field's name when validating against the provided input data.
|
||||
|
||||
Returns:
|
||||
The validated object.
|
||||
"""
|
||||
if by_alias is False and by_name is not True:
|
||||
raise PydanticUserError(
|
||||
'At least one of `by_alias` or `by_name` must be set to True.',
|
||||
code='validate-by-alias-and-name-false',
|
||||
)
|
||||
|
||||
return self.validator.validate_strings(
|
||||
obj,
|
||||
strict=strict,
|
||||
extra=extra,
|
||||
context=context,
|
||||
allow_partial=experimental_allow_partial,
|
||||
by_alias=by_alias,
|
||||
by_name=by_name,
|
||||
)
|
||||
|
||||
def get_default_value(self, *, strict: bool | None = None, context: Any | None = None) -> Some[T] | None:
|
||||
"""Get the default value for the wrapped type.
|
||||
|
||||
Args:
|
||||
strict: Whether to strictly check types.
|
||||
context: Additional context to pass to the validator.
|
||||
|
||||
Returns:
|
||||
The default value wrapped in a `Some` if there is one or None if not.
|
||||
"""
|
||||
return self.validator.get_default_value(strict=strict, context=context)
|
||||
|
||||
def dump_python(
|
||||
self,
|
||||
instance: T,
|
||||
/,
|
||||
*,
|
||||
mode: Literal['json', 'python'] = 'python',
|
||||
include: IncEx | None = None,
|
||||
exclude: IncEx | None = None,
|
||||
by_alias: bool | None = None,
|
||||
exclude_unset: bool = False,
|
||||
exclude_defaults: bool = False,
|
||||
exclude_none: bool = False,
|
||||
exclude_computed_fields: bool = False,
|
||||
round_trip: bool = False,
|
||||
warnings: bool | Literal['none', 'warn', 'error'] = True,
|
||||
fallback: Callable[[Any], Any] | None = None,
|
||||
serialize_as_any: bool = False,
|
||||
polymorphic_serialization: bool | None = None,
|
||||
context: Any | None = None,
|
||||
) -> Any:
|
||||
"""Dump an instance of the adapted type to a Python object.
|
||||
|
||||
Args:
|
||||
instance: The Python object to serialize.
|
||||
mode: The output format.
|
||||
include: Fields to include in the output.
|
||||
exclude: Fields to exclude from the output.
|
||||
by_alias: Whether to use alias names for field names.
|
||||
exclude_unset: Whether to exclude unset fields.
|
||||
exclude_defaults: Whether to exclude fields with default values.
|
||||
exclude_none: Whether to exclude fields with None values.
|
||||
exclude_computed_fields: Whether to exclude computed fields.
|
||||
While this can be useful for round-tripping, it is usually recommended to use the dedicated
|
||||
`round_trip` parameter instead.
|
||||
round_trip: Whether to output the serialized data in a way that is compatible with deserialization.
|
||||
warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors,
|
||||
"error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError].
|
||||
fallback: A function to call when an unknown value is encountered. If not provided,
|
||||
a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised.
|
||||
serialize_as_any: Whether to serialize fields with duck-typing serialization behavior.
|
||||
polymorphic_serialization: Whether to use model and dataclass polymorphic serialization for this call.
|
||||
context: Additional context to pass to the serializer.
|
||||
|
||||
Returns:
|
||||
The serialized object.
|
||||
"""
|
||||
return self.serializer.to_python(
|
||||
instance,
|
||||
mode=mode,
|
||||
by_alias=by_alias,
|
||||
include=include,
|
||||
exclude=exclude,
|
||||
exclude_unset=exclude_unset,
|
||||
exclude_defaults=exclude_defaults,
|
||||
exclude_none=exclude_none,
|
||||
exclude_computed_fields=exclude_computed_fields,
|
||||
round_trip=round_trip,
|
||||
warnings=warnings,
|
||||
fallback=fallback,
|
||||
serialize_as_any=serialize_as_any,
|
||||
polymorphic_serialization=polymorphic_serialization,
|
||||
context=context,
|
||||
)
|
||||
|
||||
def dump_json(
|
||||
self,
|
||||
instance: T,
|
||||
/,
|
||||
*,
|
||||
indent: int | None = None,
|
||||
ensure_ascii: bool = False,
|
||||
include: IncEx | None = None,
|
||||
exclude: IncEx | None = None,
|
||||
by_alias: bool | None = None,
|
||||
exclude_unset: bool = False,
|
||||
exclude_defaults: bool = False,
|
||||
exclude_none: bool = False,
|
||||
exclude_computed_fields: bool = False,
|
||||
round_trip: bool = False,
|
||||
warnings: bool | Literal['none', 'warn', 'error'] = True,
|
||||
fallback: Callable[[Any], Any] | None = None,
|
||||
serialize_as_any: bool = False,
|
||||
polymorphic_serialization: bool | None = None,
|
||||
context: Any | None = None,
|
||||
) -> bytes:
|
||||
"""!!! abstract "Usage Documentation"
|
||||
[JSON Serialization](../concepts/json.md#json-serialization)
|
||||
|
||||
Serialize an instance of the adapted type to JSON.
|
||||
|
||||
Args:
|
||||
instance: The instance to be serialized.
|
||||
indent: Number of spaces for JSON indentation.
|
||||
ensure_ascii: If `True`, the output is guaranteed to have all incoming non-ASCII characters escaped.
|
||||
If `False` (the default), these characters will be output as-is.
|
||||
include: Fields to include.
|
||||
exclude: Fields to exclude.
|
||||
by_alias: Whether to use alias names for field names.
|
||||
exclude_unset: Whether to exclude unset fields.
|
||||
exclude_defaults: Whether to exclude fields with default values.
|
||||
exclude_none: Whether to exclude fields with a value of `None`.
|
||||
exclude_computed_fields: Whether to exclude computed fields.
|
||||
While this can be useful for round-tripping, it is usually recommended to use the dedicated
|
||||
`round_trip` parameter instead.
|
||||
round_trip: Whether to serialize and deserialize the instance to ensure round-tripping.
|
||||
warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors,
|
||||
"error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError].
|
||||
fallback: A function to call when an unknown value is encountered. If not provided,
|
||||
a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised.
|
||||
serialize_as_any: Whether to serialize fields with duck-typing serialization behavior.
|
||||
polymorphic_serialization: Whether to use model and dataclass polymorphic serialization for this call.
|
||||
context: Additional context to pass to the serializer.
|
||||
|
||||
Returns:
|
||||
The JSON representation of the given instance as bytes.
|
||||
"""
|
||||
return self.serializer.to_json(
|
||||
instance,
|
||||
indent=indent,
|
||||
ensure_ascii=ensure_ascii,
|
||||
include=include,
|
||||
exclude=exclude,
|
||||
by_alias=by_alias,
|
||||
exclude_unset=exclude_unset,
|
||||
exclude_defaults=exclude_defaults,
|
||||
exclude_none=exclude_none,
|
||||
exclude_computed_fields=exclude_computed_fields,
|
||||
round_trip=round_trip,
|
||||
warnings=warnings,
|
||||
fallback=fallback,
|
||||
serialize_as_any=serialize_as_any,
|
||||
polymorphic_serialization=polymorphic_serialization,
|
||||
context=context,
|
||||
)
|
||||
|
||||
def json_schema(
|
||||
self,
|
||||
*,
|
||||
by_alias: bool = True,
|
||||
ref_template: str = DEFAULT_REF_TEMPLATE,
|
||||
union_format: Literal['any_of', 'primitive_type_array'] = 'any_of',
|
||||
schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema,
|
||||
mode: JsonSchemaMode = 'validation',
|
||||
) -> dict[str, Any]:
|
||||
"""Generate a JSON schema for the adapted type.
|
||||
|
||||
Args:
|
||||
by_alias: Whether to use alias names for field names.
|
||||
ref_template: The format string used for generating $ref strings.
|
||||
union_format: The format to use when combining schemas from unions together. Can be one of:
|
||||
|
||||
- `'any_of'`: Use the [`anyOf`](https://json-schema.org/understanding-json-schema/reference/combining#anyOf)
|
||||
keyword to combine schemas (the default).
|
||||
- `'primitive_type_array'`: Use the [`type`](https://json-schema.org/understanding-json-schema/reference/type)
|
||||
keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive
|
||||
type (`string`, `boolean`, `null`, `integer` or `number`) or contains constraints/metadata, falls back to
|
||||
`any_of`.
|
||||
schema_generator: To override the logic used to generate the JSON schema, as a subclass of
|
||||
`GenerateJsonSchema` with your desired modifications
|
||||
mode: The mode in which to generate the schema.
|
||||
schema_generator: The generator class used for creating the schema.
|
||||
mode: The mode to use for schema generation.
|
||||
|
||||
Returns:
|
||||
The JSON schema for the model as a dictionary.
|
||||
"""
|
||||
schema_generator_instance = schema_generator(
|
||||
by_alias=by_alias, ref_template=ref_template, union_format=union_format
|
||||
)
|
||||
if isinstance(self.core_schema, _mock_val_ser.MockCoreSchema):
|
||||
self.core_schema.rebuild()
|
||||
assert not isinstance(self.core_schema, _mock_val_ser.MockCoreSchema), 'this is a bug! please report it'
|
||||
return schema_generator_instance.generate(self.core_schema, mode=mode)
|
||||
|
||||
@staticmethod
|
||||
def json_schemas(
|
||||
inputs: Iterable[tuple[JsonSchemaKeyT, JsonSchemaMode, TypeAdapter[Any]]],
|
||||
/,
|
||||
*,
|
||||
by_alias: bool = True,
|
||||
title: str | None = None,
|
||||
description: str | None = None,
|
||||
ref_template: str = DEFAULT_REF_TEMPLATE,
|
||||
union_format: Literal['any_of', 'primitive_type_array'] = 'any_of',
|
||||
schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema,
|
||||
) -> tuple[dict[tuple[JsonSchemaKeyT, JsonSchemaMode], JsonSchemaValue], JsonSchemaValue]:
|
||||
"""Generate a JSON schema including definitions from multiple type adapters.
|
||||
|
||||
Args:
|
||||
inputs: Inputs to schema generation. The first two items will form the keys of the (first)
|
||||
output mapping; the type adapters will provide the core schemas that get converted into
|
||||
definitions in the output JSON schema.
|
||||
by_alias: Whether to use alias names.
|
||||
title: The title for the schema.
|
||||
description: The description for the schema.
|
||||
ref_template: The format string used for generating $ref strings.
|
||||
union_format: The format to use when combining schemas from unions together. Can be one of:
|
||||
|
||||
- `'any_of'`: Use the [`anyOf`](https://json-schema.org/understanding-json-schema/reference/combining#anyOf)
|
||||
keyword to combine schemas (the default).
|
||||
- `'primitive_type_array'`: Use the [`type`](https://json-schema.org/understanding-json-schema/reference/type)
|
||||
keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive
|
||||
type (`string`, `boolean`, `null`, `integer` or `number`) or contains constraints/metadata, falls back to
|
||||
`any_of`.
|
||||
schema_generator: The generator class used for creating the schema.
|
||||
|
||||
Returns:
|
||||
A tuple where:
|
||||
|
||||
- The first element is a dictionary whose keys are tuples of JSON schema key type and JSON mode, and
|
||||
whose values are the JSON schema corresponding to that pair of inputs. (These schemas may have
|
||||
JsonRef references to definitions that are defined in the second returned element.)
|
||||
- The second element is a JSON schema containing all definitions referenced in the first returned
|
||||
element, along with the optional title and description keys.
|
||||
|
||||
"""
|
||||
schema_generator_instance = schema_generator(
|
||||
by_alias=by_alias, ref_template=ref_template, union_format=union_format
|
||||
)
|
||||
|
||||
inputs_ = []
|
||||
for key, mode, adapter in inputs:
|
||||
# This is the same pattern we follow for model json schemas - we attempt a core schema rebuild if we detect a mock
|
||||
if isinstance(adapter.core_schema, _mock_val_ser.MockCoreSchema):
|
||||
adapter.core_schema.rebuild()
|
||||
assert not isinstance(adapter.core_schema, _mock_val_ser.MockCoreSchema), (
|
||||
'this is a bug! please report it'
|
||||
)
|
||||
inputs_.append((key, mode, adapter.core_schema))
|
||||
|
||||
json_schemas_map, definitions = schema_generator_instance.generate_definitions(inputs_)
|
||||
|
||||
json_schema: dict[str, Any] = {}
|
||||
if definitions:
|
||||
json_schema['$defs'] = definitions
|
||||
if title:
|
||||
json_schema['title'] = title
|
||||
if description:
|
||||
json_schema['description'] = description
|
||||
|
||||
return json_schemas_map, json_schema
|
||||
3310
venv/Lib/site-packages/pydantic/types.py
Normal file
3310
venv/Lib/site-packages/pydantic/types.py
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user