Coverage for pydantic/_internal/_generate_schema.py: 95.08%
1291 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-02 16:20 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-02 16:20 +0000
1"""Convert python types to pydantic-core schema."""
3from __future__ import annotations as _annotations 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
5import collections.abc 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
6import dataclasses 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
7import datetime 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
8import inspect 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
9import os 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
10import pathlib 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
11import re 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
12import sys 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
13import typing 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
14import warnings 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
15from collections.abc import Generator, Iterable, Iterator, Mapping 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
16from contextlib import contextmanager 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
17from copy import copy 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
18from decimal import Decimal 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
19from enum import Enum 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
20from fractions import Fraction 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
21from functools import partial 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
22from inspect import Parameter, _ParameterKind, signature 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
23from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
24from itertools import chain 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
25from operator import attrgetter 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
26from types import FunctionType, GenericAlias, LambdaType, MethodType 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
27from typing import ( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
28 TYPE_CHECKING,
29 Any,
30 Callable,
31 Final,
32 ForwardRef,
33 Literal,
34 TypeVar,
35 Union,
36 cast,
37 overload,
38)
39from uuid import UUID 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
40from warnings import warn 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
41from zoneinfo import ZoneInfo 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
43import typing_extensions 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
44from pydantic_core import ( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
45 CoreSchema,
46 MultiHostUrl,
47 PydanticCustomError,
48 PydanticSerializationUnexpectedValue,
49 PydanticUndefined,
50 Url,
51 core_schema,
52 to_jsonable_python,
53)
54from typing_extensions import TypeAlias, TypeAliasType, TypedDict, get_args, get_origin, is_typeddict 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
55from typing_inspection import typing_objects 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
56from typing_inspection.introspection import AnnotationSource, get_literal_values, is_union_origin 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
58from ..aliases import AliasChoices, AliasPath 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
59from ..annotated_handlers import GetCoreSchemaHandler, GetJsonSchemaHandler 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
60from ..config import ConfigDict, JsonDict, JsonEncoder, JsonSchemaExtraCallable 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
61from ..errors import PydanticSchemaGenerationError, PydanticUndefinedAnnotation, PydanticUserError 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
62from ..functional_validators import AfterValidator, BeforeValidator, FieldValidatorModes, PlainValidator, WrapValidator 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
63from ..json_schema import JsonSchemaValue 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
64from ..version import version_short 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
65from ..warnings import PydanticDeprecatedSince20 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
66from . import _decorators, _discriminated_union, _known_annotated_metadata, _repr, _typing_extra 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
67from ._config import ConfigWrapper, ConfigWrapperStack 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
68from ._core_metadata import CoreMetadata, update_core_metadata 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
69from ._core_utils import ( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
70 get_ref,
71 get_type_ref,
72 is_list_like_schema_with_items_schema,
73 validate_core_schema,
74)
75from ._decorators import ( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
76 Decorator,
77 DecoratorInfos,
78 FieldSerializerDecoratorInfo,
79 FieldValidatorDecoratorInfo,
80 ModelSerializerDecoratorInfo,
81 ModelValidatorDecoratorInfo,
82 RootValidatorDecoratorInfo,
83 ValidatorDecoratorInfo,
84 get_attribute_from_bases,
85 inspect_field_serializer,
86 inspect_model_serializer,
87 inspect_validator,
88)
89from ._docs_extraction import extract_docstrings_from_cls 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
90from ._fields import ( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
91 collect_dataclass_fields,
92 rebuild_model_fields,
93 takes_validated_data_argument,
94 update_field_from_config,
95)
96from ._forward_ref import PydanticRecursiveRef 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
97from ._generics import get_standard_typevars_map, replace_types 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
98from ._import_utils import import_cached_base_model, import_cached_field_info 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
99from ._mock_val_ser import MockCoreSchema 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
100from ._namespace_utils import NamespacesTuple, NsResolver 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
101from ._schema_gather import MissingDefinitionError, gather_schemas_for_cleaning 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
102from ._schema_generation_shared import CallbackGetCoreSchemaHandler 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
103from ._utils import lenient_issubclass, smart_deepcopy 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
105if TYPE_CHECKING: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
106 from ..fields import ComputedFieldInfo, FieldInfo
107 from ..main import BaseModel
108 from ..types import Discriminator
109 from ._dataclasses import StandardDataclass
110 from ._schema_generation_shared import GetJsonSchemaFunction
112_SUPPORTS_TYPEDDICT = sys.version_info >= (3, 12) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
114FieldDecoratorInfo = Union[ValidatorDecoratorInfo, FieldValidatorDecoratorInfo, FieldSerializerDecoratorInfo] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
115FieldDecoratorInfoType = TypeVar('FieldDecoratorInfoType', bound=FieldDecoratorInfo) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
116AnyFieldDecorator = Union[ 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
117 Decorator[ValidatorDecoratorInfo],
118 Decorator[FieldValidatorDecoratorInfo],
119 Decorator[FieldSerializerDecoratorInfo],
120]
122ModifyCoreSchemaWrapHandler: TypeAlias = GetCoreSchemaHandler 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
123GetCoreSchemaFunction: TypeAlias = Callable[[Any, ModifyCoreSchemaWrapHandler], core_schema.CoreSchema] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
124ParametersCallback: TypeAlias = "Callable[[int, str, Any], Literal['skip'] | None]" 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
126TUPLE_TYPES: list[type] = [typing.Tuple, tuple] # noqa: UP006 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
127LIST_TYPES: list[type] = [typing.List, list, collections.abc.MutableSequence] # noqa: UP006 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
128SET_TYPES: list[type] = [typing.Set, set, collections.abc.MutableSet] # noqa: UP006 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
129FROZEN_SET_TYPES: list[type] = [typing.FrozenSet, frozenset, collections.abc.Set] # noqa: UP006 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
130DICT_TYPES: list[type] = [typing.Dict, dict] # noqa: UP006 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
131IP_TYPES: list[type] = [IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
132SEQUENCE_TYPES: list[type] = [typing.Sequence, collections.abc.Sequence] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
133ITERABLE_TYPES: list[type] = [typing.Iterable, collections.abc.Iterable, typing.Generator, collections.abc.Generator] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
134TYPE_TYPES: list[type] = [typing.Type, type] # noqa: UP006 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
135PATTERN_TYPES: list[type] = [typing.Pattern, re.Pattern] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
136PATH_TYPES: list[type] = [ 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
137 os.PathLike,
138 pathlib.Path,
139 pathlib.PurePath,
140 pathlib.PosixPath,
141 pathlib.PurePosixPath,
142 pathlib.PureWindowsPath,
143]
144MAPPING_TYPES = [ 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
145 typing.Mapping,
146 typing.MutableMapping,
147 collections.abc.Mapping,
148 collections.abc.MutableMapping,
149 collections.OrderedDict,
150 typing_extensions.OrderedDict,
151 typing.DefaultDict, # noqa: UP006
152 collections.defaultdict,
153]
154COUNTER_TYPES = [collections.Counter, typing.Counter] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
155DEQUE_TYPES: list[type] = [collections.deque, typing.Deque] # noqa: UP006 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
157# Note: This does not play very well with type checkers. For example,
158# `a: LambdaType = lambda x: x` will raise a type error by Pyright.
159ValidateCallSupportedTypes = Union[ 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
160 LambdaType,
161 FunctionType,
162 MethodType,
163 partial,
164]
166VALIDATE_CALL_SUPPORTED_TYPES = get_args(ValidateCallSupportedTypes) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
168_mode_to_validator: dict[ 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
169 FieldValidatorModes, type[BeforeValidator | AfterValidator | PlainValidator | WrapValidator]
170] = {'before': BeforeValidator, 'after': AfterValidator, 'plain': PlainValidator, 'wrap': WrapValidator}
173def check_validator_fields_against_field_name( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
174 info: FieldDecoratorInfo,
175 field: str,
176) -> bool:
177 """Check if field name is in validator fields.
179 Args:
180 info: The field info.
181 field: The field name to check.
183 Returns:
184 `True` if field name is in validator fields, `False` otherwise.
185 """
186 fields = info.fields 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
187 return '*' in fields or field in fields 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
190def check_decorator_fields_exist(decorators: Iterable[AnyFieldDecorator], fields: Iterable[str]) -> None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
191 """Check if the defined fields in decorators exist in `fields` param.
193 It ignores the check for a decorator if the decorator has `*` as field or `check_fields=False`.
195 Args:
196 decorators: An iterable of decorators.
197 fields: An iterable of fields name.
199 Raises:
200 PydanticUserError: If one of the field names does not exist in `fields` param.
201 """
202 fields = set(fields) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
203 for dec in decorators: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
204 if '*' in dec.info.fields: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
205 continue 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
206 if dec.info.check_fields is False: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
207 continue 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
208 for field in dec.info.fields: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
209 if field not in fields: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
210 raise PydanticUserError( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
211 f'Decorators defined with incorrect fields: {dec.cls_ref}.{dec.cls_var_name}'
212 " (use check_fields=False if you're inheriting from the model and intended this)",
213 code='decorator-missing-field',
214 )
217def filter_field_decorator_info_by_field( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
218 validator_functions: Iterable[Decorator[FieldDecoratorInfoType]], field: str
219) -> list[Decorator[FieldDecoratorInfoType]]:
220 return [dec for dec in validator_functions if check_validator_fields_against_field_name(dec.info, field)] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
223def apply_each_item_validators( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
224 schema: core_schema.CoreSchema,
225 each_item_validators: list[Decorator[ValidatorDecoratorInfo]],
226) -> core_schema.CoreSchema:
227 # This V1 compatibility shim should eventually be removed
229 # fail early if each_item_validators is empty
230 if not each_item_validators: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
231 return schema 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
233 # push down any `each_item=True` validators
234 # note that this won't work for any Annotated types that get wrapped by a function validator
235 # but that's okay because that didn't exist in V1
236 if schema['type'] == 'nullable': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
237 schema['schema'] = apply_each_item_validators(schema['schema'], each_item_validators) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
238 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
239 elif schema['type'] == 'tuple': 239 ↛ 240line 239 didn't jump to line 240 because the condition on line 239 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
240 if (variadic_item_index := schema.get('variadic_item_index')) is not None:
241 schema['items_schema'][variadic_item_index] = apply_validators(
242 schema['items_schema'][variadic_item_index],
243 each_item_validators,
244 )
245 elif is_list_like_schema_with_items_schema(schema): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
246 inner_schema = schema.get('items_schema', core_schema.any_schema()) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
247 schema['items_schema'] = apply_validators(inner_schema, each_item_validators) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
248 elif schema['type'] == 'dict': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
249 inner_schema = schema.get('values_schema', core_schema.any_schema()) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
250 schema['values_schema'] = apply_validators(inner_schema, each_item_validators) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
251 else:
252 raise TypeError( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
253 f'`@validator(..., each_item=True)` cannot be applied to fields with a schema of {schema["type"]}'
254 )
255 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
258def _extract_json_schema_info_from_field_info( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
259 info: FieldInfo | ComputedFieldInfo,
260) -> tuple[JsonDict | None, JsonDict | JsonSchemaExtraCallable | None]:
261 json_schema_updates = { 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
262 'title': info.title,
263 'description': info.description,
264 'deprecated': bool(info.deprecated) or info.deprecated == '' or None,
265 'examples': to_jsonable_python(info.examples),
266 }
267 json_schema_updates = {k: v for k, v in json_schema_updates.items() if v is not None} 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
268 return (json_schema_updates or None, info.json_schema_extra) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
271JsonEncoders = dict[type[Any], JsonEncoder] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
274def _add_custom_serialization_from_json_encoders( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
275 json_encoders: JsonEncoders | None, tp: Any, schema: CoreSchema
276) -> CoreSchema:
277 """Iterate over the json_encoders and add the first matching encoder to the schema.
279 Args:
280 json_encoders: A dictionary of types and their encoder functions.
281 tp: The type to check for a matching encoder.
282 schema: The schema to add the encoder to.
283 """
284 if not json_encoders: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
285 return schema 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
286 if 'serialization' in schema: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
287 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
288 # Check the class type and its superclasses for a matching encoder
289 # Decimal.__class__.__mro__ (and probably other cases) doesn't include Decimal itself
290 # if the type is a GenericAlias (e.g. from list[int]) we need to use __class__ instead of .__mro__
291 for base in (tp, *getattr(tp, '__mro__', tp.__class__.__mro__)[:-1]): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
292 encoder = json_encoders.get(base) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
293 if encoder is None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
294 continue 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
296 warnings.warn( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
297 f'`json_encoders` is deprecated. See https://docs.pydantic.dev/{version_short()}/concepts/serialization/#custom-serializers for alternatives',
298 PydanticDeprecatedSince20,
299 )
301 # TODO: in theory we should check that the schema accepts a serialization key
302 schema['serialization'] = core_schema.plain_serializer_function_ser_schema(encoder, when_used='json') 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
303 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
305 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
308class InvalidSchemaError(Exception): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
309 """The core schema is invalid."""
312class GenerateSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
313 """Generate core schema for a Pydantic model, dataclass and types like `str`, `datetime`, ... ."""
315 __slots__ = ( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
316 '_config_wrapper_stack',
317 '_ns_resolver',
318 '_typevars_map',
319 'field_name_stack',
320 'model_type_stack',
321 'defs',
322 )
324 def __init__( 1abcfnquwACDhijkrsxyEFGJdlemptvzBHI
325 self,
326 config_wrapper: ConfigWrapper,
327 ns_resolver: NsResolver | None = None,
328 typevars_map: Mapping[TypeVar, Any] | None = None,
329 ) -> None:
330 # we need a stack for recursing into nested models
331 self._config_wrapper_stack = ConfigWrapperStack(config_wrapper) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
332 self._ns_resolver = ns_resolver or NsResolver() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
333 self._typevars_map = typevars_map 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
334 self.field_name_stack = _FieldNameStack() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
335 self.model_type_stack = _ModelTypeStack() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
336 self.defs = _Definitions() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
338 def __init_subclass__(cls) -> None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
339 super().__init_subclass__() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
340 warnings.warn( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
341 'Subclassing `GenerateSchema` is not supported. The API is highly subject to change in minor versions.',
342 UserWarning,
343 stacklevel=2,
344 )
346 @property 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
347 def _config_wrapper(self) -> ConfigWrapper: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
348 return self._config_wrapper_stack.tail 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
350 @property 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
351 def _types_namespace(self) -> NamespacesTuple: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
352 return self._ns_resolver.types_namespace 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
354 @property 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
355 def _arbitrary_types(self) -> bool: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
356 return self._config_wrapper.arbitrary_types_allowed 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
358 # the following methods can be overridden but should be considered
359 # unstable / private APIs
360 def _list_schema(self, items_type: Any) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
361 return core_schema.list_schema(self.generate_schema(items_type)) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
363 def _dict_schema(self, keys_type: Any, values_type: Any) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
364 return core_schema.dict_schema(self.generate_schema(keys_type), self.generate_schema(values_type)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
366 def _set_schema(self, items_type: Any) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
367 return core_schema.set_schema(self.generate_schema(items_type)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
369 def _frozenset_schema(self, items_type: Any) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
370 return core_schema.frozenset_schema(self.generate_schema(items_type)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
372 def _enum_schema(self, enum_type: type[Enum]) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
373 cases: list[Any] = list(enum_type.__members__.values()) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
375 enum_ref = get_type_ref(enum_type) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
376 description = None if not enum_type.__doc__ else inspect.cleandoc(enum_type.__doc__) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
377 if ( 1abog
378 description == 'An enumeration.'
379 ): # This is the default value provided by enum.EnumMeta.__new__; don't use it
380 description = None 1abcfoghijkdlem
381 js_updates = {'title': enum_type.__name__, 'description': description} 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
382 js_updates = {k: v for k, v in js_updates.items() if v is not None} 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
384 sub_type: Literal['str', 'int', 'float'] | None = None 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
385 if issubclass(enum_type, int): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
386 sub_type = 'int' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
387 value_ser_type: core_schema.SerSchema = core_schema.simple_ser_schema('int') 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
388 elif issubclass(enum_type, str): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
389 # this handles `StrEnum` (3.11 only), and also `Foobar(str, Enum)`
390 sub_type = 'str' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
391 value_ser_type = core_schema.simple_ser_schema('str') 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
392 elif issubclass(enum_type, float): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
393 sub_type = 'float' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
394 value_ser_type = core_schema.simple_ser_schema('float') 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
395 else:
396 # TODO this is an ugly hack, how do we trigger an Any schema for serialization?
397 value_ser_type = core_schema.plain_serializer_function_ser_schema(lambda x: x) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
399 if cases: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
401 def get_json_schema(schema: CoreSchema, handler: GetJsonSchemaHandler) -> JsonSchemaValue: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
402 json_schema = handler(schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
403 original_schema = handler.resolve_ref_schema(json_schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
404 original_schema.update(js_updates) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
405 return json_schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
407 # we don't want to add the missing to the schema if it's the default one
408 default_missing = getattr(enum_type._missing_, '__func__', None) is Enum._missing_.__func__ # pyright: ignore[reportFunctionMemberAccess] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
409 enum_schema = core_schema.enum_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
410 enum_type,
411 cases,
412 sub_type=sub_type,
413 missing=None if default_missing else enum_type._missing_,
414 ref=enum_ref,
415 metadata={'pydantic_js_functions': [get_json_schema]},
416 )
418 if self._config_wrapper.use_enum_values: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
419 enum_schema = core_schema.no_info_after_validator_function( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
420 attrgetter('value'), enum_schema, serialization=value_ser_type
421 )
423 return enum_schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
425 else:
427 def get_json_schema_no_cases(_, handler: GetJsonSchemaHandler) -> JsonSchemaValue: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
428 json_schema = handler(core_schema.enum_schema(enum_type, cases, sub_type=sub_type, ref=enum_ref)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
429 original_schema = handler.resolve_ref_schema(json_schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
430 original_schema.update(js_updates) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
431 return json_schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
433 # Use an isinstance check for enums with no cases.
434 # The most important use case for this is creating TypeVar bounds for generics that should
435 # be restricted to enums. This is more consistent than it might seem at first, since you can only
436 # subclass enum.Enum (or subclasses of enum.Enum) if all parent classes have no cases.
437 # We use the get_json_schema function when an Enum subclass has been declared with no cases
438 # so that we can still generate a valid json schema.
439 return core_schema.is_instance_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
440 enum_type,
441 metadata={'pydantic_js_functions': [get_json_schema_no_cases]},
442 )
444 def _ip_schema(self, tp: Any) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
445 from ._validators import IP_VALIDATOR_LOOKUP, IpType 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
447 ip_type_json_schema_format: dict[type[IpType], str] = { 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
448 IPv4Address: 'ipv4',
449 IPv4Network: 'ipv4network',
450 IPv4Interface: 'ipv4interface',
451 IPv6Address: 'ipv6',
452 IPv6Network: 'ipv6network',
453 IPv6Interface: 'ipv6interface',
454 }
456 def ser_ip(ip: Any, info: core_schema.SerializationInfo) -> str | IpType: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
457 if not isinstance(ip, (tp, str)): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
458 raise PydanticSerializationUnexpectedValue( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
459 f"Expected `{tp}` but got `{type(ip)}` with value `'{ip}'` - serialized value may not be as expected."
460 )
461 if info.mode == 'python': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
462 return ip 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
463 return str(ip) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
465 return core_schema.lax_or_strict_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
466 lax_schema=core_schema.no_info_plain_validator_function(IP_VALIDATOR_LOOKUP[tp]),
467 strict_schema=core_schema.json_or_python_schema(
468 json_schema=core_schema.no_info_after_validator_function(tp, core_schema.str_schema()),
469 python_schema=core_schema.is_instance_schema(tp),
470 ),
471 serialization=core_schema.plain_serializer_function_ser_schema(ser_ip, info_arg=True, when_used='always'),
472 metadata={
473 'pydantic_js_functions': [lambda _1, _2: {'type': 'string', 'format': ip_type_json_schema_format[tp]}]
474 },
475 )
477 def _path_schema(self, tp: Any, path_type: Any) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
478 if tp is os.PathLike and (path_type not in {str, bytes} and not typing_objects.is_any(path_type)): 478 ↛ 479line 478 didn't jump to line 479 because the condition on line 478 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
479 raise PydanticUserError(
480 '`os.PathLike` can only be used with `str`, `bytes` or `Any`', code='schema-for-unknown-type'
481 )
483 path_constructor = pathlib.PurePath if tp is os.PathLike else tp 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
484 strict_inner_schema = ( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
485 core_schema.bytes_schema(strict=True) if (path_type is bytes) else core_schema.str_schema(strict=True)
486 )
487 lax_inner_schema = core_schema.bytes_schema() if (path_type is bytes) else core_schema.str_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
489 def path_validator(input_value: str | bytes) -> os.PathLike[Any]: # type: ignore 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
490 try: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
491 if path_type is bytes: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
492 if isinstance(input_value, bytes): 492 ↛ 498line 492 didn't jump to line 498 because the condition on line 492 was always true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
493 try: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
494 input_value = input_value.decode() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
495 except UnicodeDecodeError as e:
496 raise PydanticCustomError('bytes_type', 'Input must be valid bytes') from e
497 else:
498 raise PydanticCustomError('bytes_type', 'Input must be bytes')
499 elif not isinstance(input_value, str): 499 ↛ 500line 499 didn't jump to line 500 because the condition on line 499 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
500 raise PydanticCustomError('path_type', 'Input is not a valid path')
502 return path_constructor(input_value) # type: ignore 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
503 except TypeError as e:
504 raise PydanticCustomError('path_type', 'Input is not a valid path') from e
506 def ser_path(path: Any, info: core_schema.SerializationInfo) -> str | os.PathLike[Any]: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
507 if not isinstance(path, (tp, str)): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
508 raise PydanticSerializationUnexpectedValue( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
509 f"Expected `{tp}` but got `{type(path)}` with value `'{path}'` - serialized value may not be as expected."
510 )
511 if info.mode == 'python': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
512 return path 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
513 return str(path) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
515 instance_schema = core_schema.json_or_python_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
516 json_schema=core_schema.no_info_after_validator_function(path_validator, lax_inner_schema),
517 python_schema=core_schema.is_instance_schema(tp),
518 )
520 schema = core_schema.lax_or_strict_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
521 lax_schema=core_schema.union_schema(
522 [
523 instance_schema,
524 core_schema.no_info_after_validator_function(path_validator, strict_inner_schema),
525 ],
526 custom_error_type='path_type',
527 custom_error_message=f'Input is not a valid path for {tp}',
528 ),
529 strict_schema=instance_schema,
530 serialization=core_schema.plain_serializer_function_ser_schema(ser_path, info_arg=True, when_used='always'),
531 metadata={'pydantic_js_functions': [lambda source, handler: {**handler(source), 'format': 'path'}]},
532 )
533 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
535 def _deque_schema(self, items_type: Any) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
536 from ._serializers import serialize_sequence_via_list 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
537 from ._validators import deque_validator 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
539 item_type_schema = self.generate_schema(items_type) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
541 # we have to use a lax list schema here, because we need to validate the deque's
542 # items via a list schema, but it's ok if the deque itself is not a list
543 list_schema = core_schema.list_schema(item_type_schema, strict=False) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
545 check_instance = core_schema.json_or_python_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
546 json_schema=list_schema,
547 python_schema=core_schema.is_instance_schema(collections.deque, cls_repr='Deque'),
548 )
550 lax_schema = core_schema.no_info_wrap_validator_function(deque_validator, list_schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
552 return core_schema.lax_or_strict_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
553 lax_schema=lax_schema,
554 strict_schema=core_schema.chain_schema([check_instance, lax_schema]),
555 serialization=core_schema.wrap_serializer_function_ser_schema(
556 serialize_sequence_via_list, schema=item_type_schema, info_arg=True
557 ),
558 )
560 def _mapping_schema(self, tp: Any, keys_type: Any, values_type: Any) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
561 from ._validators import MAPPING_ORIGIN_MAP, defaultdict_validator, get_defaultdict_default_default_factory 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
563 mapped_origin = MAPPING_ORIGIN_MAP[tp] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
564 keys_schema = self.generate_schema(keys_type) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
565 values_schema = self.generate_schema(values_type) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
566 dict_schema = core_schema.dict_schema(keys_schema, values_schema, strict=False) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
568 if mapped_origin is dict: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
569 schema = dict_schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
570 else:
571 check_instance = core_schema.json_or_python_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
572 json_schema=dict_schema,
573 python_schema=core_schema.is_instance_schema(mapped_origin),
574 )
576 if tp is collections.defaultdict: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
577 default_default_factory = get_defaultdict_default_default_factory(values_type) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
578 coerce_instance_wrap = partial( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
579 core_schema.no_info_wrap_validator_function,
580 partial(defaultdict_validator, default_default_factory=default_default_factory),
581 )
582 else:
583 coerce_instance_wrap = partial(core_schema.no_info_after_validator_function, mapped_origin) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
585 lax_schema = coerce_instance_wrap(dict_schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
586 strict_schema = core_schema.chain_schema([check_instance, lax_schema]) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
588 schema = core_schema.lax_or_strict_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
589 lax_schema=lax_schema,
590 strict_schema=strict_schema,
591 serialization=core_schema.wrap_serializer_function_ser_schema(
592 lambda v, h: h(v), schema=dict_schema, info_arg=False
593 ),
594 )
596 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
598 def _fraction_schema(self) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
599 """Support for [`fractions.Fraction`][fractions.Fraction]."""
600 from ._validators import fraction_validator 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
602 # TODO: note, this is a fairly common pattern, re lax / strict for attempted type coercion,
603 # can we use a helper function to reduce boilerplate?
604 return core_schema.lax_or_strict_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
605 lax_schema=core_schema.no_info_plain_validator_function(fraction_validator),
606 strict_schema=core_schema.json_or_python_schema(
607 json_schema=core_schema.no_info_plain_validator_function(fraction_validator),
608 python_schema=core_schema.is_instance_schema(Fraction),
609 ),
610 # use str serialization to guarantee round trip behavior
611 serialization=core_schema.to_string_ser_schema(when_used='always'),
612 metadata={'pydantic_js_functions': [lambda _1, _2: {'type': 'string', 'format': 'fraction'}]},
613 )
615 def _arbitrary_type_schema(self, tp: Any) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
616 if not isinstance(tp, type): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
617 warn( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
618 f'{tp!r} is not a Python type (it may be an instance of an object),'
619 ' Pydantic will allow any object with no validation since we cannot even'
620 ' enforce that the input is an instance of the given type.'
621 ' To get rid of this error wrap the type with `pydantic.SkipValidation`.',
622 UserWarning,
623 )
624 return core_schema.any_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
625 return core_schema.is_instance_schema(tp) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
627 def _unknown_type_schema(self, obj: Any) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
628 raise PydanticSchemaGenerationError( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
629 f'Unable to generate pydantic-core schema for {obj!r}. '
630 'Set `arbitrary_types_allowed=True` in the model_config to ignore this error'
631 ' or implement `__get_pydantic_core_schema__` on your type to fully support it.'
632 '\n\nIf you got this error by calling handler(<some type>) within'
633 ' `__get_pydantic_core_schema__` then you likely need to call'
634 ' `handler.generate_schema(<some type>)` since we do not call'
635 ' `__get_pydantic_core_schema__` on `<some type>` otherwise to avoid infinite recursion.'
636 )
638 def _apply_discriminator_to_union( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
639 self, schema: CoreSchema, discriminator: str | Discriminator | None
640 ) -> CoreSchema:
641 if discriminator is None: 641 ↛ 642line 641 didn't jump to line 642 because the condition on line 641 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
642 return schema
643 try: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
644 return _discriminated_union.apply_discriminator( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
645 schema,
646 discriminator,
647 self.defs._definitions,
648 )
649 except _discriminated_union.MissingDefinitionForUnionRef: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
650 # defer until defs are resolved
651 _discriminated_union.set_discriminator_in_metadata( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
652 schema,
653 discriminator,
654 )
655 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
657 def clean_schema(self, schema: CoreSchema) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
658 schema = self.defs.finalize_schema(schema) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
659 schema = validate_core_schema(schema) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
660 return schema 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
662 def _add_js_function(self, metadata_schema: CoreSchema, js_function: Callable[..., Any]) -> None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
663 metadata = metadata_schema.get('metadata', {}) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
664 pydantic_js_functions = metadata.setdefault('pydantic_js_functions', []) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
665 # because of how we generate core schemas for nested generic models
666 # we can end up adding `BaseModel.__get_pydantic_json_schema__` multiple times
667 # this check may fail to catch duplicates if the function is a `functools.partial`
668 # or something like that, but if it does it'll fail by inserting the duplicate
669 if js_function not in pydantic_js_functions: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
670 pydantic_js_functions.append(js_function) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
671 metadata_schema['metadata'] = metadata 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
673 def generate_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
674 self,
675 obj: Any,
676 ) -> core_schema.CoreSchema:
677 """Generate core schema.
679 Args:
680 obj: The object to generate core schema for.
682 Returns:
683 The generated core schema.
685 Raises:
686 PydanticUndefinedAnnotation:
687 If it is not possible to evaluate forward reference.
688 PydanticSchemaGenerationError:
689 If it is not possible to generate pydantic-core schema.
690 TypeError:
691 - If `alias_generator` returns a disallowed type (must be str, AliasPath or AliasChoices).
692 - If V1 style validator with `each_item=True` applied on a wrong field.
693 PydanticUserError:
694 - If `typing.TypedDict` is used instead of `typing_extensions.TypedDict` on Python < 3.12.
695 - If `__modify_schema__` method is used instead of `__get_pydantic_json_schema__`.
696 """
697 schema = self._generate_schema_from_get_schema_method(obj, obj) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
699 if schema is None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
700 schema = self._generate_schema_inner(obj) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
702 metadata_js_function = _extract_get_pydantic_json_schema(obj) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
703 if metadata_js_function is not None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
704 metadata_schema = resolve_original_schema(schema, self.defs) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
705 if metadata_schema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
706 self._add_js_function(metadata_schema, metadata_js_function) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
708 schema = _add_custom_serialization_from_json_encoders(self._config_wrapper.json_encoders, obj, schema) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
710 return schema 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
712 def _model_schema(self, cls: type[BaseModel]) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
713 """Generate schema for a Pydantic model."""
714 BaseModel_ = import_cached_base_model() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
716 with self.defs.get_schema_or_ref(cls) as (model_ref, maybe_schema): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
717 if maybe_schema is not None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
718 return maybe_schema 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
720 schema = cls.__dict__.get('__pydantic_core_schema__') 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
721 if schema is not None and not isinstance(schema, MockCoreSchema): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
722 if schema['type'] == 'definitions': 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
723 schema = self.defs.unpack_definitions(schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
724 ref = get_ref(schema) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
725 if ref: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
726 return self.defs.create_definition_reference_schema(schema) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
727 else:
728 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
730 config_wrapper = ConfigWrapper(cls.model_config, check=False) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
732 with self._config_wrapper_stack.push(config_wrapper), self._ns_resolver.push(cls): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
733 core_config = self._config_wrapper.core_config(title=cls.__name__) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
735 if cls.__pydantic_fields_complete__ or cls is BaseModel_: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
736 fields = getattr(cls, '__pydantic_fields__', {}) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
737 else:
738 if not hasattr(cls, '__pydantic_fields__'): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
739 # This happens when we have a loop in the schema generation:
740 # class Base[T](BaseModel):
741 # t: T
742 #
743 # class Other(BaseModel):
744 # b: 'Base[Other]'
745 # When we build fields for `Other`, we evaluate the forward annotation.
746 # At this point, `Other` doesn't have the model fields set. We create
747 # `Base[Other]`; model fields are successfully built, and we try to generate
748 # a schema for `t: Other`. As `Other.__pydantic_fields__` aren't set, we abort.
749 raise PydanticUndefinedAnnotation( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
750 name=cls.__name__,
751 message=f'Class {cls.__name__!r} is not defined',
752 )
753 try: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
754 fields = rebuild_model_fields( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
755 cls,
756 config_wrapper=self._config_wrapper,
757 ns_resolver=self._ns_resolver,
758 typevars_map=self._typevars_map or {},
759 )
760 except NameError as e: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
761 raise PydanticUndefinedAnnotation.from_name_error(e) from e 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
763 decorators = cls.__pydantic_decorators__ 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
764 computed_fields = decorators.computed_fields 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
765 check_decorator_fields_exist( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
766 chain(
767 decorators.field_validators.values(),
768 decorators.field_serializers.values(),
769 decorators.validators.values(),
770 ),
771 {*fields.keys(), *computed_fields.keys()},
772 )
774 model_validators = decorators.model_validators.values() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
776 extras_schema = None 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
777 extras_keys_schema = None 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
778 if core_config.get('extra_fields_behavior') == 'allow': 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
779 assert cls.__mro__[0] is cls 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
780 assert cls.__mro__[-1] is object 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
781 for candidate_cls in cls.__mro__[:-1]: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
782 extras_annotation = getattr(candidate_cls, '__annotations__', {}).get( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
783 '__pydantic_extra__', None
784 )
785 if extras_annotation is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
786 if isinstance(extras_annotation, str): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
787 extras_annotation = _typing_extra.eval_type_backport( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
788 _typing_extra._make_forward_ref(
789 extras_annotation, is_argument=False, is_class=True
790 ),
791 *self._types_namespace,
792 )
793 tp = get_origin(extras_annotation) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
794 if tp not in DICT_TYPES: 794 ↛ 795line 794 didn't jump to line 795 because the condition on line 794 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
795 raise PydanticSchemaGenerationError(
796 'The type annotation for `__pydantic_extra__` must be `dict[str, ...]`'
797 )
798 extra_keys_type, extra_items_type = self._get_args_resolving_forward_refs( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
799 extras_annotation,
800 required=True,
801 )
802 if extra_keys_type is not str: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
803 extras_keys_schema = self.generate_schema(extra_keys_type) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
804 if not typing_objects.is_any(extra_items_type): 804 ↛ 806line 804 didn't jump to line 806 because the condition on line 804 was always true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
805 extras_schema = self.generate_schema(extra_items_type) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
806 if extras_keys_schema is not None or extras_schema is not None: 806 ↛ 781line 806 didn't jump to line 781 because the condition on line 806 was always true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
807 break 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
809 generic_origin: type[BaseModel] | None = getattr(cls, '__pydantic_generic_metadata__', {}).get('origin') 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
811 if cls.__pydantic_root_model__: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
812 root_field = self._common_field_schema('root', fields['root'], decorators) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
813 inner_schema = root_field['schema'] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
814 inner_schema = apply_model_validators(inner_schema, model_validators, 'inner') 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
815 model_schema = core_schema.model_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
816 cls,
817 inner_schema,
818 generic_origin=generic_origin,
819 custom_init=getattr(cls, '__pydantic_custom_init__', None),
820 root_model=True,
821 post_init=getattr(cls, '__pydantic_post_init__', None),
822 config=core_config,
823 ref=model_ref,
824 )
825 else:
826 fields_schema: core_schema.CoreSchema = core_schema.model_fields_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
827 {k: self._generate_md_field_schema(k, v, decorators) for k, v in fields.items()},
828 computed_fields=[
829 self._computed_field_schema(d, decorators.field_serializers)
830 for d in computed_fields.values()
831 ],
832 extras_schema=extras_schema,
833 extras_keys_schema=extras_keys_schema,
834 model_name=cls.__name__,
835 )
836 inner_schema = apply_validators(fields_schema, decorators.root_validators.values()) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
837 inner_schema = apply_model_validators(inner_schema, model_validators, 'inner') 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
839 model_schema = core_schema.model_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
840 cls,
841 inner_schema,
842 generic_origin=generic_origin,
843 custom_init=getattr(cls, '__pydantic_custom_init__', None),
844 root_model=False,
845 post_init=getattr(cls, '__pydantic_post_init__', None),
846 config=core_config,
847 ref=model_ref,
848 )
850 schema = self._apply_model_serializers(model_schema, decorators.model_serializers.values()) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
851 schema = apply_model_validators(schema, model_validators, 'outer') 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
852 return self.defs.create_definition_reference_schema(schema) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
854 def _resolve_self_type(self, obj: Any) -> Any: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
855 obj = self.model_type_stack.get() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
856 if obj is None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
857 raise PydanticUserError('`typing.Self` is invalid in this context', code='invalid-self-type') 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
858 return obj 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
860 def _generate_schema_from_get_schema_method(self, obj: Any, source: Any) -> core_schema.CoreSchema | None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
861 BaseModel_ = import_cached_base_model() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
863 get_schema = getattr(obj, '__get_pydantic_core_schema__', None) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
864 is_base_model_get_schema = ( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
865 getattr(get_schema, '__func__', None) is BaseModel_.__get_pydantic_core_schema__.__func__ # pyright: ignore[reportFunctionMemberAccess]
866 )
868 if ( 1aboghidl
869 get_schema is not None
870 # BaseModel.__get_pydantic_core_schema__ is defined for backwards compatibility,
871 # to allow existing code to call `super().__get_pydantic_core_schema__` in Pydantic
872 # model that overrides `__get_pydantic_core_schema__`. However, it raises a deprecation
873 # warning stating that the method will be removed, and during the core schema gen we actually
874 # don't call the method:
875 and not is_base_model_get_schema
876 ):
877 # Some referenceable types might have a `__get_pydantic_core_schema__` method
878 # defined on it by users (e.g. on a dataclass). This generally doesn't play well
879 # as these types are already recognized by the `GenerateSchema` class and isn't ideal
880 # as we might end up calling `get_schema_or_ref` (expensive) on types that are actually
881 # not referenceable:
882 with self.defs.get_schema_or_ref(obj) as (_, maybe_schema): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
883 if maybe_schema is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
884 return maybe_schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
886 if obj is source: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
887 ref_mode = 'unpack' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
888 else:
889 ref_mode = 'to-def' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
890 schema = get_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
891 source, CallbackGetCoreSchemaHandler(self._generate_schema_inner, self, ref_mode=ref_mode)
892 )
893 if schema['type'] == 'definitions': 893 ↛ 894line 893 didn't jump to line 894 because the condition on line 893 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
894 schema = self.defs.unpack_definitions(schema)
896 ref = get_ref(schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
897 if ref: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
898 return self.defs.create_definition_reference_schema(schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
900 # Note: if schema is of type `'definition-ref'`, we might want to copy it as a
901 # safety measure (because these are inlined in place -- i.e. mutated directly)
902 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
904 if get_schema is None and (validators := getattr(obj, '__get_validators__', None)) is not None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
905 from pydantic.v1 import BaseModel as BaseModelV1 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
907 if issubclass(obj, BaseModelV1): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
908 warn( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
909 f'Mixing V1 models and V2 models (or constructs, like `TypeAdapter`) is not supported. Please upgrade `{obj.__name__}` to V2.',
910 UserWarning,
911 )
912 else:
913 warn( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
914 '`__get_validators__` is deprecated and will be removed, use `__get_pydantic_core_schema__` instead.',
915 PydanticDeprecatedSince20,
916 )
917 return core_schema.chain_schema([core_schema.with_info_plain_validator_function(v) for v in validators()]) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
919 def _resolve_forward_ref(self, obj: Any) -> Any: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
920 # we assume that types_namespace has the target of forward references in its scope,
921 # but this could fail, for example, if calling Validator on an imported type which contains
922 # forward references to other types only defined in the module from which it was imported
923 # `Validator(SomeImportedTypeAliasWithAForwardReference)`
924 # or the equivalent for BaseModel
925 # class Model(BaseModel):
926 # x: SomeImportedTypeAliasWithAForwardReference
927 try: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
928 obj = _typing_extra.eval_type_backport(obj, *self._types_namespace) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
929 except NameError as e: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
930 raise PydanticUndefinedAnnotation.from_name_error(e) from e 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
932 # if obj is still a ForwardRef, it means we can't evaluate it, raise PydanticUndefinedAnnotation
933 if isinstance(obj, ForwardRef): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
934 raise PydanticUndefinedAnnotation(obj.__forward_arg__, f'Unable to evaluate forward reference {obj}') 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
936 if self._typevars_map: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
937 obj = replace_types(obj, self._typevars_map) 1abcfoghijkdlem
939 return obj 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
941 @overload 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
942 def _get_args_resolving_forward_refs(self, obj: Any, required: Literal[True]) -> tuple[Any, ...]: ... 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
944 @overload 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
945 def _get_args_resolving_forward_refs(self, obj: Any) -> tuple[Any, ...] | None: ... 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
947 def _get_args_resolving_forward_refs(self, obj: Any, required: bool = False) -> tuple[Any, ...] | None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
948 args = get_args(obj) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
949 if args: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
950 if isinstance(obj, GenericAlias): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
951 # PEP 585 generic aliases don't convert args to ForwardRefs, unlike `typing.List/Dict` etc.
952 args = (_typing_extra._make_forward_ref(a) if isinstance(a, str) else a for a in args) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
953 args = tuple(self._resolve_forward_ref(a) if isinstance(a, ForwardRef) else a for a in args) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
954 elif required: # pragma: no cover 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
955 raise TypeError(f'Expected {obj} to have generic parameters but it had none')
956 return args 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
958 def _get_first_arg_or_any(self, obj: Any) -> Any: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
959 args = self._get_args_resolving_forward_refs(obj) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
960 if not args: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
961 return Any 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
962 return args[0] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
964 def _get_first_two_args_or_any(self, obj: Any) -> tuple[Any, Any]: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
965 args = self._get_args_resolving_forward_refs(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
966 if not args: 966 ↛ 967line 966 didn't jump to line 967 because the condition on line 966 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
967 return (Any, Any)
968 if len(args) < 2: 968 ↛ 969line 968 didn't jump to line 969 because the condition on line 968 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
969 origin = get_origin(obj)
970 raise TypeError(f'Expected two type arguments for {origin}, got 1')
971 return args[0], args[1] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
973 def _generate_schema_inner(self, obj: Any) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
974 if typing_objects.is_self(obj): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
975 obj = self._resolve_self_type(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
977 if typing_objects.is_annotated(get_origin(obj)): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
978 return self._annotated_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
980 if isinstance(obj, dict): 980 ↛ 982line 980 didn't jump to line 982 because the condition on line 980 was never true1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
981 # we assume this is already a valid schema
982 return obj # type: ignore[return-value]
984 if isinstance(obj, str): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
985 obj = ForwardRef(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
987 if isinstance(obj, ForwardRef): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
988 return self.generate_schema(self._resolve_forward_ref(obj)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
990 BaseModel = import_cached_base_model() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
992 if lenient_issubclass(obj, BaseModel): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
993 with self.model_type_stack.push(obj): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
994 return self._model_schema(obj) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
996 if isinstance(obj, PydanticRecursiveRef): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
997 return core_schema.definition_reference_schema(schema_ref=obj.type_ref) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
999 return self.match_type(obj) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1001 def match_type(self, obj: Any) -> core_schema.CoreSchema: # noqa: C901 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1002 """Main mapping of types to schemas.
1004 The general structure is a series of if statements starting with the simple cases
1005 (non-generic primitive types) and then handling generics and other more complex cases.
1007 Each case either generates a schema directly, calls into a public user-overridable method
1008 (like `GenerateSchema.tuple_variable_schema`) or calls into a private method that handles some
1009 boilerplate before calling into the user-facing method (e.g. `GenerateSchema._tuple_schema`).
1011 The idea is that we'll evolve this into adding more and more user facing methods over time
1012 as they get requested and we figure out what the right API for them is.
1013 """
1014 if obj is str: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1015 return core_schema.str_schema() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1016 elif obj is bytes: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1017 return core_schema.bytes_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1018 elif obj is int: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1019 return core_schema.int_schema() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1020 elif obj is float: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1021 return core_schema.float_schema() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1022 elif obj is bool: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1023 return core_schema.bool_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1024 elif obj is complex: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1025 return core_schema.complex_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1026 elif typing_objects.is_any(obj) or obj is object: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1027 return core_schema.any_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1028 elif obj is datetime.date: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1029 return core_schema.date_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1030 elif obj is datetime.datetime: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1031 return core_schema.datetime_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1032 elif obj is datetime.time: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1033 return core_schema.time_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1034 elif obj is datetime.timedelta: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1035 return core_schema.timedelta_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1036 elif obj is Decimal: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1037 return core_schema.decimal_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1038 elif obj is UUID: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1039 return core_schema.uuid_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1040 elif obj is Url: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1041 return core_schema.url_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1042 elif obj is Fraction: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1043 return self._fraction_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1044 elif obj is MultiHostUrl: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1045 return core_schema.multi_host_url_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1046 elif obj is None or obj is _typing_extra.NoneType: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1047 return core_schema.none_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1048 elif obj in IP_TYPES: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1049 return self._ip_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1050 elif obj in TUPLE_TYPES: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1051 return self._tuple_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1052 elif obj in LIST_TYPES: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1053 return self._list_schema(Any) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1054 elif obj in SET_TYPES: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1055 return self._set_schema(Any) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1056 elif obj in FROZEN_SET_TYPES: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1057 return self._frozenset_schema(Any) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1058 elif obj in SEQUENCE_TYPES: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1059 return self._sequence_schema(Any) 1acnuAdepvB
1060 elif obj in ITERABLE_TYPES: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1061 return self._iterable_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1062 elif obj in DICT_TYPES: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1063 return self._dict_schema(Any, Any) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1064 elif obj in PATH_TYPES: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1065 return self._path_schema(obj, Any) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1066 elif obj in DEQUE_TYPES: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1067 return self._deque_schema(Any) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1068 elif obj in MAPPING_TYPES: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1069 return self._mapping_schema(obj, Any, Any) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1070 elif obj in COUNTER_TYPES: 1070 ↛ 1071line 1070 didn't jump to line 1071 because the condition on line 1070 was never true1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1071 return self._mapping_schema(obj, Any, int)
1072 elif typing_objects.is_typealiastype(obj): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1073 return self._type_alias_type_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1074 elif obj is type: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1075 return self._type_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1076 elif _typing_extra.is_callable(obj): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1077 return core_schema.callable_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1078 elif typing_objects.is_literal(get_origin(obj)): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1079 return self._literal_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1080 elif is_typeddict(obj): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1081 return self._typed_dict_schema(obj, None) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1082 elif _typing_extra.is_namedtuple(obj): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1083 return self._namedtuple_schema(obj, None) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1084 elif typing_objects.is_newtype(obj): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1085 # NewType, can't use isinstance because it fails <3.10
1086 return self.generate_schema(obj.__supertype__) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1087 elif obj in PATTERN_TYPES: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1088 return self._pattern_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1089 elif _typing_extra.is_hashable(obj): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1090 return self._hashable_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1091 elif isinstance(obj, typing.TypeVar): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1092 return self._unsubstituted_typevar_schema(obj) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1093 elif _typing_extra.is_finalvar(obj): 1093 ↛ 1094line 1093 didn't jump to line 1094 because the condition on line 1093 was never true1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1094 if obj is Final:
1095 return core_schema.any_schema()
1096 return self.generate_schema(
1097 self._get_first_arg_or_any(obj),
1098 )
1099 elif isinstance(obj, VALIDATE_CALL_SUPPORTED_TYPES): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1100 return self._call_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1101 elif inspect.isclass(obj) and issubclass(obj, Enum): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1102 return self._enum_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1103 elif obj is ZoneInfo: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1104 return self._zoneinfo_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1106 # dataclasses.is_dataclass coerces dc instances to types, but we only handle
1107 # the case of a dc type here
1108 if dataclasses.is_dataclass(obj): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1109 return self._dataclass_schema(obj, None) # pyright: ignore[reportArgumentType] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1111 origin = get_origin(obj) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1112 if origin is not None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1113 return self._match_generic_type(obj, origin) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1115 if self._arbitrary_types: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1116 return self._arbitrary_type_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1117 return self._unknown_type_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1119 def _match_generic_type(self, obj: Any, origin: Any) -> CoreSchema: # noqa: C901 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1120 # Need to handle generic dataclasses before looking for the schema properties because attribute accesses
1121 # on _GenericAlias delegate to the origin type, so lose the information about the concrete parametrization
1122 # As a result, currently, there is no way to cache the schema for generic dataclasses. This may be possible
1123 # to resolve by modifying the value returned by `Generic.__class_getitem__`, but that is a dangerous game.
1124 if dataclasses.is_dataclass(origin): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1125 return self._dataclass_schema(obj, origin) # pyright: ignore[reportArgumentType] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1126 if _typing_extra.is_namedtuple(origin): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1127 return self._namedtuple_schema(obj, origin) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1129 schema = self._generate_schema_from_get_schema_method(origin, obj) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1130 if schema is not None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1131 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1133 if typing_objects.is_typealiastype(origin): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1134 return self._type_alias_type_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1135 elif is_union_origin(origin): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1136 return self._union_schema(obj) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1137 elif origin in TUPLE_TYPES: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1138 return self._tuple_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1139 elif origin in LIST_TYPES: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1140 return self._list_schema(self._get_first_arg_or_any(obj)) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1141 elif origin in SET_TYPES: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1142 return self._set_schema(self._get_first_arg_or_any(obj)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1143 elif origin in FROZEN_SET_TYPES: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1144 return self._frozenset_schema(self._get_first_arg_or_any(obj)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1145 elif origin in DICT_TYPES: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1146 return self._dict_schema(*self._get_first_two_args_or_any(obj)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1147 elif origin in PATH_TYPES: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1148 return self._path_schema(origin, self._get_first_arg_or_any(obj)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1149 elif origin in DEQUE_TYPES: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1150 return self._deque_schema(self._get_first_arg_or_any(obj)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1151 elif origin in MAPPING_TYPES: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1152 return self._mapping_schema(origin, *self._get_first_two_args_or_any(obj)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1153 elif origin in COUNTER_TYPES: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1154 return self._mapping_schema(origin, self._get_first_arg_or_any(obj), int) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1155 elif is_typeddict(origin): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1156 return self._typed_dict_schema(obj, origin) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1157 elif origin in TYPE_TYPES: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1158 return self._subclass_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1159 elif origin in SEQUENCE_TYPES: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1160 return self._sequence_schema(self._get_first_arg_or_any(obj)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1161 elif origin in ITERABLE_TYPES: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1162 return self._iterable_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1163 elif origin in PATTERN_TYPES: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1164 return self._pattern_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1166 if self._arbitrary_types: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1167 return self._arbitrary_type_schema(origin) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1168 return self._unknown_type_schema(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1170 def _generate_td_field_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1171 self,
1172 name: str,
1173 field_info: FieldInfo,
1174 decorators: DecoratorInfos,
1175 *,
1176 required: bool = True,
1177 ) -> core_schema.TypedDictField:
1178 """Prepare a TypedDictField to represent a model or typeddict field."""
1179 common_field = self._common_field_schema(name, field_info, decorators) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1180 return core_schema.typed_dict_field( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1181 common_field['schema'],
1182 required=False if not field_info.is_required() else required,
1183 serialization_exclude=common_field['serialization_exclude'],
1184 validation_alias=common_field['validation_alias'],
1185 serialization_alias=common_field['serialization_alias'],
1186 metadata=common_field['metadata'],
1187 )
1189 def _generate_md_field_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1190 self,
1191 name: str,
1192 field_info: FieldInfo,
1193 decorators: DecoratorInfos,
1194 ) -> core_schema.ModelField:
1195 """Prepare a ModelField to represent a model field."""
1196 common_field = self._common_field_schema(name, field_info, decorators) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1197 return core_schema.model_field( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1198 common_field['schema'],
1199 serialization_exclude=common_field['serialization_exclude'],
1200 validation_alias=common_field['validation_alias'],
1201 serialization_alias=common_field['serialization_alias'],
1202 frozen=common_field['frozen'],
1203 metadata=common_field['metadata'],
1204 )
1206 def _generate_dc_field_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1207 self,
1208 name: str,
1209 field_info: FieldInfo,
1210 decorators: DecoratorInfos,
1211 ) -> core_schema.DataclassField:
1212 """Prepare a DataclassField to represent the parameter/field, of a dataclass."""
1213 common_field = self._common_field_schema(name, field_info, decorators) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1214 return core_schema.dataclass_field( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1215 name,
1216 common_field['schema'],
1217 init=field_info.init,
1218 init_only=field_info.init_var or None,
1219 kw_only=None if field_info.kw_only else False,
1220 serialization_exclude=common_field['serialization_exclude'],
1221 validation_alias=common_field['validation_alias'],
1222 serialization_alias=common_field['serialization_alias'],
1223 frozen=common_field['frozen'],
1224 metadata=common_field['metadata'],
1225 )
1227 def _common_field_schema( # C901 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1228 self, name: str, field_info: FieldInfo, decorators: DecoratorInfos
1229 ) -> _CommonField:
1230 source_type, annotations = field_info.annotation, field_info.metadata 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1232 def set_discriminator(schema: CoreSchema) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1233 schema = self._apply_discriminator_to_union(schema, field_info.discriminator) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1234 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1236 # Convert `@field_validator` decorators to `Before/After/Plain/WrapValidator` instances:
1237 validators_from_decorators = [] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1238 for decorator in filter_field_decorator_info_by_field(decorators.field_validators.values(), name): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1239 validators_from_decorators.append(_mode_to_validator[decorator.info.mode]._from_decorator(decorator)) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1241 with self.field_name_stack.push(name): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1242 if field_info.discriminator is not None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1243 schema = self._apply_annotations( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1244 source_type, annotations + validators_from_decorators, transform_inner_schema=set_discriminator
1245 )
1246 else:
1247 schema = self._apply_annotations( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1248 source_type,
1249 annotations + validators_from_decorators,
1250 )
1252 # This V1 compatibility shim should eventually be removed
1253 # push down any `each_item=True` validators
1254 # note that this won't work for any Annotated types that get wrapped by a function validator
1255 # but that's okay because that didn't exist in V1
1256 this_field_validators = filter_field_decorator_info_by_field(decorators.validators.values(), name) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1257 if _validators_require_validate_default(this_field_validators): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1258 field_info.validate_default = True 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1259 each_item_validators = [v for v in this_field_validators if v.info.each_item is True] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1260 this_field_validators = [v for v in this_field_validators if v not in each_item_validators] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1261 schema = apply_each_item_validators(schema, each_item_validators) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1263 schema = apply_validators(schema, this_field_validators) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1265 # the default validator needs to go outside of any other validators
1266 # so that it is the topmost validator for the field validator
1267 # which uses it to check if the field has a default value or not
1268 if not field_info.is_required(): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1269 schema = wrap_default(field_info, schema) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1271 schema = self._apply_field_serializers( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1272 schema, filter_field_decorator_info_by_field(decorators.field_serializers.values(), name)
1273 )
1275 pydantic_js_updates, pydantic_js_extra = _extract_json_schema_info_from_field_info(field_info) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1276 core_metadata: dict[str, Any] = {} 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1277 update_core_metadata( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1278 core_metadata, pydantic_js_updates=pydantic_js_updates, pydantic_js_extra=pydantic_js_extra
1279 )
1281 if isinstance(field_info.validation_alias, (AliasChoices, AliasPath)): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1282 validation_alias = field_info.validation_alias.convert_to_aliases() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1283 else:
1284 validation_alias = field_info.validation_alias 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1286 return _common_field( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1287 schema,
1288 serialization_exclude=True if field_info.exclude else None,
1289 validation_alias=validation_alias,
1290 serialization_alias=field_info.serialization_alias,
1291 frozen=field_info.frozen,
1292 metadata=core_metadata,
1293 )
1295 def _union_schema(self, union_type: Any) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1296 """Generate schema for a Union."""
1297 args = self._get_args_resolving_forward_refs(union_type, required=True) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1298 choices: list[CoreSchema] = [] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1299 nullable = False 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1300 for arg in args: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1301 if arg is None or arg is _typing_extra.NoneType: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1302 nullable = True 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1303 else:
1304 choices.append(self.generate_schema(arg)) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1306 if len(choices) == 1: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1307 s = choices[0] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1308 else:
1309 choices_with_tags: list[CoreSchema | tuple[CoreSchema, str]] = [] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1310 for choice in choices: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1311 tag = cast(CoreMetadata, choice.get('metadata', {})).get('pydantic_internal_union_tag_key') 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1312 if tag is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1313 choices_with_tags.append((choice, tag)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1314 else:
1315 choices_with_tags.append(choice) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1316 s = core_schema.union_schema(choices_with_tags) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1318 if nullable: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1319 s = core_schema.nullable_schema(s) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1320 return s 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1322 def _type_alias_type_schema(self, obj: TypeAliasType) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1323 with self.defs.get_schema_or_ref(obj) as (ref, maybe_schema): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1324 if maybe_schema is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1325 return maybe_schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1327 origin: TypeAliasType = get_origin(obj) or obj 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1328 typevars_map = get_standard_typevars_map(obj) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1330 with self._ns_resolver.push(origin): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1331 try: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1332 annotation = _typing_extra.eval_type(origin.__value__, *self._types_namespace) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1333 except NameError as e:
1334 raise PydanticUndefinedAnnotation.from_name_error(e) from e
1335 annotation = replace_types(annotation, typevars_map) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1336 schema = self.generate_schema(annotation) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1337 assert schema['type'] != 'definitions' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1338 schema['ref'] = ref # type: ignore 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1339 return self.defs.create_definition_reference_schema(schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1341 def _literal_schema(self, literal_type: Any) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1342 """Generate schema for a Literal."""
1343 expected = list(get_literal_values(literal_type, type_check=False, unpack_type_aliases='eager')) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1344 assert expected, f'literal "expected" cannot be empty, obj={literal_type}' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1345 schema = core_schema.literal_schema(expected) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1347 if self._config_wrapper.use_enum_values and any(isinstance(v, Enum) for v in expected): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1348 schema = core_schema.no_info_after_validator_function( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1349 lambda v: v.value if isinstance(v, Enum) else v, schema
1350 )
1352 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1354 def _typed_dict_schema(self, typed_dict_cls: Any, origin: Any) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1355 """Generate a core schema for a `TypedDict` class.
1357 To be able to build a `DecoratorInfos` instance for the `TypedDict` class (which will include
1358 validators, serializers, etc.), we need to have access to the original bases of the class
1359 (see https://docs.python.org/3/library/types.html#types.get_original_bases).
1360 However, the `__orig_bases__` attribute was only added in 3.12 (https://github.com/python/cpython/pull/103698).
1362 For this reason, we require Python 3.12 (or using the `typing_extensions` backport).
1363 """
1364 FieldInfo = import_cached_field_info() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1366 with ( 1abcfnqoghijkrsdlempt
1367 self.model_type_stack.push(typed_dict_cls),
1368 self.defs.get_schema_or_ref(typed_dict_cls) as (
1369 typed_dict_ref,
1370 maybe_schema,
1371 ),
1372 ):
1373 if maybe_schema is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1374 return maybe_schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1376 typevars_map = get_standard_typevars_map(typed_dict_cls) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1377 if origin is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1378 typed_dict_cls = origin 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1380 if not _SUPPORTS_TYPEDDICT and type(typed_dict_cls).__module__ == 'typing': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1381 raise PydanticUserError( 1abcfnqoghijkrsdlempt
1382 'Please use `typing_extensions.TypedDict` instead of `typing.TypedDict` on Python < 3.12.',
1383 code='typed-dict-version',
1384 )
1386 try: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1387 # if a typed dictionary class doesn't have config, we use the parent's config, hence a default of `None`
1388 # see https://github.com/pydantic/pydantic/issues/10917
1389 config: ConfigDict | None = get_attribute_from_bases(typed_dict_cls, '__pydantic_config__') 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1390 except AttributeError: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1391 config = None 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1393 with self._config_wrapper_stack.push(config): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1394 core_config = self._config_wrapper.core_config(title=typed_dict_cls.__name__) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1396 required_keys: frozenset[str] = typed_dict_cls.__required_keys__ 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1398 fields: dict[str, core_schema.TypedDictField] = {} 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1400 decorators = DecoratorInfos.build(typed_dict_cls) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1401 decorators.update_from_config(self._config_wrapper) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1403 if self._config_wrapper.use_attribute_docstrings: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1404 field_docstrings = extract_docstrings_from_cls(typed_dict_cls, use_inspect=True) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1405 else:
1406 field_docstrings = None 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1408 try: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1409 annotations = _typing_extra.get_cls_type_hints(typed_dict_cls, ns_resolver=self._ns_resolver) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1410 except NameError as e:
1411 raise PydanticUndefinedAnnotation.from_name_error(e) from e
1413 readonly_fields: list[str] = [] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1415 for field_name, annotation in annotations.items(): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1416 field_info = FieldInfo.from_annotation(annotation, _source=AnnotationSource.TYPED_DICT) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1417 field_info.annotation = replace_types(field_info.annotation, typevars_map) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1419 required = ( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1420 field_name in required_keys or 'required' in field_info._qualifiers
1421 ) and 'not_required' not in field_info._qualifiers
1422 if 'read_only' in field_info._qualifiers: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1423 readonly_fields.append(field_name) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1425 if ( 1aboghidl
1426 field_docstrings is not None
1427 and field_info.description is None
1428 and field_name in field_docstrings
1429 ):
1430 field_info.description = field_docstrings[field_name] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1431 update_field_from_config(self._config_wrapper, field_name, field_info) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1433 fields[field_name] = self._generate_td_field_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1434 field_name, field_info, decorators, required=required
1435 )
1437 if readonly_fields: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1438 fields_repr = ', '.join(repr(f) for f in readonly_fields) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1439 plural = len(readonly_fields) >= 2 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1440 warnings.warn( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1441 f'Item{"s" if plural else ""} {fields_repr} on TypedDict class {typed_dict_cls.__name__!r} '
1442 f'{"are" if plural else "is"} using the `ReadOnly` qualifier. Pydantic will not protect items '
1443 'from any mutation on dictionary instances.',
1444 UserWarning,
1445 )
1447 td_schema = core_schema.typed_dict_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1448 fields,
1449 cls=typed_dict_cls,
1450 computed_fields=[
1451 self._computed_field_schema(d, decorators.field_serializers)
1452 for d in decorators.computed_fields.values()
1453 ],
1454 ref=typed_dict_ref,
1455 config=core_config,
1456 )
1458 schema = self._apply_model_serializers(td_schema, decorators.model_serializers.values()) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1459 schema = apply_model_validators(schema, decorators.model_validators.values(), 'all') 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1460 return self.defs.create_definition_reference_schema(schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1462 def _namedtuple_schema(self, namedtuple_cls: Any, origin: Any) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1463 """Generate schema for a NamedTuple."""
1464 with ( 1abcfnqoghijkrsdlempt
1465 self.model_type_stack.push(namedtuple_cls),
1466 self.defs.get_schema_or_ref(namedtuple_cls) as (
1467 namedtuple_ref,
1468 maybe_schema,
1469 ),
1470 ):
1471 if maybe_schema is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1472 return maybe_schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1473 typevars_map = get_standard_typevars_map(namedtuple_cls) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1474 if origin is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1475 namedtuple_cls = origin 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1477 try: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1478 annotations = _typing_extra.get_cls_type_hints(namedtuple_cls, ns_resolver=self._ns_resolver) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1479 except NameError as e:
1480 raise PydanticUndefinedAnnotation.from_name_error(e) from e
1481 if not annotations: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1482 # annotations is empty, happens if namedtuple_cls defined via collections.namedtuple(...)
1483 annotations: dict[str, Any] = {k: Any for k in namedtuple_cls._fields} 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1485 if typevars_map: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1486 annotations = { 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1487 field_name: replace_types(annotation, typevars_map)
1488 for field_name, annotation in annotations.items()
1489 }
1491 arguments_schema = core_schema.arguments_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1492 [
1493 self._generate_parameter_schema(
1494 field_name,
1495 annotation,
1496 source=AnnotationSource.NAMED_TUPLE,
1497 default=namedtuple_cls._field_defaults.get(field_name, Parameter.empty),
1498 )
1499 for field_name, annotation in annotations.items()
1500 ],
1501 metadata={'pydantic_js_prefer_positional_arguments': True},
1502 )
1503 schema = core_schema.call_schema(arguments_schema, namedtuple_cls, ref=namedtuple_ref) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1504 return self.defs.create_definition_reference_schema(schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1506 def _generate_parameter_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1507 self,
1508 name: str,
1509 annotation: type[Any],
1510 source: AnnotationSource,
1511 default: Any = Parameter.empty,
1512 mode: Literal['positional_only', 'positional_or_keyword', 'keyword_only'] | None = None,
1513 ) -> core_schema.ArgumentsParameter:
1514 """Generate the definition of a field in a namedtuple or a parameter in a function signature.
1516 This definition is meant to be used for the `'arguments'` core schema, which will be replaced
1517 in V3 by the `'arguments-v3`'.
1518 """
1519 FieldInfo = import_cached_field_info() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1521 if default is Parameter.empty: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1522 field = FieldInfo.from_annotation(annotation, _source=source) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1523 else:
1524 field = FieldInfo.from_annotated_attribute(annotation, default, _source=source) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1526 assert field.annotation is not None, 'field.annotation should not be None when generating a schema' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1527 update_field_from_config(self._config_wrapper, name, field) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1529 with self.field_name_stack.push(name): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1530 schema = self._apply_annotations(field.annotation, [field]) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1532 if not field.is_required(): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1533 schema = wrap_default(field, schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1535 parameter_schema = core_schema.arguments_parameter(name, schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1536 if mode is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1537 parameter_schema['mode'] = mode 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1538 if field.alias is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1539 parameter_schema['alias'] = field.alias 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1541 return parameter_schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1543 def _generate_parameter_v3_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1544 self,
1545 name: str,
1546 annotation: Any,
1547 source: AnnotationSource,
1548 mode: Literal[
1549 'positional_only',
1550 'positional_or_keyword',
1551 'keyword_only',
1552 'var_args',
1553 'var_kwargs_uniform',
1554 'var_kwargs_unpacked_typed_dict',
1555 ],
1556 default: Any = Parameter.empty,
1557 ) -> core_schema.ArgumentsV3Parameter:
1558 """Generate the definition of a parameter in a function signature.
1560 This definition is meant to be used for the `'arguments-v3'` core schema, which will replace
1561 the `'arguments`' schema in V3.
1562 """
1563 FieldInfo = import_cached_field_info() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1565 if default is Parameter.empty: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1566 field = FieldInfo.from_annotation(annotation, _source=source) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1567 else:
1568 field = FieldInfo.from_annotated_attribute(annotation, default, _source=source) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1569 update_field_from_config(self._config_wrapper, name, field) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1571 with self.field_name_stack.push(name): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1572 schema = self._apply_annotations(field.annotation, [field]) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1574 if not field.is_required(): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1575 schema = wrap_default(field, schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1577 parameter_schema = core_schema.arguments_v3_parameter( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1578 name=name,
1579 schema=schema,
1580 mode=mode,
1581 )
1582 if field.alias is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1583 parameter_schema['alias'] = field.alias 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1585 return parameter_schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1587 def _tuple_schema(self, tuple_type: Any) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1588 """Generate schema for a Tuple, e.g. `tuple[int, str]` or `tuple[int, ...]`."""
1589 # TODO: do we really need to resolve type vars here?
1590 typevars_map = get_standard_typevars_map(tuple_type) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1591 params = self._get_args_resolving_forward_refs(tuple_type) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1593 if typevars_map and params: 1593 ↛ 1594line 1593 didn't jump to line 1594 because the condition on line 1593 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1594 params = tuple(replace_types(param, typevars_map) for param in params)
1596 # NOTE: subtle difference: `tuple[()]` gives `params=()`, whereas `typing.Tuple[()]` gives `params=((),)`
1597 # This is only true for <3.11, on Python 3.11+ `typing.Tuple[()]` gives `params=()`
1598 if not params: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1599 if tuple_type in TUPLE_TYPES: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1600 return core_schema.tuple_schema([core_schema.any_schema()], variadic_item_index=0) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1601 else:
1602 # special case for `tuple[()]` which means `tuple[]` - an empty tuple
1603 return core_schema.tuple_schema([]) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1604 elif params[-1] is Ellipsis: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1605 if len(params) == 2: 1605 ↛ 1609line 1605 didn't jump to line 1609 because the condition on line 1605 was always true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1606 return core_schema.tuple_schema([self.generate_schema(params[0])], variadic_item_index=0) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1607 else:
1608 # TODO: something like https://github.com/pydantic/pydantic/issues/5952
1609 raise ValueError('Variable tuples can only have one type')
1610 elif len(params) == 1 and params[0] == (): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1611 # special case for `tuple[()]` which means `tuple[]` - an empty tuple
1612 # NOTE: This conditional can be removed when we drop support for Python 3.10.
1613 return core_schema.tuple_schema([]) 1abcfoghijkdlem
1614 else:
1615 return core_schema.tuple_schema([self.generate_schema(param) for param in params]) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1617 def _type_schema(self) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1618 return core_schema.custom_error_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1619 core_schema.is_instance_schema(type),
1620 custom_error_type='is_type',
1621 custom_error_message='Input should be a type',
1622 )
1624 def _zoneinfo_schema(self) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1625 """Generate schema for a zone_info.ZoneInfo object"""
1626 from ._validators import validate_str_is_valid_iana_tz 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1628 metadata = {'pydantic_js_functions': [lambda _1, _2: {'type': 'string', 'format': 'zoneinfo'}]} 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1629 return core_schema.no_info_plain_validator_function( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1630 validate_str_is_valid_iana_tz,
1631 serialization=core_schema.to_string_ser_schema(),
1632 metadata=metadata,
1633 )
1635 def _union_is_subclass_schema(self, union_type: Any) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1636 """Generate schema for `type[Union[X, ...]]`."""
1637 args = self._get_args_resolving_forward_refs(union_type, required=True) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1638 return core_schema.union_schema([self.generate_schema(type[args]) for args in args]) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1640 def _subclass_schema(self, type_: Any) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1641 """Generate schema for a type, e.g. `type[int]`."""
1642 type_param = self._get_first_arg_or_any(type_) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1644 # Assume `type[Annotated[<typ>, ...]]` is equivalent to `type[<typ>]`:
1645 type_param = _typing_extra.annotated_type(type_param) or type_param 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1647 if typing_objects.is_any(type_param): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1648 return self._type_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1649 elif typing_objects.is_typealiastype(type_param): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1650 return self.generate_schema(type[type_param.__value__]) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1651 elif typing_objects.is_typevar(type_param): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1652 if type_param.__bound__: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1653 if is_union_origin(get_origin(type_param.__bound__)): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1654 return self._union_is_subclass_schema(type_param.__bound__) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1655 return core_schema.is_subclass_schema(type_param.__bound__) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1656 elif type_param.__constraints__: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1657 return core_schema.union_schema([self.generate_schema(type[c]) for c in type_param.__constraints__]) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1658 else:
1659 return self._type_schema() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1660 elif is_union_origin(get_origin(type_param)): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1661 return self._union_is_subclass_schema(type_param) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1662 else:
1663 if typing_objects.is_self(type_param): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1664 type_param = self._resolve_self_type(type_param) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1665 if _typing_extra.is_generic_alias(type_param): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1666 raise PydanticUserError( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1667 'Subscripting `type[]` with an already parametrized type is not supported. '
1668 f'Instead of using type[{type_param!r}], use type[{_repr.display_as_type(get_origin(type_param))}].',
1669 code=None,
1670 )
1671 if not inspect.isclass(type_param): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1672 # when using type[None], this doesn't type convert to type[NoneType], and None isn't a class
1673 # so we handle it manually here
1674 if type_param is None: 1674 ↛ 1676line 1674 didn't jump to line 1676 because the condition on line 1674 was always true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1675 return core_schema.is_subclass_schema(_typing_extra.NoneType) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1676 raise TypeError(f'Expected a class, got {type_param!r}')
1677 return core_schema.is_subclass_schema(type_param) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1679 def _sequence_schema(self, items_type: Any) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1680 """Generate schema for a Sequence, e.g. `Sequence[int]`."""
1681 from ._serializers import serialize_sequence_via_list 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1683 item_type_schema = self.generate_schema(items_type) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1684 list_schema = core_schema.list_schema(item_type_schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1686 json_schema = smart_deepcopy(list_schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1687 python_schema = core_schema.is_instance_schema(typing.Sequence, cls_repr='Sequence') 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1688 if not typing_objects.is_any(items_type): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1689 from ._validators import sequence_validator 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1691 python_schema = core_schema.chain_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1692 [python_schema, core_schema.no_info_wrap_validator_function(sequence_validator, list_schema)],
1693 )
1695 serialization = core_schema.wrap_serializer_function_ser_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1696 serialize_sequence_via_list, schema=item_type_schema, info_arg=True
1697 )
1698 return core_schema.json_or_python_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1699 json_schema=json_schema, python_schema=python_schema, serialization=serialization
1700 )
1702 def _iterable_schema(self, type_: Any) -> core_schema.GeneratorSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1703 """Generate a schema for an `Iterable`."""
1704 item_type = self._get_first_arg_or_any(type_) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1706 return core_schema.generator_schema(self.generate_schema(item_type)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1708 def _pattern_schema(self, pattern_type: Any) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1709 from . import _validators 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1711 metadata = {'pydantic_js_functions': [lambda _1, _2: {'type': 'string', 'format': 'regex'}]} 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1712 ser = core_schema.plain_serializer_function_ser_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1713 attrgetter('pattern'), when_used='json', return_schema=core_schema.str_schema()
1714 )
1715 if pattern_type is typing.Pattern or pattern_type is re.Pattern: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1716 # bare type
1717 return core_schema.no_info_plain_validator_function( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1718 _validators.pattern_either_validator, serialization=ser, metadata=metadata
1719 )
1721 param = self._get_args_resolving_forward_refs( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1722 pattern_type,
1723 required=True,
1724 )[0]
1725 if param is str: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1726 return core_schema.no_info_plain_validator_function( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1727 _validators.pattern_str_validator, serialization=ser, metadata=metadata
1728 )
1729 elif param is bytes: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1730 return core_schema.no_info_plain_validator_function( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1731 _validators.pattern_bytes_validator, serialization=ser, metadata=metadata
1732 )
1733 else:
1734 raise PydanticSchemaGenerationError(f'Unable to generate pydantic-core schema for {pattern_type!r}.') 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1736 def _hashable_schema(self) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1737 return core_schema.custom_error_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1738 schema=core_schema.json_or_python_schema(
1739 json_schema=core_schema.chain_schema(
1740 [core_schema.any_schema(), core_schema.is_instance_schema(collections.abc.Hashable)]
1741 ),
1742 python_schema=core_schema.is_instance_schema(collections.abc.Hashable),
1743 ),
1744 custom_error_type='is_hashable',
1745 custom_error_message='Input should be hashable',
1746 )
1748 def _dataclass_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1749 self, dataclass: type[StandardDataclass], origin: type[StandardDataclass] | None
1750 ) -> core_schema.CoreSchema:
1751 """Generate schema for a dataclass."""
1752 with ( 1abcfnqoghijkrsdlempt
1753 self.model_type_stack.push(dataclass),
1754 self.defs.get_schema_or_ref(dataclass) as (
1755 dataclass_ref,
1756 maybe_schema,
1757 ),
1758 ):
1759 if maybe_schema is not None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1760 return maybe_schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1762 schema = dataclass.__dict__.get('__pydantic_core_schema__') 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1763 if schema is not None and not isinstance(schema, MockCoreSchema): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1764 if schema['type'] == 'definitions': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1765 schema = self.defs.unpack_definitions(schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1766 ref = get_ref(schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1767 if ref: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1768 return self.defs.create_definition_reference_schema(schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1769 else:
1770 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1772 typevars_map = get_standard_typevars_map(dataclass) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1773 if origin is not None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1774 dataclass = origin 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1776 # if (plain) dataclass doesn't have config, we use the parent's config, hence a default of `None`
1777 # (Pydantic dataclasses have an empty dict config by default).
1778 # see https://github.com/pydantic/pydantic/issues/10917
1779 config = getattr(dataclass, '__pydantic_config__', None) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1781 from ..dataclasses import is_pydantic_dataclass 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1783 with self._ns_resolver.push(dataclass), self._config_wrapper_stack.push(config): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1784 if is_pydantic_dataclass(dataclass): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1785 # Copy the field info instances to avoid mutating the `FieldInfo` instances
1786 # of the generic dataclass generic origin (e.g. `apply_typevars_map` below).
1787 # Note that we don't apply `deepcopy` on `__pydantic_fields__` because we
1788 # don't want to copy the `FieldInfo` attributes:
1789 fields = {f_name: copy(field_info) for f_name, field_info in dataclass.__pydantic_fields__.items()} 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1790 if typevars_map: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1791 for field in fields.values(): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1792 field.apply_typevars_map(typevars_map, *self._types_namespace) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1793 else:
1794 fields = collect_dataclass_fields( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1795 dataclass,
1796 typevars_map=typevars_map,
1797 config_wrapper=self._config_wrapper,
1798 )
1800 if self._config_wrapper.extra == 'allow': 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1801 # disallow combination of init=False on a dataclass field and extra='allow' on a dataclass
1802 for field_name, field in fields.items(): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1803 if field.init is False: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1804 raise PydanticUserError( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1805 f'Field {field_name} has `init=False` and dataclass has config setting `extra="allow"`. '
1806 f'This combination is not allowed.',
1807 code='dataclass-init-false-extra-allow',
1808 )
1810 decorators = dataclass.__dict__.get('__pydantic_decorators__') 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1811 if decorators is None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1812 decorators = DecoratorInfos.build(dataclass) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1813 decorators.update_from_config(self._config_wrapper) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1814 # Move kw_only=False args to the start of the list, as this is how vanilla dataclasses work.
1815 # Note that when kw_only is missing or None, it is treated as equivalent to kw_only=True
1816 args = sorted( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1817 (self._generate_dc_field_schema(k, v, decorators) for k, v in fields.items()),
1818 key=lambda a: a.get('kw_only') is not False,
1819 )
1820 has_post_init = hasattr(dataclass, '__post_init__') 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1821 has_slots = hasattr(dataclass, '__slots__') 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1823 args_schema = core_schema.dataclass_args_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1824 dataclass.__name__,
1825 args,
1826 computed_fields=[
1827 self._computed_field_schema(d, decorators.field_serializers)
1828 for d in decorators.computed_fields.values()
1829 ],
1830 collect_init_only=has_post_init,
1831 )
1833 inner_schema = apply_validators(args_schema, decorators.root_validators.values()) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1835 model_validators = decorators.model_validators.values() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1836 inner_schema = apply_model_validators(inner_schema, model_validators, 'inner') 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1838 core_config = self._config_wrapper.core_config(title=dataclass.__name__) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1840 dc_schema = core_schema.dataclass_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1841 dataclass,
1842 inner_schema,
1843 generic_origin=origin,
1844 post_init=has_post_init,
1845 ref=dataclass_ref,
1846 fields=[field.name for field in dataclasses.fields(dataclass)],
1847 slots=has_slots,
1848 config=core_config,
1849 # we don't use a custom __setattr__ for dataclasses, so we must
1850 # pass along the frozen config setting to the pydantic-core schema
1851 frozen=self._config_wrapper_stack.tail.frozen,
1852 )
1853 schema = self._apply_model_serializers(dc_schema, decorators.model_serializers.values()) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1854 schema = apply_model_validators(schema, model_validators, 'outer') 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1855 return self.defs.create_definition_reference_schema(schema) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1857 def _call_schema(self, function: ValidateCallSupportedTypes) -> core_schema.CallSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
1858 """Generate schema for a Callable.
1860 TODO support functional validators once we support them in Config
1861 """
1862 arguments_schema = self._arguments_schema(function) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1864 return_schema: core_schema.CoreSchema | None = None 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1865 config_wrapper = self._config_wrapper 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1866 if config_wrapper.validate_return: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1867 sig = signature(function) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1868 return_hint = sig.return_annotation 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1869 if return_hint is not sig.empty: 1869 ↛ 1876line 1869 didn't jump to line 1876 because the condition on line 1869 was always true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1870 globalns, localns = self._types_namespace 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1871 type_hints = _typing_extra.get_function_type_hints( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1872 function, globalns=globalns, localns=localns, include_keys={'return'}
1873 )
1874 return_schema = self.generate_schema(type_hints['return']) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1876 return core_schema.call_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1877 arguments_schema,
1878 function,
1879 return_schema=return_schema,
1880 )
1882 def _arguments_schema( 1abcfnquwACDhijkrsxyEFGJdlemptvzBHI
1883 self, function: ValidateCallSupportedTypes, parameters_callback: ParametersCallback | None = None
1884 ) -> core_schema.ArgumentsSchema:
1885 """Generate schema for a Signature."""
1886 mode_lookup: dict[_ParameterKind, Literal['positional_only', 'positional_or_keyword', 'keyword_only']] = { 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1887 Parameter.POSITIONAL_ONLY: 'positional_only',
1888 Parameter.POSITIONAL_OR_KEYWORD: 'positional_or_keyword',
1889 Parameter.KEYWORD_ONLY: 'keyword_only',
1890 }
1892 sig = signature(function) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1893 globalns, localns = self._types_namespace 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1894 type_hints = _typing_extra.get_function_type_hints(function, globalns=globalns, localns=localns) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1896 arguments_list: list[core_schema.ArgumentsParameter] = [] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1897 var_args_schema: core_schema.CoreSchema | None = None 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1898 var_kwargs_schema: core_schema.CoreSchema | None = None 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1899 var_kwargs_mode: core_schema.VarKwargsMode | None = None 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1901 for i, (name, p) in enumerate(sig.parameters.items()): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1902 if p.annotation is sig.empty: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1903 annotation = typing.cast(Any, Any) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1904 else:
1905 annotation = type_hints[name] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1907 if parameters_callback is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1908 result = parameters_callback(i, name, annotation) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1909 if result == 'skip': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1910 continue 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1912 parameter_mode = mode_lookup.get(p.kind) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1913 if parameter_mode is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1914 arg_schema = self._generate_parameter_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1915 name, annotation, AnnotationSource.FUNCTION, p.default, parameter_mode
1916 )
1917 arguments_list.append(arg_schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1918 elif p.kind == Parameter.VAR_POSITIONAL: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1919 var_args_schema = self.generate_schema(annotation) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1920 else:
1921 assert p.kind == Parameter.VAR_KEYWORD, p.kind 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1923 unpack_type = _typing_extra.unpack_type(annotation) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1924 if unpack_type is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1925 origin = get_origin(unpack_type) or unpack_type 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1926 if not is_typeddict(origin): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1927 raise PydanticUserError( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1928 f'Expected a `TypedDict` class inside `Unpack[...]`, got {unpack_type!r}',
1929 code='unpack-typed-dict',
1930 )
1931 non_pos_only_param_names = { 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1932 name for name, p in sig.parameters.items() if p.kind != Parameter.POSITIONAL_ONLY
1933 }
1934 overlapping_params = non_pos_only_param_names.intersection(origin.__annotations__) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1935 if overlapping_params: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1936 raise PydanticUserError( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1937 f'Typed dictionary {origin.__name__!r} overlaps with parameter'
1938 f'{"s" if len(overlapping_params) >= 2 else ""} '
1939 f'{", ".join(repr(p) for p in sorted(overlapping_params))}',
1940 code='overlapping-unpack-typed-dict',
1941 )
1943 var_kwargs_mode = 'unpacked-typed-dict' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1944 var_kwargs_schema = self._typed_dict_schema(unpack_type, get_origin(unpack_type)) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1945 else:
1946 var_kwargs_mode = 'uniform' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1947 var_kwargs_schema = self.generate_schema(annotation) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1949 return core_schema.arguments_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1950 arguments_list,
1951 var_args_schema=var_args_schema,
1952 var_kwargs_mode=var_kwargs_mode,
1953 var_kwargs_schema=var_kwargs_schema,
1954 validate_by_name=self._config_wrapper.validate_by_name,
1955 )
1957 def _arguments_v3_schema( 1abcfnquwACDhijkrsxyEFGJdlemptvzBHI
1958 self, function: ValidateCallSupportedTypes, parameters_callback: ParametersCallback | None = None
1959 ) -> core_schema.ArgumentsV3Schema:
1960 mode_lookup: dict[ 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1961 _ParameterKind, Literal['positional_only', 'positional_or_keyword', 'var_args', 'keyword_only']
1962 ] = {
1963 Parameter.POSITIONAL_ONLY: 'positional_only',
1964 Parameter.POSITIONAL_OR_KEYWORD: 'positional_or_keyword',
1965 Parameter.VAR_POSITIONAL: 'var_args',
1966 Parameter.KEYWORD_ONLY: 'keyword_only',
1967 }
1969 sig = signature(function) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1970 globalns, localns = self._types_namespace 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1971 type_hints = _typing_extra.get_function_type_hints(function, globalns=globalns, localns=localns) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1973 parameters_list: list[core_schema.ArgumentsV3Parameter] = [] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1975 for i, (name, p) in enumerate(sig.parameters.items()): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1976 if parameters_callback is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1977 result = parameters_callback(i, name, p.annotation) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1978 if result == 'skip': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1979 continue 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1981 if p.annotation is Parameter.empty: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1982 annotation = typing.cast(Any, Any) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1983 else:
1984 annotation = type_hints[name] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1986 parameter_mode = mode_lookup.get(p.kind) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1987 if parameter_mode is None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1988 assert p.kind == Parameter.VAR_KEYWORD, p.kind 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1990 unpack_type = _typing_extra.unpack_type(annotation) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1991 if unpack_type is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1992 origin = get_origin(unpack_type) or unpack_type 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1993 if not is_typeddict(origin): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1994 raise PydanticUserError( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1995 f'Expected a `TypedDict` class inside `Unpack[...]`, got {unpack_type!r}',
1996 code='unpack-typed-dict',
1997 )
1998 non_pos_only_param_names = { 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
1999 name for name, p in sig.parameters.items() if p.kind != Parameter.POSITIONAL_ONLY
2000 }
2001 overlapping_params = non_pos_only_param_names.intersection(origin.__annotations__) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2002 if overlapping_params: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2003 raise PydanticUserError( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2004 f'Typed dictionary {origin.__name__!r} overlaps with parameter'
2005 f'{"s" if len(overlapping_params) >= 2 else ""} '
2006 f'{", ".join(repr(p) for p in sorted(overlapping_params))}',
2007 code='overlapping-unpack-typed-dict',
2008 )
2009 parameter_mode = 'var_kwargs_unpacked_typed_dict' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2010 annotation = unpack_type 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2011 else:
2012 parameter_mode = 'var_kwargs_uniform' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2014 parameters_list.append( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2015 self._generate_parameter_v3_schema(
2016 name, annotation, AnnotationSource.FUNCTION, parameter_mode, default=p.default
2017 )
2018 )
2020 return core_schema.arguments_v3_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2021 parameters_list,
2022 validate_by_name=self._config_wrapper.validate_by_name,
2023 )
2025 def _unsubstituted_typevar_schema(self, typevar: typing.TypeVar) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2026 try: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2027 has_default = typevar.has_default() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2028 except AttributeError: 1abcfnquwoghijkrsxydlemptvz
2029 # Happens if using `typing.TypeVar` (and not `typing_extensions`) on Python < 3.13
2030 pass 1abcfnquwoghijkrsxydlemptvz
2031 else:
2032 if has_default: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2033 return self.generate_schema(typevar.__default__) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2035 if constraints := typevar.__constraints__: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2036 return self._union_schema(typing.Union[constraints]) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2038 if bound := typevar.__bound__: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2039 schema = self.generate_schema(bound) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2040 schema['serialization'] = core_schema.wrap_serializer_function_ser_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2041 lambda x, h: h(x),
2042 schema=core_schema.any_schema(),
2043 )
2044 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2046 return core_schema.any_schema() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2048 def _computed_field_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2049 self,
2050 d: Decorator[ComputedFieldInfo],
2051 field_serializers: dict[str, Decorator[FieldSerializerDecoratorInfo]],
2052 ) -> core_schema.ComputedField:
2053 if d.info.return_type is not PydanticUndefined: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2054 return_type = d.info.return_type 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2055 else:
2056 try: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2057 # Do not pass in globals as the function could be defined in a different module.
2058 # Instead, let `get_callable_return_type` infer the globals to use, but still pass
2059 # in locals that may contain a parent/rebuild namespace:
2060 return_type = _decorators.get_callable_return_type(d.func, localns=self._types_namespace.locals) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2061 except NameError as e: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2062 raise PydanticUndefinedAnnotation.from_name_error(e) from e 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2063 if return_type is PydanticUndefined: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2064 raise PydanticUserError( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2065 'Computed field is missing return type annotation or specifying `return_type`'
2066 ' to the `@computed_field` decorator (e.g. `@computed_field(return_type=int | str)`)',
2067 code='model-field-missing-annotation',
2068 )
2070 return_type = replace_types(return_type, self._typevars_map) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2071 # Create a new ComputedFieldInfo so that different type parametrizations of the same
2072 # generic model's computed field can have different return types.
2073 d.info = dataclasses.replace(d.info, return_type=return_type) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2074 return_type_schema = self.generate_schema(return_type) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2075 # Apply serializers to computed field if there exist
2076 return_type_schema = self._apply_field_serializers( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2077 return_type_schema,
2078 filter_field_decorator_info_by_field(field_serializers.values(), d.cls_var_name),
2079 )
2081 pydantic_js_updates, pydantic_js_extra = _extract_json_schema_info_from_field_info(d.info) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2082 core_metadata: dict[str, Any] = {} 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2083 update_core_metadata( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2084 core_metadata,
2085 pydantic_js_updates={'readOnly': True, **(pydantic_js_updates if pydantic_js_updates else {})},
2086 pydantic_js_extra=pydantic_js_extra,
2087 )
2088 return core_schema.computed_field( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2089 d.cls_var_name, return_schema=return_type_schema, alias=d.info.alias, metadata=core_metadata
2090 )
2092 def _annotated_schema(self, annotated_type: Any) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2093 """Generate schema for an Annotated type, e.g. `Annotated[int, Field(...)]` or `Annotated[int, Gt(0)]`."""
2094 FieldInfo = import_cached_field_info() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2095 source_type, *annotations = self._get_args_resolving_forward_refs( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2096 annotated_type,
2097 required=True,
2098 )
2099 schema = self._apply_annotations(source_type, annotations) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2100 # put the default validator last so that TypeAdapter.get_default_value() works
2101 # even if there are function validators involved
2102 for annotation in annotations: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2103 if isinstance(annotation, FieldInfo): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2104 schema = wrap_default(annotation, schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2105 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2107 def _apply_annotations( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2108 self,
2109 source_type: Any,
2110 annotations: list[Any],
2111 transform_inner_schema: Callable[[CoreSchema], CoreSchema] = lambda x: x,
2112 ) -> CoreSchema:
2113 """Apply arguments from `Annotated` or from `FieldInfo` to a schema.
2115 This gets called by `GenerateSchema._annotated_schema` but differs from it in that it does
2116 not expect `source_type` to be an `Annotated` object, it expects it to be the first argument of that
2117 (in other words, `GenerateSchema._annotated_schema` just unpacks `Annotated`, this process it).
2118 """
2119 annotations = list(_known_annotated_metadata.expand_grouped_metadata(annotations)) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2121 pydantic_js_annotation_functions: list[GetJsonSchemaFunction] = [] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2123 def inner_handler(obj: Any) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2124 schema = self._generate_schema_from_get_schema_method(obj, source_type) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2126 if schema is None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2127 schema = self._generate_schema_inner(obj) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2129 metadata_js_function = _extract_get_pydantic_json_schema(obj) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2130 if metadata_js_function is not None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2131 metadata_schema = resolve_original_schema(schema, self.defs) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2132 if metadata_schema is not None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2133 self._add_js_function(metadata_schema, metadata_js_function) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2134 return transform_inner_schema(schema) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2136 get_inner_schema = CallbackGetCoreSchemaHandler(inner_handler, self) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2138 for annotation in annotations: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2139 if annotation is None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2140 continue 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2141 get_inner_schema = self._get_wrapped_inner_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2142 get_inner_schema, annotation, pydantic_js_annotation_functions
2143 )
2145 schema = get_inner_schema(source_type) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2146 if pydantic_js_annotation_functions: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2147 core_metadata = schema.setdefault('metadata', {}) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2148 update_core_metadata(core_metadata, pydantic_js_annotation_functions=pydantic_js_annotation_functions) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2149 return _add_custom_serialization_from_json_encoders(self._config_wrapper.json_encoders, source_type, schema) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2151 def _apply_single_annotation(self, schema: core_schema.CoreSchema, metadata: Any) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2152 FieldInfo = import_cached_field_info() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2154 if isinstance(metadata, FieldInfo): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2155 for field_metadata in metadata.metadata: 2155 ↛ 2156line 2155 didn't jump to line 2156 because the loop on line 2155 never started1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2156 schema = self._apply_single_annotation(schema, field_metadata)
2158 if metadata.discriminator is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2159 schema = self._apply_discriminator_to_union(schema, metadata.discriminator) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2160 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2162 if schema['type'] == 'nullable': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2163 # for nullable schemas, metadata is automatically applied to the inner schema
2164 inner = schema.get('schema', core_schema.any_schema()) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2165 inner = self._apply_single_annotation(inner, metadata) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2166 if inner: 2166 ↛ 2168line 2166 didn't jump to line 2168 because the condition on line 2166 was always true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2167 schema['schema'] = inner 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2168 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2170 original_schema = schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2171 ref = schema.get('ref') 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2172 if ref is not None: 2172 ↛ 2173line 2172 didn't jump to line 2173 because the condition on line 2172 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2173 schema = schema.copy()
2174 new_ref = ref + f'_{repr(metadata)}'
2175 if (existing := self.defs.get_schema_from_ref(new_ref)) is not None:
2176 return existing
2177 schema['ref'] = new_ref # pyright: ignore[reportGeneralTypeIssues]
2178 elif schema['type'] == 'definition-ref': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2179 ref = schema['schema_ref'] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2180 if (referenced_schema := self.defs.get_schema_from_ref(ref)) is not None: 2180 ↛ 2187line 2180 didn't jump to line 2187 because the condition on line 2180 was always true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2181 schema = referenced_schema.copy() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2182 new_ref = ref + f'_{repr(metadata)}' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2183 if (existing := self.defs.get_schema_from_ref(new_ref)) is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2184 return existing 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2185 schema['ref'] = new_ref # pyright: ignore[reportGeneralTypeIssues] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2187 maybe_updated_schema = _known_annotated_metadata.apply_known_metadata(metadata, schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2189 if maybe_updated_schema is not None: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2190 return maybe_updated_schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2191 return original_schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2193 def _apply_single_annotation_json_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2194 self, schema: core_schema.CoreSchema, metadata: Any
2195 ) -> core_schema.CoreSchema:
2196 FieldInfo = import_cached_field_info() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2198 if isinstance(metadata, FieldInfo): 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2199 for field_metadata in metadata.metadata: 2199 ↛ 2200line 2199 didn't jump to line 2200 because the loop on line 2199 never started1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2200 schema = self._apply_single_annotation_json_schema(schema, field_metadata)
2202 pydantic_js_updates, pydantic_js_extra = _extract_json_schema_info_from_field_info(metadata) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2203 core_metadata = schema.setdefault('metadata', {}) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2204 update_core_metadata( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2205 core_metadata, pydantic_js_updates=pydantic_js_updates, pydantic_js_extra=pydantic_js_extra
2206 )
2207 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2209 def _get_wrapped_inner_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2210 self,
2211 get_inner_schema: GetCoreSchemaHandler,
2212 annotation: Any,
2213 pydantic_js_annotation_functions: list[GetJsonSchemaFunction],
2214 ) -> CallbackGetCoreSchemaHandler:
2215 annotation_get_schema: GetCoreSchemaFunction | None = getattr(annotation, '__get_pydantic_core_schema__', None) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2217 def new_handler(source: Any) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2218 if annotation_get_schema is not None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2219 schema = annotation_get_schema(source, get_inner_schema) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2220 else:
2221 schema = get_inner_schema(source) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2222 schema = self._apply_single_annotation(schema, annotation) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2223 schema = self._apply_single_annotation_json_schema(schema, annotation) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2225 metadata_js_function = _extract_get_pydantic_json_schema(annotation) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2226 if metadata_js_function is not None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2227 pydantic_js_annotation_functions.append(metadata_js_function) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2228 return schema 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2230 return CallbackGetCoreSchemaHandler(new_handler, self) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2232 def _apply_field_serializers( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2233 self,
2234 schema: core_schema.CoreSchema,
2235 serializers: list[Decorator[FieldSerializerDecoratorInfo]],
2236 ) -> core_schema.CoreSchema:
2237 """Apply field serializers to a schema."""
2238 if serializers: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2239 schema = copy(schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2240 if schema['type'] == 'definitions': 2240 ↛ 2241line 2240 didn't jump to line 2241 because the condition on line 2240 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2241 inner_schema = schema['schema']
2242 schema['schema'] = self._apply_field_serializers(inner_schema, serializers)
2243 return schema
2244 elif 'ref' in schema: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2245 schema = self.defs.create_definition_reference_schema(schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2247 # use the last serializer to make it easy to override a serializer set on a parent model
2248 serializer = serializers[-1] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2249 is_field_serializer, info_arg = inspect_field_serializer(serializer.func, serializer.info.mode) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2251 if serializer.info.return_type is not PydanticUndefined: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2252 return_type = serializer.info.return_type 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2253 else:
2254 try: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2255 # Do not pass in globals as the function could be defined in a different module.
2256 # Instead, let `get_callable_return_type` infer the globals to use, but still pass
2257 # in locals that may contain a parent/rebuild namespace:
2258 return_type = _decorators.get_callable_return_type( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2259 serializer.func, localns=self._types_namespace.locals
2260 )
2261 except NameError as e: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2262 raise PydanticUndefinedAnnotation.from_name_error(e) from e 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2264 if return_type is PydanticUndefined: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2265 return_schema = None 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2266 else:
2267 return_schema = self.generate_schema(return_type) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2269 if serializer.info.mode == 'wrap': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2270 schema['serialization'] = core_schema.wrap_serializer_function_ser_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2271 serializer.func,
2272 is_field_serializer=is_field_serializer,
2273 info_arg=info_arg,
2274 return_schema=return_schema,
2275 when_used=serializer.info.when_used,
2276 )
2277 else:
2278 assert serializer.info.mode == 'plain' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2279 schema['serialization'] = core_schema.plain_serializer_function_ser_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2280 serializer.func,
2281 is_field_serializer=is_field_serializer,
2282 info_arg=info_arg,
2283 return_schema=return_schema,
2284 when_used=serializer.info.when_used,
2285 )
2286 return schema 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2288 def _apply_model_serializers( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2289 self, schema: core_schema.CoreSchema, serializers: Iterable[Decorator[ModelSerializerDecoratorInfo]]
2290 ) -> core_schema.CoreSchema:
2291 """Apply model serializers to a schema."""
2292 ref: str | None = schema.pop('ref', None) # type: ignore 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2293 if serializers: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2294 serializer = list(serializers)[-1] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2295 info_arg = inspect_model_serializer(serializer.func, serializer.info.mode) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2297 if serializer.info.return_type is not PydanticUndefined: 2297 ↛ 2298line 2297 didn't jump to line 2298 because the condition on line 2297 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2298 return_type = serializer.info.return_type
2299 else:
2300 try: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2301 # Do not pass in globals as the function could be defined in a different module.
2302 # Instead, let `get_callable_return_type` infer the globals to use, but still pass
2303 # in locals that may contain a parent/rebuild namespace:
2304 return_type = _decorators.get_callable_return_type( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2305 serializer.func, localns=self._types_namespace.locals
2306 )
2307 except NameError as e:
2308 raise PydanticUndefinedAnnotation.from_name_error(e) from e
2310 if return_type is PydanticUndefined: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2311 return_schema = None 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2312 else:
2313 return_schema = self.generate_schema(return_type) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2315 if serializer.info.mode == 'wrap': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2316 ser_schema: core_schema.SerSchema = core_schema.wrap_serializer_function_ser_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2317 serializer.func,
2318 info_arg=info_arg,
2319 return_schema=return_schema,
2320 when_used=serializer.info.when_used,
2321 )
2322 else:
2323 # plain
2324 ser_schema = core_schema.plain_serializer_function_ser_schema( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2325 serializer.func,
2326 info_arg=info_arg,
2327 return_schema=return_schema,
2328 when_used=serializer.info.when_used,
2329 )
2330 schema['serialization'] = ser_schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2331 if ref: 2331 ↛ 2333line 2331 didn't jump to line 2333 because the condition on line 2331 was always true1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2332 schema['ref'] = ref # type: ignore 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2333 return schema 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2336_VALIDATOR_F_MATCH: Mapping[ 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2337 tuple[FieldValidatorModes, Literal['no-info', 'with-info']],
2338 Callable[[Callable[..., Any], core_schema.CoreSchema], core_schema.CoreSchema],
2339] = {
2340 ('before', 'no-info'): lambda f, schema: core_schema.no_info_before_validator_function(f, schema),
2341 ('after', 'no-info'): lambda f, schema: core_schema.no_info_after_validator_function(f, schema),
2342 ('plain', 'no-info'): lambda f, _: core_schema.no_info_plain_validator_function(f),
2343 ('wrap', 'no-info'): lambda f, schema: core_schema.no_info_wrap_validator_function(f, schema),
2344 ('before', 'with-info'): lambda f, schema: core_schema.with_info_before_validator_function(f, schema),
2345 ('after', 'with-info'): lambda f, schema: core_schema.with_info_after_validator_function(f, schema),
2346 ('plain', 'with-info'): lambda f, _: core_schema.with_info_plain_validator_function(f),
2347 ('wrap', 'with-info'): lambda f, schema: core_schema.with_info_wrap_validator_function(f, schema),
2348}
2351# TODO V3: this function is only used for deprecated decorators. It should
2352# be removed once we drop support for those.
2353def apply_validators( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2354 schema: core_schema.CoreSchema,
2355 validators: Iterable[Decorator[RootValidatorDecoratorInfo]]
2356 | Iterable[Decorator[ValidatorDecoratorInfo]]
2357 | Iterable[Decorator[FieldValidatorDecoratorInfo]],
2358) -> core_schema.CoreSchema:
2359 """Apply validators to a schema.
2361 Args:
2362 schema: The schema to apply validators on.
2363 validators: An iterable of validators.
2364 field_name: The name of the field if validators are being applied to a model field.
2366 Returns:
2367 The updated schema.
2368 """
2369 for validator in validators: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2370 info_arg = inspect_validator(validator.func, validator.info.mode) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2371 val_type = 'with-info' if info_arg else 'no-info' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2373 schema = _VALIDATOR_F_MATCH[(validator.info.mode, val_type)](validator.func, schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2374 return schema 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2377def _validators_require_validate_default(validators: Iterable[Decorator[ValidatorDecoratorInfo]]) -> bool: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2378 """In v1, if any of the validators for a field had `always=True`, the default value would be validated.
2380 This serves as an auxiliary function for re-implementing that logic, by looping over a provided
2381 collection of (v1-style) ValidatorDecoratorInfo's and checking if any of them have `always=True`.
2383 We should be able to drop this function and the associated logic calling it once we drop support
2384 for v1-style validator decorators. (Or we can extend it and keep it if we add something equivalent
2385 to the v1-validator `always` kwarg to `field_validator`.)
2386 """
2387 for validator in validators: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2388 if validator.info.always: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2389 return True 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2390 return False 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2393def apply_model_validators( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2394 schema: core_schema.CoreSchema,
2395 validators: Iterable[Decorator[ModelValidatorDecoratorInfo]],
2396 mode: Literal['inner', 'outer', 'all'],
2397) -> core_schema.CoreSchema:
2398 """Apply model validators to a schema.
2400 If mode == 'inner', only "before" validators are applied
2401 If mode == 'outer', validators other than "before" are applied
2402 If mode == 'all', all validators are applied
2404 Args:
2405 schema: The schema to apply validators on.
2406 validators: An iterable of validators.
2407 mode: The validator mode.
2409 Returns:
2410 The updated schema.
2411 """
2412 ref: str | None = schema.pop('ref', None) # type: ignore 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2413 for validator in validators: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2414 if mode == 'inner' and validator.info.mode != 'before': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2415 continue 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2416 if mode == 'outer' and validator.info.mode == 'before': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2417 continue 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2418 info_arg = inspect_validator(validator.func, validator.info.mode) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2419 if validator.info.mode == 'wrap': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2420 if info_arg: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2421 schema = core_schema.with_info_wrap_validator_function(function=validator.func, schema=schema) 1uwACDxyEFGvzBHI
2422 else:
2423 schema = core_schema.no_info_wrap_validator_function(function=validator.func, schema=schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2424 elif validator.info.mode == 'before': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2425 if info_arg: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2426 schema = core_schema.with_info_before_validator_function(function=validator.func, schema=schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2427 else:
2428 schema = core_schema.no_info_before_validator_function(function=validator.func, schema=schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2429 else:
2430 assert validator.info.mode == 'after' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2431 if info_arg: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2432 schema = core_schema.with_info_after_validator_function(function=validator.func, schema=schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2433 else:
2434 schema = core_schema.no_info_after_validator_function(function=validator.func, schema=schema) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2435 if ref: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2436 schema['ref'] = ref # type: ignore 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2437 return schema 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2440def wrap_default(field_info: FieldInfo, schema: core_schema.CoreSchema) -> core_schema.CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2441 """Wrap schema with default schema if default value or `default_factory` are available.
2443 Args:
2444 field_info: The field info object.
2445 schema: The schema to apply default on.
2447 Returns:
2448 Updated schema by default value or `default_factory`.
2449 """
2450 if field_info.default_factory: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2451 return core_schema.with_default_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2452 schema,
2453 default_factory=field_info.default_factory,
2454 default_factory_takes_data=takes_validated_data_argument(field_info.default_factory),
2455 validate_default=field_info.validate_default,
2456 )
2457 elif field_info.default is not PydanticUndefined: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2458 return core_schema.with_default_schema( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2459 schema, default=field_info.default, validate_default=field_info.validate_default
2460 )
2461 else:
2462 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2465def _extract_get_pydantic_json_schema(tp: Any) -> GetJsonSchemaFunction | None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2466 """Extract `__get_pydantic_json_schema__` from a type, handling the deprecated `__modify_schema__`."""
2467 js_modify_function = getattr(tp, '__get_pydantic_json_schema__', None) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2469 if hasattr(tp, '__modify_schema__'): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2470 BaseModel = import_cached_base_model() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2472 has_custom_v2_modify_js_func = ( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2473 js_modify_function is not None
2474 and BaseModel.__get_pydantic_json_schema__.__func__ # type: ignore
2475 not in (js_modify_function, getattr(js_modify_function, '__func__', None))
2476 )
2478 if not has_custom_v2_modify_js_func: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2479 cls_name = getattr(tp, '__name__', None) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2480 raise PydanticUserError( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2481 f'The `__modify_schema__` method is not supported in Pydantic v2. '
2482 f'Use `__get_pydantic_json_schema__` instead{f" in class `{cls_name}`" if cls_name else ""}.',
2483 code='custom-json-schema',
2484 )
2486 if (origin := get_origin(tp)) is not None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2487 # Generic aliases proxy attribute access to the origin, *except* dunder attributes,
2488 # such as `__get_pydantic_json_schema__`, hence the explicit check.
2489 return _extract_get_pydantic_json_schema(origin) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2491 if js_modify_function is None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2492 return None 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2494 return js_modify_function 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2497class _CommonField(TypedDict): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2498 schema: core_schema.CoreSchema 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2499 validation_alias: str | list[str | int] | list[list[str | int]] | None 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2500 serialization_alias: str | None 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2501 serialization_exclude: bool | None 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2502 frozen: bool | None 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2503 metadata: dict[str, Any] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2506def _common_field( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2507 schema: core_schema.CoreSchema,
2508 *,
2509 validation_alias: str | list[str | int] | list[list[str | int]] | None = None,
2510 serialization_alias: str | None = None,
2511 serialization_exclude: bool | None = None,
2512 frozen: bool | None = None,
2513 metadata: Any = None,
2514) -> _CommonField:
2515 return { 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2516 'schema': schema,
2517 'validation_alias': validation_alias,
2518 'serialization_alias': serialization_alias,
2519 'serialization_exclude': serialization_exclude,
2520 'frozen': frozen,
2521 'metadata': metadata,
2522 }
2525def resolve_original_schema(schema: CoreSchema, definitions: _Definitions) -> CoreSchema | None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2526 if schema['type'] == 'definition-ref': 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2527 return definitions.get_schema_from_ref(schema['schema_ref']) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2528 elif schema['type'] == 'definitions': 2528 ↛ 2529line 2528 didn't jump to line 2529 because the condition on line 2528 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2529 return schema['schema']
2530 else:
2531 return schema 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2534def _inlining_behavior( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2535 def_ref: core_schema.DefinitionReferenceSchema,
2536) -> Literal['inline', 'keep', 'preserve_metadata']:
2537 """Determine the inlining behavior of the `'definition-ref'` schema.
2539 - If no `'serialization'` schema and no metadata is attached, the schema can safely be inlined.
2540 - If it has metadata but only related to the deferred discriminator application, it can be inlined
2541 provided that such metadata is kept.
2542 - Otherwise, the schema should not be inlined. Doing so would remove the `'serialization'` schema or metadata.
2543 """
2544 if 'serialization' in def_ref: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2545 return 'keep' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2546 metadata = def_ref.get('metadata') 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2547 if not metadata: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2548 return 'inline' 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2549 if len(metadata) == 1 and 'pydantic_internal_union_discriminator' in metadata: 2549 ↛ 2550line 2549 didn't jump to line 2550 because the condition on line 2549 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2550 return 'preserve_metadata'
2551 return 'keep' 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2554class _Definitions: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2555 """Keeps track of references and definitions."""
2557 _recursively_seen: set[str] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2558 """A set of recursively seen references. 1cfnquwACDgjkrsxyEFGJemptvzBHI
2560 When a referenceable type is encountered, the `get_schema_or_ref` context manager is
2561 entered to compute the reference. If the type references itself by some way (e.g. for
2562 a dataclass a Pydantic model, the class can be referenced as a field annotation),
2563 entering the context manager again will yield a `'definition-ref'` schema that should
2564 short-circuit the normal generation process, as the reference was already in this set.
2565 """
2567 _definitions: dict[str, core_schema.CoreSchema] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2568 """A mapping of references to their corresponding schema. 1cfnquwACDgjkrsxyEFGJemptvzBHI
2570 When a schema for a referenceable type is generated, it is stored in this mapping. If the
2571 same type is encountered again, the reference is yielded by the `get_schema_or_ref` context
2572 manager.
2573 """
2575 def __init__(self) -> None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2576 self._recursively_seen = set() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2577 self._definitions = {} 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2579 @contextmanager 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2580 def get_schema_or_ref(self, tp: Any, /) -> Generator[tuple[str, core_schema.DefinitionReferenceSchema | None]]: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2581 """Get a definition for `tp` if one exists.
2583 If a definition exists, a tuple of `(ref_string, CoreSchema)` is returned.
2584 If no definition exists yet, a tuple of `(ref_string, None)` is returned.
2586 Note that the returned `CoreSchema` will always be a `DefinitionReferenceSchema`,
2587 not the actual definition itself.
2589 This should be called for any type that can be identified by reference.
2590 This includes any recursive types.
2592 At present the following types can be named/recursive:
2594 - Pydantic model
2595 - Pydantic and stdlib dataclasses
2596 - Typed dictionaries
2597 - Named tuples
2598 - `TypeAliasType` instances
2599 - Enums
2600 """
2601 ref = get_type_ref(tp) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2602 # return the reference if we're either (1) in a cycle or (2) it the reference was already encountered:
2603 if ref in self._recursively_seen or ref in self._definitions: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2604 yield (ref, core_schema.definition_reference_schema(ref)) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2605 else:
2606 self._recursively_seen.add(ref) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2607 try: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2608 yield (ref, None) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2609 finally:
2610 self._recursively_seen.discard(ref) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2612 def get_schema_from_ref(self, ref: str) -> CoreSchema | None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2613 """Resolve the schema from the given reference."""
2614 return self._definitions.get(ref) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2616 def create_definition_reference_schema(self, schema: CoreSchema) -> core_schema.DefinitionReferenceSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2617 """Store the schema as a definition and return a `'definition-reference'` schema pointing to it.
2619 The schema must have a reference attached to it.
2620 """
2621 ref = schema['ref'] # pyright: ignore 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2622 self._definitions[ref] = schema 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2623 return core_schema.definition_reference_schema(ref) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2625 def unpack_definitions(self, schema: core_schema.DefinitionsSchema) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2626 """Store the definitions of the `'definitions'` core schema and return the inner core schema."""
2627 for def_schema in schema['definitions']: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2628 self._definitions[def_schema['ref']] = def_schema # pyright: ignore 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2629 return schema['schema'] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2631 def finalize_schema(self, schema: CoreSchema) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2632 """Finalize the core schema.
2634 This traverses the core schema and referenced definitions, replaces `'definition-ref'` schemas
2635 by the referenced definition if possible, and applies deferred discriminators.
2636 """
2637 definitions = self._definitions 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2638 try: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2639 gather_result = gather_schemas_for_cleaning( 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2640 schema,
2641 definitions=definitions,
2642 )
2643 except MissingDefinitionError as e: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2644 raise InvalidSchemaError from e 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2646 remaining_defs: dict[str, CoreSchema] = {} 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2648 # Note: this logic doesn't play well when core schemas with deferred discriminator metadata
2649 # and references are encountered. See the `test_deferred_discriminated_union_and_references()` test.
2650 for ref, inlinable_def_ref in gather_result['collected_references'].items(): 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2651 if inlinable_def_ref is not None and (inlining_behavior := _inlining_behavior(inlinable_def_ref)) != 'keep': 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2652 if inlining_behavior == 'inline': 2652 ↛ 2659line 2652 didn't jump to line 2659 because the condition on line 2652 was always true1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2653 # `ref` was encountered, and only once:
2654 # - `inlinable_def_ref` is a `'definition-ref'` schema and is guaranteed to be
2655 # the only one. Transform it into the definition it points to.
2656 # - Do not store the definition in the `remaining_defs`.
2657 inlinable_def_ref.clear() # pyright: ignore[reportAttributeAccessIssue] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2658 inlinable_def_ref.update(self._resolve_definition(ref, definitions)) # pyright: ignore 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2659 elif inlining_behavior == 'preserve_metadata':
2660 # `ref` was encountered, and only once, but contains discriminator metadata.
2661 # We will do the same thing as if `inlining_behavior` was `'inline'`, but make
2662 # sure to keep the metadata for the deferred discriminator application logic below.
2663 meta = inlinable_def_ref.pop('metadata')
2664 inlinable_def_ref.clear() # pyright: ignore[reportAttributeAccessIssue]
2665 inlinable_def_ref.update(self._resolve_definition(ref, definitions)) # pyright: ignore
2666 inlinable_def_ref['metadata'] = meta
2667 else:
2668 # `ref` was encountered, at least two times (or only once, but with metadata or a serialization schema):
2669 # - Do not inline the `'definition-ref'` schemas (they are not provided in the gather result anyway).
2670 # - Store the the definition in the `remaining_defs`
2671 remaining_defs[ref] = self._resolve_definition(ref, definitions) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2673 for cs in gather_result['deferred_discriminator_schemas']: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2674 discriminator: str | None = cs['metadata'].pop('pydantic_internal_union_discriminator', None) # pyright: ignore[reportTypedDictNotRequiredAccess] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2675 if discriminator is None: 2675 ↛ 2679line 2675 didn't jump to line 2679 because the condition on line 2675 was never true1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2676 # This can happen in rare scenarios, when a deferred schema is present multiple times in the
2677 # gather result (e.g. when using the `Sequence` type -- see `test_sequence_discriminated_union()`).
2678 # In this case, a previous loop iteration applied the discriminator and so we can just skip it here.
2679 continue
2680 applied = _discriminated_union.apply_discriminator(cs.copy(), discriminator, remaining_defs) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2681 # Mutate the schema directly to have the discriminator applied
2682 cs.clear() # pyright: ignore[reportAttributeAccessIssue] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2683 cs.update(applied) # pyright: ignore 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2685 if remaining_defs: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2686 schema = core_schema.definitions_schema(schema=schema, definitions=[*remaining_defs.values()]) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2687 return schema 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2689 def _resolve_definition(self, ref: str, definitions: dict[str, CoreSchema]) -> CoreSchema: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2690 definition = definitions[ref] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2691 if definition['type'] != 'definition-ref': 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2692 return definition 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2694 # Some `'definition-ref'` schemas might act as "intermediate" references (e.g. when using
2695 # a PEP 695 type alias (which is referenceable) that references another PEP 695 type alias):
2696 visited: set[str] = set() 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2697 while definition['type'] == 'definition-ref' and _inlining_behavior(definition) == 'inline': 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2698 schema_ref = definition['schema_ref'] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2699 if schema_ref in visited: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2700 raise PydanticUserError( 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2701 f'{ref} contains a circular reference to itself.', code='circular-reference-schema'
2702 )
2703 visited.add(schema_ref) 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2704 definition = definitions[schema_ref] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2705 return {**definition, 'ref': ref} # pyright: ignore[reportReturnType] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2708class _FieldNameStack: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2709 __slots__ = ('_stack',) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2711 def __init__(self) -> None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2712 self._stack: list[str] = [] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2714 @contextmanager 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2715 def push(self, field_name: str) -> Iterator[None]: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2716 self._stack.append(field_name) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2717 yield 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2718 self._stack.pop() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2720 def get(self) -> str | None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2721 if self._stack:
2722 return self._stack[-1]
2723 else:
2724 return None
2727class _ModelTypeStack: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2728 __slots__ = ('_stack',) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2730 def __init__(self) -> None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2731 self._stack: list[type] = [] 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2733 @contextmanager 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2734 def push(self, type_obj: type) -> Iterator[None]: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2735 self._stack.append(type_obj) 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2736 yield 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2737 self._stack.pop() 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2739 def get(self) -> type | None: 1abcfnquwACDoghijkrsxyEFGJdlemptvzBHI
2740 if self._stack: 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2741 return self._stack[-1] 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI
2742 else:
2743 return None 1abcfnquwACDoghijkrsxyEFGdlemptvzBHI