Coverage for pydantic/_internal/_generate_schema.py: 95.63%
1260 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-02-13 19:35 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-02-13 19:35 +0000
1"""Convert python types to pydantic-core schema."""
3from __future__ import annotations as _annotations 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
5import collections.abc 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
6import dataclasses 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
7import datetime 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
8import inspect 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
9import os 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
10import pathlib 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
11import re 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
12import sys 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
13import typing 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
14import warnings 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
15from collections.abc import Generator, Iterable, Iterator, Mapping 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
16from contextlib import contextmanager 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
17from copy import copy 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
18from decimal import Decimal 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
19from enum import Enum 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
20from fractions import Fraction 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
21from functools import partial 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
22from inspect import Parameter, _ParameterKind, signature 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
23from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
24from itertools import chain 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
25from operator import attrgetter 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
26from types import FunctionType, GenericAlias, LambdaType, MethodType 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
27from typing import ( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
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 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
40from warnings import warn 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
42import typing_extensions 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
43from pydantic_core import ( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
44 CoreSchema,
45 MultiHostUrl,
46 PydanticCustomError,
47 PydanticSerializationUnexpectedValue,
48 PydanticUndefined,
49 Url,
50 core_schema,
51 to_jsonable_python,
52)
53from typing_extensions import TypeAliasType, TypedDict, get_args, get_origin, is_typeddict 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
55from ..aliases import AliasChoices, AliasGenerator, AliasPath 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
56from ..annotated_handlers import GetCoreSchemaHandler, GetJsonSchemaHandler 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
57from ..config import ConfigDict, JsonDict, JsonEncoder, JsonSchemaExtraCallable 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
58from ..errors import PydanticSchemaGenerationError, PydanticUndefinedAnnotation, PydanticUserError 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
59from ..functional_validators import AfterValidator, BeforeValidator, FieldValidatorModes, PlainValidator, WrapValidator 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
60from ..json_schema import JsonSchemaValue 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
61from ..version import version_short 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
62from ..warnings import PydanticDeprecatedSince20 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
63from . import _decorators, _discriminated_union, _known_annotated_metadata, _repr, _typing_extra 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
64from ._config import ConfigWrapper, ConfigWrapperStack 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
65from ._core_metadata import CoreMetadata, update_core_metadata 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
66from ._core_utils import ( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
67 get_ref,
68 get_type_ref,
69 is_list_like_schema_with_items_schema,
70 validate_core_schema,
71)
72from ._decorators import ( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
73 Decorator,
74 DecoratorInfos,
75 FieldSerializerDecoratorInfo,
76 FieldValidatorDecoratorInfo,
77 ModelSerializerDecoratorInfo,
78 ModelValidatorDecoratorInfo,
79 RootValidatorDecoratorInfo,
80 ValidatorDecoratorInfo,
81 get_attribute_from_bases,
82 inspect_field_serializer,
83 inspect_model_serializer,
84 inspect_validator,
85)
86from ._docs_extraction import extract_docstrings_from_cls 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
87from ._fields import collect_dataclass_fields, rebuild_model_fields, takes_validated_data_argument 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
88from ._forward_ref import PydanticRecursiveRef 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
89from ._generics import get_standard_typevars_map, replace_types 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
90from ._import_utils import import_cached_base_model, import_cached_field_info 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
91from ._mock_val_ser import MockCoreSchema 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
92from ._namespace_utils import NamespacesTuple, NsResolver 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
93from ._schema_gather import MissingDefinitionError, gather_schemas_for_cleaning 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
94from ._schema_generation_shared import CallbackGetCoreSchemaHandler 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
95from ._utils import lenient_issubclass, smart_deepcopy 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
97if TYPE_CHECKING: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
98 from ..fields import ComputedFieldInfo, FieldInfo
99 from ..main import BaseModel
100 from ..types import Discriminator
101 from ._dataclasses import StandardDataclass
102 from ._schema_generation_shared import GetJsonSchemaFunction
104_SUPPORTS_TYPEDDICT = sys.version_info >= (3, 12) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
106FieldDecoratorInfo = Union[ValidatorDecoratorInfo, FieldValidatorDecoratorInfo, FieldSerializerDecoratorInfo] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
107FieldDecoratorInfoType = TypeVar('FieldDecoratorInfoType', bound=FieldDecoratorInfo) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
108AnyFieldDecorator = Union[ 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
109 Decorator[ValidatorDecoratorInfo],
110 Decorator[FieldValidatorDecoratorInfo],
111 Decorator[FieldSerializerDecoratorInfo],
112]
114ModifyCoreSchemaWrapHandler = GetCoreSchemaHandler 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
115GetCoreSchemaFunction = Callable[[Any, ModifyCoreSchemaWrapHandler], core_schema.CoreSchema] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
117TUPLE_TYPES: list[type] = [typing.Tuple, tuple] # noqa: UP006 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
118LIST_TYPES: list[type] = [typing.List, list, collections.abc.MutableSequence] # noqa: UP006 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
119SET_TYPES: list[type] = [typing.Set, set, collections.abc.MutableSet] # noqa: UP006 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
120FROZEN_SET_TYPES: list[type] = [typing.FrozenSet, frozenset, collections.abc.Set] # noqa: UP006 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
121DICT_TYPES: list[type] = [typing.Dict, dict] # noqa: UP006 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
122IP_TYPES: list[type] = [IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
123SEQUENCE_TYPES: list[type] = [typing.Sequence, collections.abc.Sequence] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
124ITERABLE_TYPES: list[type] = [typing.Iterable, collections.abc.Iterable, typing.Generator, collections.abc.Generator] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
125TYPE_TYPES: list[type] = [typing.Type, type] # noqa: UP006 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
126PATTERN_TYPES: list[type] = [typing.Pattern, re.Pattern] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
127PATH_TYPES: list[type] = [ 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
128 os.PathLike,
129 pathlib.Path,
130 pathlib.PurePath,
131 pathlib.PosixPath,
132 pathlib.PurePosixPath,
133 pathlib.PureWindowsPath,
134]
135MAPPING_TYPES = [ 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
136 typing.Mapping,
137 typing.MutableMapping,
138 collections.abc.Mapping,
139 collections.abc.MutableMapping,
140 collections.OrderedDict,
141 typing_extensions.OrderedDict,
142 typing.DefaultDict, # noqa: UP006
143 collections.defaultdict,
144]
145COUNTER_TYPES = [collections.Counter, typing.Counter] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
146DEQUE_TYPES: list[type] = [collections.deque, typing.Deque] # noqa: UP006 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
148# Note: This does not play very well with type checkers. For example,
149# `a: LambdaType = lambda x: x` will raise a type error by Pyright.
150ValidateCallSupportedTypes = Union[ 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
151 LambdaType,
152 FunctionType,
153 MethodType,
154 partial,
155]
157VALIDATE_CALL_SUPPORTED_TYPES = get_args(ValidateCallSupportedTypes) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
159_mode_to_validator: dict[ 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
160 FieldValidatorModes, type[BeforeValidator | AfterValidator | PlainValidator | WrapValidator]
161] = {'before': BeforeValidator, 'after': AfterValidator, 'plain': PlainValidator, 'wrap': WrapValidator}
164def check_validator_fields_against_field_name( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
165 info: FieldDecoratorInfo,
166 field: str,
167) -> bool:
168 """Check if field name is in validator fields.
170 Args:
171 info: The field info.
172 field: The field name to check.
174 Returns:
175 `True` if field name is in validator fields, `False` otherwise.
176 """
177 fields = info.fields 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
178 return '*' in fields or field in fields 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
181def check_decorator_fields_exist(decorators: Iterable[AnyFieldDecorator], fields: Iterable[str]) -> None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
182 """Check if the defined fields in decorators exist in `fields` param.
184 It ignores the check for a decorator if the decorator has `*` as field or `check_fields=False`.
186 Args:
187 decorators: An iterable of decorators.
188 fields: An iterable of fields name.
190 Raises:
191 PydanticUserError: If one of the field names does not exist in `fields` param.
192 """
193 fields = set(fields) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
194 for dec in decorators: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
195 if '*' in dec.info.fields: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
196 continue 1acekoquwxCfbhilmrsyzDEdjgnptvABF
197 if dec.info.check_fields is False: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
198 continue 1acekoquwxCfbhilmrsyzDEdjgnptvABF
199 for field in dec.info.fields: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
200 if field not in fields: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
201 raise PydanticUserError( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
202 f'Decorators defined with incorrect fields: {dec.cls_ref}.{dec.cls_var_name}'
203 " (use check_fields=False if you're inheriting from the model and intended this)",
204 code='decorator-missing-field',
205 )
208def filter_field_decorator_info_by_field( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
209 validator_functions: Iterable[Decorator[FieldDecoratorInfoType]], field: str
210) -> list[Decorator[FieldDecoratorInfoType]]:
211 return [dec for dec in validator_functions if check_validator_fields_against_field_name(dec.info, field)] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
214def apply_each_item_validators( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
215 schema: core_schema.CoreSchema,
216 each_item_validators: list[Decorator[ValidatorDecoratorInfo]],
217 field_name: str | None,
218) -> core_schema.CoreSchema:
219 # This V1 compatibility shim should eventually be removed
221 # fail early if each_item_validators is empty
222 if not each_item_validators: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
223 return schema 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
225 # push down any `each_item=True` validators
226 # note that this won't work for any Annotated types that get wrapped by a function validator
227 # but that's okay because that didn't exist in V1
228 if schema['type'] == 'nullable': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
229 schema['schema'] = apply_each_item_validators(schema['schema'], each_item_validators, field_name) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
230 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
231 elif schema['type'] == 'tuple': 231 ↛ 232line 231 didn't jump to line 232 because the condition on line 231 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
232 if (variadic_item_index := schema.get('variadic_item_index')) is not None:
233 schema['items_schema'][variadic_item_index] = apply_validators(
234 schema['items_schema'][variadic_item_index],
235 each_item_validators,
236 field_name,
237 )
238 elif is_list_like_schema_with_items_schema(schema): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
239 inner_schema = schema.get('items_schema', core_schema.any_schema()) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
240 schema['items_schema'] = apply_validators(inner_schema, each_item_validators, field_name) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
241 elif schema['type'] == 'dict': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
242 inner_schema = schema.get('values_schema', core_schema.any_schema()) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
243 schema['values_schema'] = apply_validators(inner_schema, each_item_validators, field_name) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
244 else:
245 raise TypeError( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
246 f'`@validator(..., each_item=True)` cannot be applied to fields with a schema of {schema["type"]}'
247 )
248 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
251def _extract_json_schema_info_from_field_info( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
252 info: FieldInfo | ComputedFieldInfo,
253) -> tuple[JsonDict | None, JsonDict | JsonSchemaExtraCallable | None]:
254 json_schema_updates = { 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
255 'title': info.title,
256 'description': info.description,
257 'deprecated': bool(info.deprecated) or info.deprecated == '' or None,
258 'examples': to_jsonable_python(info.examples),
259 }
260 json_schema_updates = {k: v for k, v in json_schema_updates.items() if v is not None} 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
261 return (json_schema_updates or None, info.json_schema_extra) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
264JsonEncoders = dict[type[Any], JsonEncoder] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
267def _add_custom_serialization_from_json_encoders( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
268 json_encoders: JsonEncoders | None, tp: Any, schema: CoreSchema
269) -> CoreSchema:
270 """Iterate over the json_encoders and add the first matching encoder to the schema.
272 Args:
273 json_encoders: A dictionary of types and their encoder functions.
274 tp: The type to check for a matching encoder.
275 schema: The schema to add the encoder to.
276 """
277 if not json_encoders: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
278 return schema 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
279 if 'serialization' in schema: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
280 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
281 # Check the class type and its superclasses for a matching encoder
282 # Decimal.__class__.__mro__ (and probably other cases) doesn't include Decimal itself
283 # if the type is a GenericAlias (e.g. from list[int]) we need to use __class__ instead of .__mro__
284 for base in (tp, *getattr(tp, '__mro__', tp.__class__.__mro__)[:-1]): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
285 encoder = json_encoders.get(base) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
286 if encoder is None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
287 continue 1acekoquwxCfbhilmrsyzDEdjgnptvABF
289 warnings.warn( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
290 f'`json_encoders` is deprecated. See https://docs.pydantic.dev/{version_short()}/concepts/serialization/#custom-serializers for alternatives',
291 PydanticDeprecatedSince20,
292 )
294 # TODO: in theory we should check that the schema accepts a serialization key
295 schema['serialization'] = core_schema.plain_serializer_function_ser_schema(encoder, when_used='json') 1acekoquwxCfbhilmrsyzDEdjgnptvABF
296 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
298 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
301def _get_first_non_null(a: Any, b: Any) -> Any: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
302 """Return the first argument if it is not None, otherwise return the second argument.
304 Use case: serialization_alias (argument a) and alias (argument b) are both defined, and serialization_alias is ''.
305 This function will return serialization_alias, which is the first argument, even though it is an empty string.
306 """
307 return a if a is not None else b 1acekoquwxCfbhilmrsyzDEdjgnptvABF
310class InvalidSchemaError(Exception): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
311 """The core schema is invalid."""
314class GenerateSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
315 """Generate core schema for a Pydantic model, dataclass and types like `str`, `datetime`, ... ."""
317 __slots__ = ( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
318 '_config_wrapper_stack',
319 '_ns_resolver',
320 '_typevars_map',
321 'field_name_stack',
322 'model_type_stack',
323 'defs',
324 )
326 def __init__( 1acekoquwxChilmrsyzDELGHIJKMdjgnptvABF
327 self,
328 config_wrapper: ConfigWrapper,
329 ns_resolver: NsResolver | None = None,
330 typevars_map: Mapping[TypeVar, Any] | None = None,
331 ) -> None:
332 # we need a stack for recursing into nested models
333 self._config_wrapper_stack = ConfigWrapperStack(config_wrapper) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
334 self._ns_resolver = ns_resolver or NsResolver() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
335 self._typevars_map = typevars_map 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
336 self.field_name_stack = _FieldNameStack() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
337 self.model_type_stack = _ModelTypeStack() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
338 self.defs = _Definitions() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
340 def __init_subclass__(cls) -> None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
341 super().__init_subclass__() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
342 warnings.warn( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
343 'Subclassing `GenerateSchema` is not supported. The API is highly subject to change in minor versions.',
344 UserWarning,
345 stacklevel=2,
346 )
348 @property 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
349 def _config_wrapper(self) -> ConfigWrapper: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
350 return self._config_wrapper_stack.tail 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
352 @property 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
353 def _types_namespace(self) -> NamespacesTuple: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
354 return self._ns_resolver.types_namespace 1acekoquwxCfbhilmrsyzDEdjgnptvABF
356 @property 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
357 def _arbitrary_types(self) -> bool: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
358 return self._config_wrapper.arbitrary_types_allowed 1acekoquwxCfbhilmrsyzDEdjgnptvABF
360 # the following methods can be overridden but should be considered
361 # unstable / private APIs
362 def _list_schema(self, items_type: Any) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
363 return core_schema.list_schema(self.generate_schema(items_type)) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
365 def _dict_schema(self, keys_type: Any, values_type: Any) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
366 return core_schema.dict_schema(self.generate_schema(keys_type), self.generate_schema(values_type)) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
368 def _set_schema(self, items_type: Any) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
369 return core_schema.set_schema(self.generate_schema(items_type)) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
371 def _frozenset_schema(self, items_type: Any) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
372 return core_schema.frozenset_schema(self.generate_schema(items_type)) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
374 def _enum_schema(self, enum_type: type[Enum]) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
375 cases: list[Any] = list(enum_type.__members__.values()) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
377 enum_ref = get_type_ref(enum_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
378 description = None if not enum_type.__doc__ else inspect.cleandoc(enum_type.__doc__) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
379 if ( 1acfb
380 description == 'An enumeration.'
381 ): # This is the default value provided by enum.EnumMeta.__new__; don't use it
382 description = None 1acekfbhilmdjgn
383 js_updates = {'title': enum_type.__name__, 'description': description} 1acekoquwxCfbhilmrsyzDEdjgnptvABF
384 js_updates = {k: v for k, v in js_updates.items() if v is not None} 1acekoquwxCfbhilmrsyzDEdjgnptvABF
386 sub_type: Literal['str', 'int', 'float'] | None = None 1acekoquwxCfbhilmrsyzDEdjgnptvABF
387 if issubclass(enum_type, int): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
388 sub_type = 'int' 1acekoquwxCfbhilmrsyzDEdjgnptvABF
389 value_ser_type: core_schema.SerSchema = core_schema.simple_ser_schema('int') 1acekoquwxCfbhilmrsyzDEdjgnptvABF
390 elif issubclass(enum_type, str): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
391 # this handles `StrEnum` (3.11 only), and also `Foobar(str, Enum)`
392 sub_type = 'str' 1acekoquwxCfbhilmrsyzDEdjgnptvABF
393 value_ser_type = core_schema.simple_ser_schema('str') 1acekoquwxCfbhilmrsyzDEdjgnptvABF
394 elif issubclass(enum_type, float): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
395 sub_type = 'float' 1acekoquwxCfbhilmrsyzDEdjgnptvABF
396 value_ser_type = core_schema.simple_ser_schema('float') 1acekoquwxCfbhilmrsyzDEdjgnptvABF
397 else:
398 # TODO this is an ugly hack, how do we trigger an Any schema for serialization?
399 value_ser_type = core_schema.plain_serializer_function_ser_schema(lambda x: x) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
401 if cases: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
403 def get_json_schema(schema: CoreSchema, handler: GetJsonSchemaHandler) -> JsonSchemaValue: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
404 json_schema = handler(schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
405 original_schema = handler.resolve_ref_schema(json_schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
406 original_schema.update(js_updates) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
407 return json_schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
409 # we don't want to add the missing to the schema if it's the default one
410 default_missing = getattr(enum_type._missing_, '__func__', None) is Enum._missing_.__func__ # pyright: ignore[reportFunctionMemberAccess] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
411 enum_schema = core_schema.enum_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
412 enum_type,
413 cases,
414 sub_type=sub_type,
415 missing=None if default_missing else enum_type._missing_,
416 ref=enum_ref,
417 metadata={'pydantic_js_functions': [get_json_schema]},
418 )
420 if self._config_wrapper.use_enum_values: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
421 enum_schema = core_schema.no_info_after_validator_function( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
422 attrgetter('value'), enum_schema, serialization=value_ser_type
423 )
425 return enum_schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
427 else:
429 def get_json_schema_no_cases(_, handler: GetJsonSchemaHandler) -> JsonSchemaValue: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
430 json_schema = handler(core_schema.enum_schema(enum_type, cases, sub_type=sub_type, ref=enum_ref)) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
431 original_schema = handler.resolve_ref_schema(json_schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
432 original_schema.update(js_updates) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
433 return json_schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
435 # Use an isinstance check for enums with no cases.
436 # The most important use case for this is creating TypeVar bounds for generics that should
437 # be restricted to enums. This is more consistent than it might seem at first, since you can only
438 # subclass enum.Enum (or subclasses of enum.Enum) if all parent classes have no cases.
439 # We use the get_json_schema function when an Enum subclass has been declared with no cases
440 # so that we can still generate a valid json schema.
441 return core_schema.is_instance_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
442 enum_type,
443 metadata={'pydantic_js_functions': [get_json_schema_no_cases]},
444 )
446 def _ip_schema(self, tp: Any) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
447 from ._validators import IP_VALIDATOR_LOOKUP, IpType 1acekoquwxCfbhilmrsyzDEdjgnptvABF
449 ip_type_json_schema_format: dict[type[IpType], str] = { 1acekoquwxCfbhilmrsyzDEdjgnptvABF
450 IPv4Address: 'ipv4',
451 IPv4Network: 'ipv4network',
452 IPv4Interface: 'ipv4interface',
453 IPv6Address: 'ipv6',
454 IPv6Network: 'ipv6network',
455 IPv6Interface: 'ipv6interface',
456 }
458 def ser_ip(ip: Any, info: core_schema.SerializationInfo) -> str | IpType: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
459 if not isinstance(ip, (tp, str)): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
460 raise PydanticSerializationUnexpectedValue( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
461 f"Expected `{tp}` but got `{type(ip)}` with value `'{ip}'` - serialized value may not be as expected."
462 )
463 if info.mode == 'python': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
464 return ip 1acekoquwxCfbhilmrsyzDEdjgnptvABF
465 return str(ip) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
467 return core_schema.lax_or_strict_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
468 lax_schema=core_schema.no_info_plain_validator_function(IP_VALIDATOR_LOOKUP[tp]),
469 strict_schema=core_schema.json_or_python_schema(
470 json_schema=core_schema.no_info_after_validator_function(tp, core_schema.str_schema()),
471 python_schema=core_schema.is_instance_schema(tp),
472 ),
473 serialization=core_schema.plain_serializer_function_ser_schema(ser_ip, info_arg=True, when_used='always'),
474 metadata={
475 'pydantic_js_functions': [lambda _1, _2: {'type': 'string', 'format': ip_type_json_schema_format[tp]}]
476 },
477 )
479 def _path_schema(self, tp: Any, path_type: Any) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
480 if tp is os.PathLike and (path_type not in {str, bytes} and not _typing_extra.is_any(path_type)): 480 ↛ 481line 480 didn't jump to line 481 because the condition on line 480 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
481 raise PydanticUserError(
482 '`os.PathLike` can only be used with `str`, `bytes` or `Any`', code='schema-for-unknown-type'
483 )
485 path_constructor = pathlib.PurePath if tp is os.PathLike else tp 1acekoquwxCfbhilmrsyzDEdjgnptvABF
486 constrained_schema = core_schema.bytes_schema() if (path_type is bytes) else core_schema.str_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
488 def path_validator(input_value: str | bytes) -> os.PathLike[Any]: # type: ignore 1acekoquwxCfbhilmrsyzDEdjgnptvABF
489 try: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
490 if path_type is bytes: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
491 if isinstance(input_value, bytes): 491 ↛ 497line 491 didn't jump to line 497 because the condition on line 491 was always true1acekoquwxCfbhilmrsyzDEdjgnptvABF
492 try: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
493 input_value = input_value.decode() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
494 except UnicodeDecodeError as e:
495 raise PydanticCustomError('bytes_type', 'Input must be valid bytes') from e
496 else:
497 raise PydanticCustomError('bytes_type', 'Input must be bytes')
498 elif not isinstance(input_value, str): 498 ↛ 499line 498 didn't jump to line 499 because the condition on line 498 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
499 raise PydanticCustomError('path_type', 'Input is not a valid path')
501 return path_constructor(input_value) # type: ignore 1acekoquwxCfbhilmrsyzDEdjgnptvABF
502 except TypeError as e:
503 raise PydanticCustomError('path_type', 'Input is not a valid path') from e
505 def ser_path(path: Any, info: core_schema.SerializationInfo) -> str | os.PathLike[Any]: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
506 if not isinstance(path, (tp, str)): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
507 raise PydanticSerializationUnexpectedValue( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
508 f"Expected `{tp}` but got `{type(path)}` with value `'{path}'` - serialized value may not be as expected."
509 )
510 if info.mode == 'python': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
511 return path 1acekoquwxCfbhilmrsyzDEdjgnptvABF
512 return str(path) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
514 instance_schema = core_schema.json_or_python_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
515 json_schema=core_schema.no_info_after_validator_function(path_validator, constrained_schema),
516 python_schema=core_schema.is_instance_schema(tp),
517 )
519 schema = core_schema.lax_or_strict_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
520 lax_schema=core_schema.union_schema(
521 [
522 instance_schema,
523 core_schema.no_info_after_validator_function(path_validator, constrained_schema),
524 ],
525 custom_error_type='path_type',
526 custom_error_message=f'Input is not a valid path for {tp}',
527 strict=True,
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 1acekoquwxCfbhilmrsyzDEdjgnptvABF
535 def _deque_schema(self, items_type: Any) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
536 from ._serializers import serialize_sequence_via_list 1acekoquwxCfbhilmrsyzDEdjgnptvABF
537 from ._validators import deque_validator 1acekoquwxCfbhilmrsyzDEdjgnptvABF
539 item_type_schema = self.generate_schema(items_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
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) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
545 check_instance = core_schema.json_or_python_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
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) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
552 return core_schema.lax_or_strict_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
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: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
561 from ._validators import MAPPING_ORIGIN_MAP, defaultdict_validator, get_defaultdict_default_default_factory 1acekoquwxCfbhilmrsyzDEdjgnptvABF
563 keys_schema = self.generate_schema(keys_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
564 values_schema = self.generate_schema(values_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
566 dict_schema = core_schema.dict_schema(keys_schema, values_schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
567 check_instance = core_schema.json_or_python_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
568 json_schema=dict_schema,
569 python_schema=core_schema.is_instance_schema(tp),
570 )
572 if tp is collections.defaultdict: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
573 default_default_factory = get_defaultdict_default_default_factory(values_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
574 coerce_instance_wrap = partial( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
575 core_schema.no_info_wrap_validator_function,
576 partial(defaultdict_validator, default_default_factory=default_default_factory),
577 )
578 else:
579 coerce_instance_wrap = partial(core_schema.no_info_after_validator_function, MAPPING_ORIGIN_MAP[tp]) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
581 lax_schema = coerce_instance_wrap(dict_schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
582 schema = core_schema.lax_or_strict_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
583 lax_schema=lax_schema,
584 strict_schema=core_schema.union_schema([check_instance, lax_schema]),
585 serialization=core_schema.wrap_serializer_function_ser_schema(
586 lambda v, h: h(v), schema=dict_schema, info_arg=False
587 ),
588 )
590 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
592 def _fraction_schema(self) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
593 """Support for [`fractions.Fraction`][fractions.Fraction]."""
594 from ._validators import fraction_validator 1acekoquwxCfbhilmrsyzDEdjgnptvABF
596 # TODO: note, this is a fairly common pattern, re lax / strict for attempted type coercion,
597 # can we use a helper function to reduce boilerplate?
598 return core_schema.lax_or_strict_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
599 lax_schema=core_schema.no_info_plain_validator_function(fraction_validator),
600 strict_schema=core_schema.json_or_python_schema(
601 json_schema=core_schema.no_info_plain_validator_function(fraction_validator),
602 python_schema=core_schema.is_instance_schema(Fraction),
603 ),
604 # use str serialization to guarantee round trip behavior
605 serialization=core_schema.to_string_ser_schema(when_used='always'),
606 metadata={'pydantic_js_functions': [lambda _1, _2: {'type': 'string', 'format': 'fraction'}]},
607 )
609 def _arbitrary_type_schema(self, tp: Any) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
610 if not isinstance(tp, type): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
611 warn( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
612 f'{tp!r} is not a Python type (it may be an instance of an object),'
613 ' Pydantic will allow any object with no validation since we cannot even'
614 ' enforce that the input is an instance of the given type.'
615 ' To get rid of this error wrap the type with `pydantic.SkipValidation`.',
616 UserWarning,
617 )
618 return core_schema.any_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
619 return core_schema.is_instance_schema(tp) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
621 def _unknown_type_schema(self, obj: Any) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
622 raise PydanticSchemaGenerationError( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
623 f'Unable to generate pydantic-core schema for {obj!r}. '
624 'Set `arbitrary_types_allowed=True` in the model_config to ignore this error'
625 ' or implement `__get_pydantic_core_schema__` on your type to fully support it.'
626 '\n\nIf you got this error by calling handler(<some type>) within'
627 ' `__get_pydantic_core_schema__` then you likely need to call'
628 ' `handler.generate_schema(<some type>)` since we do not call'
629 ' `__get_pydantic_core_schema__` on `<some type>` otherwise to avoid infinite recursion.'
630 )
632 def _apply_discriminator_to_union( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
633 self, schema: CoreSchema, discriminator: str | Discriminator | None
634 ) -> CoreSchema:
635 if discriminator is None: 635 ↛ 636line 635 didn't jump to line 636 because the condition on line 635 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
636 return schema
637 try: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
638 return _discriminated_union.apply_discriminator( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
639 schema,
640 discriminator,
641 )
642 except _discriminated_union.MissingDefinitionForUnionRef: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
643 # defer until defs are resolved
644 _discriminated_union.set_discriminator_in_metadata( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
645 schema,
646 discriminator,
647 )
648 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
650 def clean_schema(self, schema: CoreSchema) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
651 schema = self.defs.finalize_schema(schema) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
652 schema = validate_core_schema(schema) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
653 return schema 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
655 def _add_js_function(self, metadata_schema: CoreSchema, js_function: Callable[..., Any]) -> None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
656 metadata = metadata_schema.get('metadata', {}) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
657 pydantic_js_functions = metadata.setdefault('pydantic_js_functions', []) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
658 # because of how we generate core schemas for nested generic models
659 # we can end up adding `BaseModel.__get_pydantic_json_schema__` multiple times
660 # this check may fail to catch duplicates if the function is a `functools.partial`
661 # or something like that, but if it does it'll fail by inserting the duplicate
662 if js_function not in pydantic_js_functions: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
663 pydantic_js_functions.append(js_function) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
664 metadata_schema['metadata'] = metadata 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
666 def generate_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
667 self,
668 obj: Any,
669 ) -> core_schema.CoreSchema:
670 """Generate core schema.
672 Args:
673 obj: The object to generate core schema for.
675 Returns:
676 The generated core schema.
678 Raises:
679 PydanticUndefinedAnnotation:
680 If it is not possible to evaluate forward reference.
681 PydanticSchemaGenerationError:
682 If it is not possible to generate pydantic-core schema.
683 TypeError:
684 - If `alias_generator` returns a disallowed type (must be str, AliasPath or AliasChoices).
685 - If V1 style validator with `each_item=True` applied on a wrong field.
686 PydanticUserError:
687 - If `typing.TypedDict` is used instead of `typing_extensions.TypedDict` on Python < 3.12.
688 - If `__modify_schema__` method is used instead of `__get_pydantic_json_schema__`.
689 """
690 schema = self._generate_schema_from_get_schema_method(obj, obj) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
692 if schema is None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
693 schema = self._generate_schema_inner(obj) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
695 metadata_js_function = _extract_get_pydantic_json_schema(obj) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
696 if metadata_js_function is not None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
697 metadata_schema = resolve_original_schema(schema, self.defs) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
698 if metadata_schema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
699 self._add_js_function(metadata_schema, metadata_js_function) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
701 schema = _add_custom_serialization_from_json_encoders(self._config_wrapper.json_encoders, obj, schema) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
703 return schema 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
705 def _model_schema(self, cls: type[BaseModel]) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
706 """Generate schema for a Pydantic model."""
707 BaseModel_ = import_cached_base_model() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
709 with self.defs.get_schema_or_ref(cls) as (model_ref, maybe_schema): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
710 if maybe_schema is not None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
711 return maybe_schema 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
713 schema = cls.__dict__.get('__pydantic_core_schema__') 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
714 if schema is not None and not isinstance(schema, MockCoreSchema): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
715 if schema['type'] == 'definitions': 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
716 schema = self.defs.unpack_definitions(schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
717 ref = get_ref(schema) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
718 if ref: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
719 return self.defs.create_definition_reference_schema(schema) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
720 else:
721 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
723 config_wrapper = ConfigWrapper(cls.model_config, check=False) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
725 with self._config_wrapper_stack.push(config_wrapper), self._ns_resolver.push(cls): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
726 core_config = self._config_wrapper.core_config(title=cls.__name__) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
728 if cls.__pydantic_fields_complete__ or cls is BaseModel_: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
729 fields = getattr(cls, '__pydantic_fields__', {}) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
730 else:
731 try: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
732 fields = rebuild_model_fields( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
733 cls,
734 ns_resolver=self._ns_resolver,
735 typevars_map=self._typevars_map or {},
736 )
737 except NameError as e: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
738 raise PydanticUndefinedAnnotation.from_name_error(e) from e 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
740 decorators = cls.__pydantic_decorators__ 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
741 computed_fields = decorators.computed_fields 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
742 check_decorator_fields_exist( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
743 chain(
744 decorators.field_validators.values(),
745 decorators.field_serializers.values(),
746 decorators.validators.values(),
747 ),
748 {*fields.keys(), *computed_fields.keys()},
749 )
751 model_validators = decorators.model_validators.values() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
753 extras_schema = None 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
754 if core_config.get('extra_fields_behavior') == 'allow': 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
755 assert cls.__mro__[0] is cls 1acekoquwxCfbhilmrsyzDEdjgnptvABF
756 assert cls.__mro__[-1] is object 1acekoquwxCfbhilmrsyzDEdjgnptvABF
757 for candidate_cls in cls.__mro__[:-1]: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
758 extras_annotation = getattr(candidate_cls, '__annotations__', {}).get( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
759 '__pydantic_extra__', None
760 )
761 if extras_annotation is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
762 if isinstance(extras_annotation, str): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
763 extras_annotation = _typing_extra.eval_type_backport( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
764 _typing_extra._make_forward_ref(
765 extras_annotation, is_argument=False, is_class=True
766 ),
767 *self._types_namespace,
768 )
769 tp = get_origin(extras_annotation) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
770 if tp not in DICT_TYPES: 770 ↛ 771line 770 didn't jump to line 771 because the condition on line 770 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
771 raise PydanticSchemaGenerationError(
772 'The type annotation for `__pydantic_extra__` must be `dict[str, ...]`'
773 )
774 extra_items_type = self._get_args_resolving_forward_refs( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
775 extras_annotation,
776 required=True,
777 )[1]
778 if not _typing_extra.is_any(extra_items_type): 778 ↛ 757line 778 didn't jump to line 757 because the condition on line 778 was always true1acekoquwxCfbhilmrsyzDEdjgnptvABF
779 extras_schema = self.generate_schema(extra_items_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
780 break 1acekoquwxCfbhilmrsyzDEdjgnptvABF
782 generic_origin: type[BaseModel] | None = getattr(cls, '__pydantic_generic_metadata__', {}).get('origin') 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
784 if cls.__pydantic_root_model__: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
785 root_field = self._common_field_schema('root', fields['root'], decorators) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
786 inner_schema = root_field['schema'] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
787 inner_schema = apply_model_validators(inner_schema, model_validators, 'inner') 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
788 model_schema = core_schema.model_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
789 cls,
790 inner_schema,
791 generic_origin=generic_origin,
792 custom_init=getattr(cls, '__pydantic_custom_init__', None),
793 root_model=True,
794 post_init=getattr(cls, '__pydantic_post_init__', None),
795 config=core_config,
796 ref=model_ref,
797 )
798 else:
799 fields_schema: core_schema.CoreSchema = core_schema.model_fields_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
800 {k: self._generate_md_field_schema(k, v, decorators) for k, v in fields.items()},
801 computed_fields=[
802 self._computed_field_schema(d, decorators.field_serializers)
803 for d in computed_fields.values()
804 ],
805 extras_schema=extras_schema,
806 model_name=cls.__name__,
807 )
808 inner_schema = apply_validators(fields_schema, decorators.root_validators.values(), None) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
809 inner_schema = apply_model_validators(inner_schema, model_validators, 'inner') 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
811 model_schema = core_schema.model_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
812 cls,
813 inner_schema,
814 generic_origin=generic_origin,
815 custom_init=getattr(cls, '__pydantic_custom_init__', None),
816 root_model=False,
817 post_init=getattr(cls, '__pydantic_post_init__', None),
818 config=core_config,
819 ref=model_ref,
820 )
822 schema = self._apply_model_serializers(model_schema, decorators.model_serializers.values()) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
823 schema = apply_model_validators(schema, model_validators, 'outer') 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
824 return self.defs.create_definition_reference_schema(schema) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
826 def _resolve_self_type(self, obj: Any) -> Any: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
827 obj = self.model_type_stack.get() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
828 if obj is None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
829 raise PydanticUserError('`typing.Self` is invalid in this context', code='invalid-self-type') 1acekoquwxCfbhilmrsyzDEdjgnptvABF
830 return obj 1acekoquwxCfbhilmrsyzDEdjgnptvABF
832 def _generate_schema_from_get_schema_method(self, obj: Any, source: Any) -> core_schema.CoreSchema | None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
833 BaseModel_ = import_cached_base_model() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
835 get_schema = getattr(obj, '__get_pydantic_core_schema__', None) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
836 is_base_model_get_schema = ( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
837 getattr(get_schema, '__func__', None) is BaseModel_.__get_pydantic_core_schema__.__func__ # pyright: ignore[reportFunctionMemberAccess]
838 )
840 if ( 1acfbhiLdj
841 get_schema is not None
842 # BaseModel.__get_pydantic_core_schema__ is defined for backwards compatibility,
843 # to allow existing code to call `super().__get_pydantic_core_schema__` in Pydantic
844 # model that overrides `__get_pydantic_core_schema__`. However, it raises a deprecation
845 # warning stating that the method will be removed, and during the core schema gen we actually
846 # don't call the method:
847 and not is_base_model_get_schema
848 ):
849 # Some referenceable types might have a `__get_pydantic_core_schema__` method
850 # defined on it by users (e.g. on a dataclass). This generally doesn't play well
851 # as these types are already recognized by the `GenerateSchema` class and isn't ideal
852 # as we might end up calling `get_schema_or_ref` (expensive) on types that are actually
853 # not referenceable:
854 with self.defs.get_schema_or_ref(obj) as (_, maybe_schema): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
855 if maybe_schema is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
856 return maybe_schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
858 if obj is source: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
859 ref_mode = 'unpack' 1acekoquwxCfbhilmrsyzDEdjgnptvABF
860 else:
861 ref_mode = 'to-def' 1acekoquwxCfbhilmrsyzDEdjgnptvABF
862 schema = get_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
863 source, CallbackGetCoreSchemaHandler(self._generate_schema_inner, self, ref_mode=ref_mode)
864 )
865 if schema['type'] == 'definitions': 865 ↛ 866line 865 didn't jump to line 866 because the condition on line 865 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
866 schema = self.defs.unpack_definitions(schema)
868 ref = get_ref(schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
869 if ref: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
870 return self.defs.create_definition_reference_schema(schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
872 # Note: if schema is of type `'definition-ref'`, we might want to copy it as a
873 # safety measure (because these are inlined in place -- i.e. mutated directly)
874 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
876 if (validators := getattr(obj, '__get_validators__', None)) is not None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
877 from pydantic.v1 import BaseModel as BaseModelV1 1acekoquwxCfbhilmrsyzDEdjgnptvABF
879 if issubclass(obj, BaseModelV1): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
880 warn( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
881 f'Mixing V1 models and V2 models (or constructs, like `TypeAdapter`) is not supported. Please upgrade `{obj.__name__}` to V2.',
882 UserWarning,
883 )
884 else:
885 warn( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
886 '`__get_validators__` is deprecated and will be removed, use `__get_pydantic_core_schema__` instead.',
887 PydanticDeprecatedSince20,
888 )
889 return core_schema.chain_schema([core_schema.with_info_plain_validator_function(v) for v in validators()]) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
891 def _resolve_forward_ref(self, obj: Any) -> Any: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
892 # we assume that types_namespace has the target of forward references in its scope,
893 # but this could fail, for example, if calling Validator on an imported type which contains
894 # forward references to other types only defined in the module from which it was imported
895 # `Validator(SomeImportedTypeAliasWithAForwardReference)`
896 # or the equivalent for BaseModel
897 # class Model(BaseModel):
898 # x: SomeImportedTypeAliasWithAForwardReference
899 try: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
900 obj = _typing_extra.eval_type_backport(obj, *self._types_namespace) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
901 except NameError as e: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
902 raise PydanticUndefinedAnnotation.from_name_error(e) from e 1acekoquwxCfbhilmrsyzDEdjgnptvABF
904 # if obj is still a ForwardRef, it means we can't evaluate it, raise PydanticUndefinedAnnotation
905 if isinstance(obj, ForwardRef): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
906 raise PydanticUndefinedAnnotation(obj.__forward_arg__, f'Unable to evaluate forward reference {obj}') 1acekoquwxCfbhilmrsyzDEdjgnptvABF
908 if self._typevars_map: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
909 obj = replace_types(obj, self._typevars_map) 1acekfbhilmdjgn
911 return obj 1acekoquwxCfbhilmrsyzDEdjgnptvABF
913 @overload 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
914 def _get_args_resolving_forward_refs(self, obj: Any, required: Literal[True]) -> tuple[Any, ...]: ... 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
916 @overload 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
917 def _get_args_resolving_forward_refs(self, obj: Any) -> tuple[Any, ...] | None: ... 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
919 def _get_args_resolving_forward_refs(self, obj: Any, required: bool = False) -> tuple[Any, ...] | None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
920 args = get_args(obj) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
921 if args: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
922 if isinstance(obj, GenericAlias): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
923 # PEP 585 generic aliases don't convert args to ForwardRefs, unlike `typing.List/Dict` etc.
924 args = (_typing_extra._make_forward_ref(a) if isinstance(a, str) else a for a in args) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
925 args = tuple(self._resolve_forward_ref(a) if isinstance(a, ForwardRef) else a for a in args) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
926 elif required: # pragma: no cover 1acekoquwxCfbhilmrsyzDEdjgnptvABF
927 raise TypeError(f'Expected {obj} to have generic parameters but it had none')
928 return args 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
930 def _get_first_arg_or_any(self, obj: Any) -> Any: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
931 args = self._get_args_resolving_forward_refs(obj) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
932 if not args: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
933 return Any 1acekoquwxCfbhilmrsyzDEdjgnptvABF
934 return args[0] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
936 def _get_first_two_args_or_any(self, obj: Any) -> tuple[Any, Any]: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
937 args = self._get_args_resolving_forward_refs(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
938 if not args: 938 ↛ 939line 938 didn't jump to line 939 because the condition on line 938 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
939 return (Any, Any)
940 if len(args) < 2: 940 ↛ 941line 940 didn't jump to line 941 because the condition on line 940 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
941 origin = get_origin(obj)
942 raise TypeError(f'Expected two type arguments for {origin}, got 1')
943 return args[0], args[1] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
945 def _generate_schema_inner(self, obj: Any) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
946 if _typing_extra.is_self(obj): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
947 obj = self._resolve_self_type(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
949 if _typing_extra.is_annotated(obj): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
950 return self._annotated_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
952 if isinstance(obj, dict): 952 ↛ 954line 952 didn't jump to line 954 because the condition on line 952 was never true1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
953 # we assume this is already a valid schema
954 return obj # type: ignore[return-value]
956 if isinstance(obj, str): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
957 obj = ForwardRef(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
959 if isinstance(obj, ForwardRef): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
960 return self.generate_schema(self._resolve_forward_ref(obj)) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
962 BaseModel = import_cached_base_model() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
964 if lenient_issubclass(obj, BaseModel): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
965 with self.model_type_stack.push(obj): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
966 return self._model_schema(obj) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
968 if isinstance(obj, PydanticRecursiveRef): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
969 return core_schema.definition_reference_schema(schema_ref=obj.type_ref) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
971 return self.match_type(obj) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
973 def match_type(self, obj: Any) -> core_schema.CoreSchema: # noqa: C901 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
974 """Main mapping of types to schemas.
976 The general structure is a series of if statements starting with the simple cases
977 (non-generic primitive types) and then handling generics and other more complex cases.
979 Each case either generates a schema directly, calls into a public user-overridable method
980 (like `GenerateSchema.tuple_variable_schema`) or calls into a private method that handles some
981 boilerplate before calling into the user-facing method (e.g. `GenerateSchema._tuple_schema`).
983 The idea is that we'll evolve this into adding more and more user facing methods over time
984 as they get requested and we figure out what the right API for them is.
985 """
986 if obj is str: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
987 return core_schema.str_schema() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
988 elif obj is bytes: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
989 return core_schema.bytes_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
990 elif obj is int: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
991 return core_schema.int_schema() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
992 elif obj is float: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
993 return core_schema.float_schema() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
994 elif obj is bool: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
995 return core_schema.bool_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
996 elif obj is complex: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
997 return core_schema.complex_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
998 elif _typing_extra.is_any(obj) or obj is object: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
999 return core_schema.any_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1000 elif obj is datetime.date: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1001 return core_schema.date_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1002 elif obj is datetime.datetime: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1003 return core_schema.datetime_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1004 elif obj is datetime.time: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1005 return core_schema.time_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1006 elif obj is datetime.timedelta: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1007 return core_schema.timedelta_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1008 elif obj is Decimal: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1009 return core_schema.decimal_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1010 elif obj is UUID: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1011 return core_schema.uuid_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1012 elif obj is Url: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1013 return core_schema.url_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1014 elif obj is Fraction: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1015 return self._fraction_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1016 elif obj is MultiHostUrl: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1017 return core_schema.multi_host_url_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1018 elif obj is None or obj is _typing_extra.NoneType: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1019 return core_schema.none_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1020 elif obj in IP_TYPES: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1021 return self._ip_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1022 elif obj in TUPLE_TYPES: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1023 return self._tuple_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1024 elif obj in LIST_TYPES: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1025 return self._list_schema(Any) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1026 elif obj in SET_TYPES: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1027 return self._set_schema(Any) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1028 elif obj in FROZEN_SET_TYPES: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1029 return self._frozenset_schema(Any) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1030 elif obj in SEQUENCE_TYPES: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1031 return self._sequence_schema(Any) 1aeouxdgpvB
1032 elif obj in ITERABLE_TYPES: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1033 return self._iterable_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1034 elif obj in DICT_TYPES: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1035 return self._dict_schema(Any, Any) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1036 elif obj in PATH_TYPES: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1037 return self._path_schema(obj, Any) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1038 elif obj in DEQUE_TYPES: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1039 return self._deque_schema(Any) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1040 elif obj in MAPPING_TYPES: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1041 return self._mapping_schema(obj, Any, Any) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1042 elif obj in COUNTER_TYPES: 1042 ↛ 1043line 1042 didn't jump to line 1043 because the condition on line 1042 was never true1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1043 return self._mapping_schema(obj, Any, int)
1044 elif _typing_extra.is_type_alias_type(obj): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1045 return self._type_alias_type_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1046 elif obj is type: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1047 return self._type_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1048 elif _typing_extra.is_callable(obj): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1049 return core_schema.callable_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1050 elif _typing_extra.is_literal(obj): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1051 return self._literal_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1052 elif is_typeddict(obj): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1053 return self._typed_dict_schema(obj, None) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1054 elif _typing_extra.is_namedtuple(obj): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1055 return self._namedtuple_schema(obj, None) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1056 elif _typing_extra.is_new_type(obj): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1057 # NewType, can't use isinstance because it fails <3.10
1058 return self.generate_schema(obj.__supertype__) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1059 elif obj in PATTERN_TYPES: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1060 return self._pattern_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1061 elif _typing_extra.is_hashable(obj): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1062 return self._hashable_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1063 elif isinstance(obj, typing.TypeVar): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1064 return self._unsubstituted_typevar_schema(obj) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1065 elif _typing_extra.is_finalvar(obj): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1066 if obj is Final: 1066 ↛ 1068line 1066 didn't jump to line 1068 because the condition on line 1066 was always true1acekoquwxCfbhilmrsyzDEdjgnptvABF
1067 return core_schema.any_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1068 return self.generate_schema(
1069 self._get_first_arg_or_any(obj),
1070 )
1071 elif isinstance(obj, VALIDATE_CALL_SUPPORTED_TYPES): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1072 return self._call_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1073 elif inspect.isclass(obj) and issubclass(obj, Enum): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1074 return self._enum_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1075 elif _typing_extra.is_zoneinfo_type(obj): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1076 return self._zoneinfo_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1078 # dataclasses.is_dataclass coerces dc instances to types, but we only handle
1079 # the case of a dc type here
1080 if dataclasses.is_dataclass(obj): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1081 return self._dataclass_schema(obj, None) # pyright: ignore[reportArgumentType] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1083 origin = get_origin(obj) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1084 if origin is not None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1085 return self._match_generic_type(obj, origin) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1087 if self._arbitrary_types: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1088 return self._arbitrary_type_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1089 return self._unknown_type_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1091 def _match_generic_type(self, obj: Any, origin: Any) -> CoreSchema: # noqa: C901 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1092 # Need to handle generic dataclasses before looking for the schema properties because attribute accesses
1093 # on _GenericAlias delegate to the origin type, so lose the information about the concrete parametrization
1094 # As a result, currently, there is no way to cache the schema for generic dataclasses. This may be possible
1095 # to resolve by modifying the value returned by `Generic.__class_getitem__`, but that is a dangerous game.
1096 if dataclasses.is_dataclass(origin): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1097 return self._dataclass_schema(obj, origin) # pyright: ignore[reportArgumentType] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1098 if _typing_extra.is_namedtuple(origin): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1099 return self._namedtuple_schema(obj, origin) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1101 schema = self._generate_schema_from_get_schema_method(origin, obj) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1102 if schema is not None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1103 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1105 if _typing_extra.is_type_alias_type(origin): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1106 return self._type_alias_type_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1107 elif _typing_extra.origin_is_union(origin): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1108 return self._union_schema(obj) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1109 elif origin in TUPLE_TYPES: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1110 return self._tuple_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1111 elif origin in LIST_TYPES: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1112 return self._list_schema(self._get_first_arg_or_any(obj)) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1113 elif origin in SET_TYPES: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1114 return self._set_schema(self._get_first_arg_or_any(obj)) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1115 elif origin in FROZEN_SET_TYPES: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1116 return self._frozenset_schema(self._get_first_arg_or_any(obj)) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1117 elif origin in DICT_TYPES: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1118 return self._dict_schema(*self._get_first_two_args_or_any(obj)) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1119 elif origin in PATH_TYPES: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1120 return self._path_schema(origin, self._get_first_arg_or_any(obj)) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1121 elif origin in DEQUE_TYPES: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1122 return self._deque_schema(self._get_first_arg_or_any(obj)) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1123 elif origin in MAPPING_TYPES: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1124 return self._mapping_schema(origin, *self._get_first_two_args_or_any(obj)) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1125 elif origin in COUNTER_TYPES: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1126 return self._mapping_schema(origin, self._get_first_arg_or_any(obj), int) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1127 elif is_typeddict(origin): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1128 return self._typed_dict_schema(obj, origin) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1129 elif origin in TYPE_TYPES: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1130 return self._subclass_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1131 elif origin in SEQUENCE_TYPES: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1132 return self._sequence_schema(self._get_first_arg_or_any(obj)) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1133 elif origin in ITERABLE_TYPES: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1134 return self._iterable_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1135 elif origin in PATTERN_TYPES: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1136 return self._pattern_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1138 if self._arbitrary_types: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1139 return self._arbitrary_type_schema(origin) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1140 return self._unknown_type_schema(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1142 def _generate_td_field_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1143 self,
1144 name: str,
1145 field_info: FieldInfo,
1146 decorators: DecoratorInfos,
1147 *,
1148 required: bool = True,
1149 ) -> core_schema.TypedDictField:
1150 """Prepare a TypedDictField to represent a model or typeddict field."""
1151 common_field = self._common_field_schema(name, field_info, decorators) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1152 return core_schema.typed_dict_field( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1153 common_field['schema'],
1154 required=False if not field_info.is_required() else required,
1155 serialization_exclude=common_field['serialization_exclude'],
1156 validation_alias=common_field['validation_alias'],
1157 serialization_alias=common_field['serialization_alias'],
1158 metadata=common_field['metadata'],
1159 )
1161 def _generate_md_field_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1162 self,
1163 name: str,
1164 field_info: FieldInfo,
1165 decorators: DecoratorInfos,
1166 ) -> core_schema.ModelField:
1167 """Prepare a ModelField to represent a model field."""
1168 common_field = self._common_field_schema(name, field_info, decorators) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1169 return core_schema.model_field( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1170 common_field['schema'],
1171 serialization_exclude=common_field['serialization_exclude'],
1172 validation_alias=common_field['validation_alias'],
1173 serialization_alias=common_field['serialization_alias'],
1174 frozen=common_field['frozen'],
1175 metadata=common_field['metadata'],
1176 )
1178 def _generate_dc_field_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1179 self,
1180 name: str,
1181 field_info: FieldInfo,
1182 decorators: DecoratorInfos,
1183 ) -> core_schema.DataclassField:
1184 """Prepare a DataclassField to represent the parameter/field, of a dataclass."""
1185 common_field = self._common_field_schema(name, field_info, decorators) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1186 return core_schema.dataclass_field( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1187 name,
1188 common_field['schema'],
1189 init=field_info.init,
1190 init_only=field_info.init_var or None,
1191 kw_only=None if field_info.kw_only else False,
1192 serialization_exclude=common_field['serialization_exclude'],
1193 validation_alias=common_field['validation_alias'],
1194 serialization_alias=common_field['serialization_alias'],
1195 frozen=common_field['frozen'],
1196 metadata=common_field['metadata'],
1197 )
1199 @staticmethod 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1200 def _apply_alias_generator_to_field_info( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1201 alias_generator: Callable[[str], str] | AliasGenerator, field_info: FieldInfo, field_name: str
1202 ) -> None:
1203 """Apply an alias_generator to aliases on a FieldInfo instance if appropriate.
1205 Args:
1206 alias_generator: A callable that takes a string and returns a string, or an AliasGenerator instance.
1207 field_info: The FieldInfo instance to which the alias_generator is (maybe) applied.
1208 field_name: The name of the field from which to generate the alias.
1209 """
1210 # Apply an alias_generator if
1211 # 1. An alias is not specified
1212 # 2. An alias is specified, but the priority is <= 1
1213 if ( 1acfbhidj
1214 field_info.alias_priority is None
1215 or field_info.alias_priority <= 1
1216 or field_info.alias is None
1217 or field_info.validation_alias is None
1218 or field_info.serialization_alias is None
1219 ):
1220 alias, validation_alias, serialization_alias = None, None, None 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1222 if isinstance(alias_generator, AliasGenerator): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1223 alias, validation_alias, serialization_alias = alias_generator.generate_aliases(field_name) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1224 elif isinstance(alias_generator, Callable): 1224 ↛ 1232line 1224 didn't jump to line 1232 because the condition on line 1224 was always true1acekoquwxCfbhilmrsyzDEdjgnptvABF
1225 alias = alias_generator(field_name) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1226 if not isinstance(alias, str): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1227 raise TypeError(f'alias_generator {alias_generator} must return str, not {alias.__class__}') 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1229 # if priority is not set, we set to 1
1230 # which supports the case where the alias_generator from a child class is used
1231 # to generate an alias for a field in a parent class
1232 if field_info.alias_priority is None or field_info.alias_priority <= 1: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1233 field_info.alias_priority = 1 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1235 # if the priority is 1, then we set the aliases to the generated alias
1236 if field_info.alias_priority == 1: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1237 field_info.serialization_alias = _get_first_non_null(serialization_alias, alias) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1238 field_info.validation_alias = _get_first_non_null(validation_alias, alias) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1239 field_info.alias = alias 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1241 # if any of the aliases are not set, then we set them to the corresponding generated alias
1242 if field_info.alias is None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1243 field_info.alias = alias 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1244 if field_info.serialization_alias is None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1245 field_info.serialization_alias = _get_first_non_null(serialization_alias, alias) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1246 if field_info.validation_alias is None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1247 field_info.validation_alias = _get_first_non_null(validation_alias, alias) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1249 @staticmethod 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1250 def _apply_alias_generator_to_computed_field_info( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1251 alias_generator: Callable[[str], str] | AliasGenerator,
1252 computed_field_info: ComputedFieldInfo,
1253 computed_field_name: str,
1254 ):
1255 """Apply an alias_generator to alias on a ComputedFieldInfo instance if appropriate.
1257 Args:
1258 alias_generator: A callable that takes a string and returns a string, or an AliasGenerator instance.
1259 computed_field_info: The ComputedFieldInfo instance to which the alias_generator is (maybe) applied.
1260 computed_field_name: The name of the computed field from which to generate the alias.
1261 """
1262 # Apply an alias_generator if
1263 # 1. An alias is not specified
1264 # 2. An alias is specified, but the priority is <= 1
1266 if ( 1acfb
1267 computed_field_info.alias_priority is None
1268 or computed_field_info.alias_priority <= 1
1269 or computed_field_info.alias is None
1270 ):
1271 alias, validation_alias, serialization_alias = None, None, None 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1273 if isinstance(alias_generator, AliasGenerator): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1274 alias, validation_alias, serialization_alias = alias_generator.generate_aliases(computed_field_name) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1275 elif isinstance(alias_generator, Callable): 1275 ↛ 1283line 1275 didn't jump to line 1283 because the condition on line 1275 was always true1acekoquwxCfbhilmrsyzDEdjgnptvABF
1276 alias = alias_generator(computed_field_name) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1277 if not isinstance(alias, str): 1277 ↛ 1278line 1277 didn't jump to line 1278 because the condition on line 1277 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
1278 raise TypeError(f'alias_generator {alias_generator} must return str, not {alias.__class__}')
1280 # if priority is not set, we set to 1
1281 # which supports the case where the alias_generator from a child class is used
1282 # to generate an alias for a field in a parent class
1283 if computed_field_info.alias_priority is None or computed_field_info.alias_priority <= 1: 1283 ↛ 1289line 1283 didn't jump to line 1289 because the condition on line 1283 was always true1acekoquwxCfbhilmrsyzDEdjgnptvABF
1284 computed_field_info.alias_priority = 1 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1286 # if the priority is 1, then we set the aliases to the generated alias
1287 # note that we use the serialization_alias with priority over alias, as computed_field
1288 # aliases are used for serialization only (not validation)
1289 if computed_field_info.alias_priority == 1: 1289 ↛ exitline 1289 didn't return from function '_apply_alias_generator_to_computed_field_info' because the condition on line 1289 was always true1acekoquwxCfbhilmrsyzDEdjgnptvABF
1290 computed_field_info.alias = _get_first_non_null(serialization_alias, alias) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1292 @staticmethod 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1293 def _apply_field_title_generator_to_field_info( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1294 config_wrapper: ConfigWrapper, field_info: FieldInfo | ComputedFieldInfo, field_name: str
1295 ) -> None:
1296 """Apply a field_title_generator on a FieldInfo or ComputedFieldInfo instance if appropriate
1297 Args:
1298 config_wrapper: The config of the model
1299 field_info: The FieldInfo or ComputedField instance to which the title_generator is (maybe) applied.
1300 field_name: The name of the field from which to generate the title.
1301 """
1302 field_title_generator = field_info.field_title_generator or config_wrapper.field_title_generator 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1304 if field_title_generator is None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1305 return 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1307 if field_info.title is None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1308 title = field_title_generator(field_name, field_info) # type: ignore 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1309 if not isinstance(title, str): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1310 raise TypeError(f'field_title_generator {field_title_generator} must return str, not {title.__class__}') 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1312 field_info.title = title 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1314 def _common_field_schema( # C901 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1315 self, name: str, field_info: FieldInfo, decorators: DecoratorInfos
1316 ) -> _CommonField:
1317 source_type, annotations = field_info.annotation, field_info.metadata 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1319 def set_discriminator(schema: CoreSchema) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1320 schema = self._apply_discriminator_to_union(schema, field_info.discriminator) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1321 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1323 # Convert `@field_validator` decorators to `Before/After/Plain/WrapValidator` instances:
1324 validators_from_decorators = [] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1325 for decorator in filter_field_decorator_info_by_field(decorators.field_validators.values(), name): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1326 validators_from_decorators.append(_mode_to_validator[decorator.info.mode]._from_decorator(decorator)) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1328 with self.field_name_stack.push(name): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1329 if field_info.discriminator is not None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1330 schema = self._apply_annotations( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1331 source_type, annotations + validators_from_decorators, transform_inner_schema=set_discriminator
1332 )
1333 else:
1334 schema = self._apply_annotations( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1335 source_type,
1336 annotations + validators_from_decorators,
1337 )
1339 # This V1 compatibility shim should eventually be removed
1340 # push down any `each_item=True` validators
1341 # note that this won't work for any Annotated types that get wrapped by a function validator
1342 # but that's okay because that didn't exist in V1
1343 this_field_validators = filter_field_decorator_info_by_field(decorators.validators.values(), name) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1344 if _validators_require_validate_default(this_field_validators): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1345 field_info.validate_default = True 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1346 each_item_validators = [v for v in this_field_validators if v.info.each_item is True] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1347 this_field_validators = [v for v in this_field_validators if v not in each_item_validators] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1348 schema = apply_each_item_validators(schema, each_item_validators, name) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1350 schema = apply_validators(schema, this_field_validators, name) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1352 # the default validator needs to go outside of any other validators
1353 # so that it is the topmost validator for the field validator
1354 # which uses it to check if the field has a default value or not
1355 if not field_info.is_required(): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1356 schema = wrap_default(field_info, schema) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1358 schema = self._apply_field_serializers( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1359 schema, filter_field_decorator_info_by_field(decorators.field_serializers.values(), name)
1360 )
1361 self._apply_field_title_generator_to_field_info(self._config_wrapper, field_info, name) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1363 pydantic_js_updates, pydantic_js_extra = _extract_json_schema_info_from_field_info(field_info) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1364 core_metadata: dict[str, Any] = {} 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1365 update_core_metadata( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1366 core_metadata, pydantic_js_updates=pydantic_js_updates, pydantic_js_extra=pydantic_js_extra
1367 )
1369 alias_generator = self._config_wrapper.alias_generator 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1370 if alias_generator is not None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1371 self._apply_alias_generator_to_field_info(alias_generator, field_info, name) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1373 if isinstance(field_info.validation_alias, (AliasChoices, AliasPath)): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1374 validation_alias = field_info.validation_alias.convert_to_aliases() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1375 else:
1376 validation_alias = field_info.validation_alias 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1378 return _common_field( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1379 schema,
1380 serialization_exclude=True if field_info.exclude else None,
1381 validation_alias=validation_alias,
1382 serialization_alias=field_info.serialization_alias,
1383 frozen=field_info.frozen,
1384 metadata=core_metadata,
1385 )
1387 def _union_schema(self, union_type: Any) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1388 """Generate schema for a Union."""
1389 args = self._get_args_resolving_forward_refs(union_type, required=True) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1390 choices: list[CoreSchema] = [] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1391 nullable = False 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1392 for arg in args: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1393 if arg is None or arg is _typing_extra.NoneType: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1394 nullable = True 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1395 else:
1396 choices.append(self.generate_schema(arg)) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1398 if len(choices) == 1: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1399 s = choices[0] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1400 else:
1401 choices_with_tags: list[CoreSchema | tuple[CoreSchema, str]] = [] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1402 for choice in choices: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1403 tag = cast(CoreMetadata, choice.get('metadata', {})).get('pydantic_internal_union_tag_key') 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1404 if tag is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1405 choices_with_tags.append((choice, tag)) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1406 else:
1407 choices_with_tags.append(choice) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1408 s = core_schema.union_schema(choices_with_tags) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1410 if nullable: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1411 s = core_schema.nullable_schema(s) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1412 return s 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1414 def _type_alias_type_schema(self, obj: TypeAliasType) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1415 with self.defs.get_schema_or_ref(obj) as (ref, maybe_schema): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1416 if maybe_schema is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1417 return maybe_schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1419 origin: TypeAliasType = get_origin(obj) or obj 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1420 typevars_map = get_standard_typevars_map(obj) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1422 with self._ns_resolver.push(origin): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1423 try: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1424 annotation = _typing_extra.eval_type(origin.__value__, *self._types_namespace) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1425 except NameError as e:
1426 raise PydanticUndefinedAnnotation.from_name_error(e) from e
1427 annotation = replace_types(annotation, typevars_map) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1428 schema = self.generate_schema(annotation) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1429 assert schema['type'] != 'definitions' 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1430 schema['ref'] = ref # type: ignore 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1431 return self.defs.create_definition_reference_schema(schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1433 def _literal_schema(self, literal_type: Any) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1434 """Generate schema for a Literal."""
1435 expected = _typing_extra.literal_values(literal_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1436 assert expected, f'literal "expected" cannot be empty, obj={literal_type}' 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1437 schema = core_schema.literal_schema(expected) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1439 if self._config_wrapper.use_enum_values and any(isinstance(v, Enum) for v in expected): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1440 schema = core_schema.no_info_after_validator_function( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1441 lambda v: v.value if isinstance(v, Enum) else v, schema
1442 )
1444 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1446 def _typed_dict_schema(self, typed_dict_cls: Any, origin: Any) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1447 """Generate schema for a TypedDict.
1449 It is not possible to track required/optional keys in TypedDict without __required_keys__
1450 since TypedDict.__new__ erases the base classes (it replaces them with just `dict`)
1451 and thus we can track usage of total=True/False
1452 __required_keys__ was added in Python 3.9
1453 (https://github.com/miss-islington/cpython/blob/1e9939657dd1f8eb9f596f77c1084d2d351172fc/Doc/library/typing.rst?plain=1#L1546-L1548)
1454 however it is buggy
1455 (https://github.com/python/typing_extensions/blob/ac52ac5f2cb0e00e7988bae1e2a1b8257ac88d6d/src/typing_extensions.py#L657-L666).
1457 On 3.11 but < 3.12 TypedDict does not preserve inheritance information.
1459 Hence to avoid creating validators that do not do what users expect we only
1460 support typing.TypedDict on Python >= 3.12 or typing_extension.TypedDict on all versions
1461 """
1462 FieldInfo = import_cached_field_info() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1464 with ( 1acekoqfbhilmrsdjgnpt
1465 self.model_type_stack.push(typed_dict_cls),
1466 self.defs.get_schema_or_ref(typed_dict_cls) as (
1467 typed_dict_ref,
1468 maybe_schema,
1469 ),
1470 ):
1471 if maybe_schema is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1472 return maybe_schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1474 typevars_map = get_standard_typevars_map(typed_dict_cls) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1475 if origin is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1476 typed_dict_cls = origin 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1478 if not _SUPPORTS_TYPEDDICT and type(typed_dict_cls).__module__ == 'typing': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1479 raise PydanticUserError( 1acekoqfbhilmrsdjgnpt
1480 'Please use `typing_extensions.TypedDict` instead of `typing.TypedDict` on Python < 3.12.',
1481 code='typed-dict-version',
1482 )
1484 try: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1485 # if a typed dictionary class doesn't have config, we use the parent's config, hence a default of `None`
1486 # see https://github.com/pydantic/pydantic/issues/10917
1487 config: ConfigDict | None = get_attribute_from_bases(typed_dict_cls, '__pydantic_config__') 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1488 except AttributeError: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1489 config = None 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1491 with self._config_wrapper_stack.push(config): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1492 core_config = self._config_wrapper.core_config(title=typed_dict_cls.__name__) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1494 required_keys: frozenset[str] = typed_dict_cls.__required_keys__ 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1496 fields: dict[str, core_schema.TypedDictField] = {} 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1498 decorators = DecoratorInfos.build(typed_dict_cls) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1500 if self._config_wrapper.use_attribute_docstrings: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1501 field_docstrings = extract_docstrings_from_cls(typed_dict_cls, use_inspect=True) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1502 else:
1503 field_docstrings = None 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1505 try: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1506 annotations = _typing_extra.get_cls_type_hints(typed_dict_cls, ns_resolver=self._ns_resolver) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1507 except NameError as e:
1508 raise PydanticUndefinedAnnotation.from_name_error(e) from e
1510 for field_name, annotation in annotations.items(): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1511 annotation = replace_types(annotation, typevars_map) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1512 required = field_name in required_keys 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1514 if _typing_extra.is_required(annotation): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1515 required = True 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1516 annotation = self._get_args_resolving_forward_refs( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1517 annotation,
1518 required=True,
1519 )[0]
1520 elif _typing_extra.is_not_required(annotation): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1521 required = False 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1522 annotation = self._get_args_resolving_forward_refs( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1523 annotation,
1524 required=True,
1525 )[0]
1527 field_info = FieldInfo.from_annotation(annotation) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1528 if ( 1acfbhidj
1529 field_docstrings is not None
1530 and field_info.description is None
1531 and field_name in field_docstrings
1532 ):
1533 field_info.description = field_docstrings[field_name] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1534 self._apply_field_title_generator_to_field_info(self._config_wrapper, field_info, field_name) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1535 fields[field_name] = self._generate_td_field_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1536 field_name, field_info, decorators, required=required
1537 )
1539 td_schema = core_schema.typed_dict_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1540 fields,
1541 cls=typed_dict_cls,
1542 computed_fields=[
1543 self._computed_field_schema(d, decorators.field_serializers)
1544 for d in decorators.computed_fields.values()
1545 ],
1546 ref=typed_dict_ref,
1547 config=core_config,
1548 )
1550 schema = self._apply_model_serializers(td_schema, decorators.model_serializers.values()) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1551 schema = apply_model_validators(schema, decorators.model_validators.values(), 'all') 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1552 return self.defs.create_definition_reference_schema(schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1554 def _namedtuple_schema(self, namedtuple_cls: Any, origin: Any) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1555 """Generate schema for a NamedTuple."""
1556 with ( 1acekoqfbhilmrsdjgnpt
1557 self.model_type_stack.push(namedtuple_cls),
1558 self.defs.get_schema_or_ref(namedtuple_cls) as (
1559 namedtuple_ref,
1560 maybe_schema,
1561 ),
1562 ):
1563 if maybe_schema is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1564 return maybe_schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1565 typevars_map = get_standard_typevars_map(namedtuple_cls) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1566 if origin is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1567 namedtuple_cls = origin 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1569 try: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1570 annotations = _typing_extra.get_cls_type_hints(namedtuple_cls, ns_resolver=self._ns_resolver) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1571 except NameError as e:
1572 raise PydanticUndefinedAnnotation.from_name_error(e) from e
1573 if not annotations: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1574 # annotations is empty, happens if namedtuple_cls defined via collections.namedtuple(...)
1575 annotations: dict[str, Any] = {k: Any for k in namedtuple_cls._fields} 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1577 if typevars_map: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1578 annotations = { 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1579 field_name: replace_types(annotation, typevars_map)
1580 for field_name, annotation in annotations.items()
1581 }
1583 arguments_schema = core_schema.arguments_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1584 [
1585 self._generate_parameter_schema(
1586 field_name,
1587 annotation,
1588 default=namedtuple_cls._field_defaults.get(field_name, Parameter.empty),
1589 )
1590 for field_name, annotation in annotations.items()
1591 ],
1592 metadata={'pydantic_js_prefer_positional_arguments': True},
1593 )
1594 schema = core_schema.call_schema(arguments_schema, namedtuple_cls, ref=namedtuple_ref) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1595 return self.defs.create_definition_reference_schema(schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1597 def _generate_parameter_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1598 self,
1599 name: str,
1600 annotation: type[Any],
1601 default: Any = Parameter.empty,
1602 mode: Literal['positional_only', 'positional_or_keyword', 'keyword_only'] | None = None,
1603 ) -> core_schema.ArgumentsParameter:
1604 """Prepare a ArgumentsParameter to represent a field in a namedtuple or function signature."""
1605 FieldInfo = import_cached_field_info() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1607 if default is Parameter.empty: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1608 field = FieldInfo.from_annotation(annotation) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1609 else:
1610 field = FieldInfo.from_annotated_attribute(annotation, default) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1611 assert field.annotation is not None, 'field.annotation should not be None when generating a schema' 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1612 with self.field_name_stack.push(name): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1613 schema = self._apply_annotations(field.annotation, [field]) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1615 if not field.is_required(): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1616 schema = wrap_default(field, schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1618 parameter_schema = core_schema.arguments_parameter(name, schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1619 if mode is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1620 parameter_schema['mode'] = mode 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1621 if field.alias is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1622 parameter_schema['alias'] = field.alias 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1623 else:
1624 alias_generator = self._config_wrapper.alias_generator 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1625 if isinstance(alias_generator, AliasGenerator) and alias_generator.alias is not None: 1625 ↛ 1626line 1625 didn't jump to line 1626 because the condition on line 1625 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
1626 parameter_schema['alias'] = alias_generator.alias(name)
1627 elif isinstance(alias_generator, Callable): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1628 parameter_schema['alias'] = alias_generator(name) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1629 return parameter_schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1631 def _tuple_schema(self, tuple_type: Any) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1632 """Generate schema for a Tuple, e.g. `tuple[int, str]` or `tuple[int, ...]`."""
1633 # TODO: do we really need to resolve type vars here?
1634 typevars_map = get_standard_typevars_map(tuple_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1635 params = self._get_args_resolving_forward_refs(tuple_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1637 if typevars_map and params: 1637 ↛ 1638line 1637 didn't jump to line 1638 because the condition on line 1637 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
1638 params = tuple(replace_types(param, typevars_map) for param in params)
1640 # NOTE: subtle difference: `tuple[()]` gives `params=()`, whereas `typing.Tuple[()]` gives `params=((),)`
1641 # This is only true for <3.11, on Python 3.11+ `typing.Tuple[()]` gives `params=()`
1642 if not params: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1643 if tuple_type in TUPLE_TYPES: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1644 return core_schema.tuple_schema([core_schema.any_schema()], variadic_item_index=0) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1645 else:
1646 # special case for `tuple[()]` which means `tuple[]` - an empty tuple
1647 return core_schema.tuple_schema([]) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1648 elif params[-1] is Ellipsis: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1649 if len(params) == 2: 1649 ↛ 1653line 1649 didn't jump to line 1653 because the condition on line 1649 was always true1acekoquwxCfbhilmrsyzDEdjgnptvABF
1650 return core_schema.tuple_schema([self.generate_schema(params[0])], variadic_item_index=0) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1651 else:
1652 # TODO: something like https://github.com/pydantic/pydantic/issues/5952
1653 raise ValueError('Variable tuples can only have one type')
1654 elif len(params) == 1 and params[0] == (): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1655 # special case for `tuple[()]` which means `tuple[]` - an empty tuple
1656 # NOTE: This conditional can be removed when we drop support for Python 3.10.
1657 return core_schema.tuple_schema([]) 1acekfbhilmdjgn
1658 else:
1659 return core_schema.tuple_schema([self.generate_schema(param) for param in params]) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1661 def _type_schema(self) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1662 return core_schema.custom_error_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1663 core_schema.is_instance_schema(type),
1664 custom_error_type='is_type',
1665 custom_error_message='Input should be a type',
1666 )
1668 def _zoneinfo_schema(self) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1669 """Generate schema for a zone_info.ZoneInfo object"""
1670 from ._validators import validate_str_is_valid_iana_tz 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1672 metadata = {'pydantic_js_functions': [lambda _1, _2: {'type': 'string', 'format': 'zoneinfo'}]} 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1673 return core_schema.no_info_plain_validator_function( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1674 validate_str_is_valid_iana_tz,
1675 serialization=core_schema.to_string_ser_schema(),
1676 metadata=metadata,
1677 )
1679 def _union_is_subclass_schema(self, union_type: Any) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1680 """Generate schema for `type[Union[X, ...]]`."""
1681 args = self._get_args_resolving_forward_refs(union_type, required=True) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1682 return core_schema.union_schema([self.generate_schema(type[args]) for args in args]) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1684 def _subclass_schema(self, type_: Any) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1685 """Generate schema for a type, e.g. `type[int]`."""
1686 type_param = self._get_first_arg_or_any(type_) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1688 # Assume `type[Annotated[<typ>, ...]]` is equivalent to `type[<typ>]`:
1689 type_param = _typing_extra.annotated_type(type_param) or type_param 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1691 if _typing_extra.is_any(type_param): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1692 return self._type_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1693 elif _typing_extra.is_type_alias_type(type_param): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1694 return self.generate_schema(type[type_param.__value__]) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1695 elif isinstance(type_param, typing.TypeVar): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1696 if type_param.__bound__: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1697 if _typing_extra.origin_is_union(get_origin(type_param.__bound__)): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1698 return self._union_is_subclass_schema(type_param.__bound__) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1699 return core_schema.is_subclass_schema(type_param.__bound__) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1700 elif type_param.__constraints__: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1701 return core_schema.union_schema([self.generate_schema(type[c]) for c in type_param.__constraints__]) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1702 else:
1703 return self._type_schema() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1704 elif _typing_extra.origin_is_union(get_origin(type_param)): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1705 return self._union_is_subclass_schema(type_param) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1706 else:
1707 if _typing_extra.is_self(type_param): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1708 type_param = self._resolve_self_type(type_param) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1709 if _typing_extra.is_generic_alias(type_param): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1710 raise PydanticUserError( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1711 'Subscripting `type[]` with an already parametrized type is not supported. '
1712 f'Instead of using type[{type_param!r}], use type[{_repr.display_as_type(get_origin(type_param))}].',
1713 code=None,
1714 )
1715 if not inspect.isclass(type_param): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1716 # when using type[None], this doesn't type convert to type[NoneType], and None isn't a class
1717 # so we handle it manually here
1718 if type_param is None: 1718 ↛ 1720line 1718 didn't jump to line 1720 because the condition on line 1718 was always true1acekoquwxCfbhilmrsyzDEdjgnptvABF
1719 return core_schema.is_subclass_schema(_typing_extra.NoneType) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1720 raise TypeError(f'Expected a class, got {type_param!r}')
1721 return core_schema.is_subclass_schema(type_param) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1723 def _sequence_schema(self, items_type: Any) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1724 """Generate schema for a Sequence, e.g. `Sequence[int]`."""
1725 from ._serializers import serialize_sequence_via_list 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1727 item_type_schema = self.generate_schema(items_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1728 list_schema = core_schema.list_schema(item_type_schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1730 json_schema = smart_deepcopy(list_schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1731 python_schema = core_schema.is_instance_schema(typing.Sequence, cls_repr='Sequence') 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1732 if not _typing_extra.is_any(items_type): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1733 from ._validators import sequence_validator 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1735 python_schema = core_schema.chain_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1736 [python_schema, core_schema.no_info_wrap_validator_function(sequence_validator, list_schema)],
1737 )
1739 serialization = core_schema.wrap_serializer_function_ser_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1740 serialize_sequence_via_list, schema=item_type_schema, info_arg=True
1741 )
1742 return core_schema.json_or_python_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1743 json_schema=json_schema, python_schema=python_schema, serialization=serialization
1744 )
1746 def _iterable_schema(self, type_: Any) -> core_schema.GeneratorSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1747 """Generate a schema for an `Iterable`."""
1748 item_type = self._get_first_arg_or_any(type_) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1750 return core_schema.generator_schema(self.generate_schema(item_type)) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1752 def _pattern_schema(self, pattern_type: Any) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1753 from . import _validators 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1755 metadata = {'pydantic_js_functions': [lambda _1, _2: {'type': 'string', 'format': 'regex'}]} 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1756 ser = core_schema.plain_serializer_function_ser_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1757 attrgetter('pattern'), when_used='json', return_schema=core_schema.str_schema()
1758 )
1759 if pattern_type is typing.Pattern or pattern_type is re.Pattern: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1760 # bare type
1761 return core_schema.no_info_plain_validator_function( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1762 _validators.pattern_either_validator, serialization=ser, metadata=metadata
1763 )
1765 param = self._get_args_resolving_forward_refs( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1766 pattern_type,
1767 required=True,
1768 )[0]
1769 if param is str: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1770 return core_schema.no_info_plain_validator_function( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1771 _validators.pattern_str_validator, serialization=ser, metadata=metadata
1772 )
1773 elif param is bytes: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1774 return core_schema.no_info_plain_validator_function( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1775 _validators.pattern_bytes_validator, serialization=ser, metadata=metadata
1776 )
1777 else:
1778 raise PydanticSchemaGenerationError(f'Unable to generate pydantic-core schema for {pattern_type!r}.') 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1780 def _hashable_schema(self) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1781 return core_schema.custom_error_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1782 schema=core_schema.json_or_python_schema(
1783 json_schema=core_schema.chain_schema(
1784 [core_schema.any_schema(), core_schema.is_instance_schema(collections.abc.Hashable)]
1785 ),
1786 python_schema=core_schema.is_instance_schema(collections.abc.Hashable),
1787 ),
1788 custom_error_type='is_hashable',
1789 custom_error_message='Input should be hashable',
1790 )
1792 def _dataclass_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1793 self, dataclass: type[StandardDataclass], origin: type[StandardDataclass] | None
1794 ) -> core_schema.CoreSchema:
1795 """Generate schema for a dataclass."""
1796 with ( 1acekoqfbhilmrsLGHIJKdjgnpt
1797 self.model_type_stack.push(dataclass),
1798 self.defs.get_schema_or_ref(dataclass) as (
1799 dataclass_ref,
1800 maybe_schema,
1801 ),
1802 ):
1803 if maybe_schema is not None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1804 return maybe_schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1806 schema = dataclass.__dict__.get('__pydantic_core_schema__') 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1807 if schema is not None and not isinstance(schema, MockCoreSchema): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1808 if schema['type'] == 'definitions': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1809 schema = self.defs.unpack_definitions(schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1810 ref = get_ref(schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1811 if ref: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1812 return self.defs.create_definition_reference_schema(schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1813 else:
1814 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1816 typevars_map = get_standard_typevars_map(dataclass) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1817 if origin is not None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1818 dataclass = origin 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1820 # if (plain) dataclass doesn't have config, we use the parent's config, hence a default of `None`
1821 # (Pydantic dataclasses have an empty dict config by default).
1822 # see https://github.com/pydantic/pydantic/issues/10917
1823 config = getattr(dataclass, '__pydantic_config__', None) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1825 from ..dataclasses import is_pydantic_dataclass 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1827 with self._ns_resolver.push(dataclass), self._config_wrapper_stack.push(config): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1828 if is_pydantic_dataclass(dataclass): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1829 # Copy the field info instances to avoid mutating the `FieldInfo` instances
1830 # of the generic dataclass generic origin (e.g. `apply_typevars_map` below).
1831 # Note that we don't apply `deepcopy` on `__pydantic_fields__` because we
1832 # don't want to copy the `FieldInfo` attributes:
1833 fields = {f_name: copy(field_info) for f_name, field_info in dataclass.__pydantic_fields__.items()} 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1834 if typevars_map: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1835 for field in fields.values(): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1836 field.apply_typevars_map(typevars_map, *self._types_namespace) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1837 else:
1838 fields = collect_dataclass_fields( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1839 dataclass,
1840 typevars_map=typevars_map,
1841 config_wrapper=self._config_wrapper,
1842 )
1844 if self._config_wrapper.extra == 'allow': 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1845 # disallow combination of init=False on a dataclass field and extra='allow' on a dataclass
1846 for field_name, field in fields.items(): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1847 if field.init is False: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1848 raise PydanticUserError( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1849 f'Field {field_name} has `init=False` and dataclass has config setting `extra="allow"`. '
1850 f'This combination is not allowed.',
1851 code='dataclass-init-false-extra-allow',
1852 )
1854 decorators = dataclass.__dict__.get('__pydantic_decorators__') or DecoratorInfos.build(dataclass) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1855 # Move kw_only=False args to the start of the list, as this is how vanilla dataclasses work.
1856 # Note that when kw_only is missing or None, it is treated as equivalent to kw_only=True
1857 args = sorted( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1858 (self._generate_dc_field_schema(k, v, decorators) for k, v in fields.items()),
1859 key=lambda a: a.get('kw_only') is not False,
1860 )
1861 has_post_init = hasattr(dataclass, '__post_init__') 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1862 has_slots = hasattr(dataclass, '__slots__') 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1864 args_schema = core_schema.dataclass_args_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1865 dataclass.__name__,
1866 args,
1867 computed_fields=[
1868 self._computed_field_schema(d, decorators.field_serializers)
1869 for d in decorators.computed_fields.values()
1870 ],
1871 collect_init_only=has_post_init,
1872 )
1874 inner_schema = apply_validators(args_schema, decorators.root_validators.values(), None) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1876 model_validators = decorators.model_validators.values() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1877 inner_schema = apply_model_validators(inner_schema, model_validators, 'inner') 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1879 core_config = self._config_wrapper.core_config(title=dataclass.__name__) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1881 dc_schema = core_schema.dataclass_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1882 dataclass,
1883 inner_schema,
1884 generic_origin=origin,
1885 post_init=has_post_init,
1886 ref=dataclass_ref,
1887 fields=[field.name for field in dataclasses.fields(dataclass)],
1888 slots=has_slots,
1889 config=core_config,
1890 # we don't use a custom __setattr__ for dataclasses, so we must
1891 # pass along the frozen config setting to the pydantic-core schema
1892 frozen=self._config_wrapper_stack.tail.frozen,
1893 )
1894 schema = self._apply_model_serializers(dc_schema, decorators.model_serializers.values()) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1895 schema = apply_model_validators(schema, model_validators, 'outer') 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1896 return self.defs.create_definition_reference_schema(schema) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1898 def _call_schema(self, function: ValidateCallSupportedTypes) -> core_schema.CallSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1899 """Generate schema for a Callable.
1901 TODO support functional validators once we support them in Config
1902 """
1903 sig = signature(function) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1904 globalns, localns = self._types_namespace 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1905 type_hints = _typing_extra.get_function_type_hints(function, globalns=globalns, localns=localns) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1907 mode_lookup: dict[_ParameterKind, Literal['positional_only', 'positional_or_keyword', 'keyword_only']] = { 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1908 Parameter.POSITIONAL_ONLY: 'positional_only',
1909 Parameter.POSITIONAL_OR_KEYWORD: 'positional_or_keyword',
1910 Parameter.KEYWORD_ONLY: 'keyword_only',
1911 }
1913 arguments_list: list[core_schema.ArgumentsParameter] = [] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1914 var_args_schema: core_schema.CoreSchema | None = None 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1915 var_kwargs_schema: core_schema.CoreSchema | None = None 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1916 var_kwargs_mode: core_schema.VarKwargsMode | None = None 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1918 for name, p in sig.parameters.items(): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1919 if p.annotation is sig.empty: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1920 annotation = typing.cast(Any, Any) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1921 else:
1922 annotation = type_hints[name] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1924 parameter_mode = mode_lookup.get(p.kind) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1925 if parameter_mode is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1926 arg_schema = self._generate_parameter_schema(name, annotation, p.default, parameter_mode) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1927 arguments_list.append(arg_schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1928 elif p.kind == Parameter.VAR_POSITIONAL: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1929 var_args_schema = self.generate_schema(annotation) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1930 else:
1931 assert p.kind == Parameter.VAR_KEYWORD, p.kind 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1933 unpack_type = _typing_extra.unpack_type(annotation) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1934 if unpack_type is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1935 if not is_typeddict(unpack_type): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1936 raise PydanticUserError( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1937 f'Expected a `TypedDict` class, got {unpack_type.__name__!r}', code='unpack-typed-dict'
1938 )
1939 non_pos_only_param_names = { 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1940 name for name, p in sig.parameters.items() if p.kind != Parameter.POSITIONAL_ONLY
1941 }
1942 overlapping_params = non_pos_only_param_names.intersection(unpack_type.__annotations__) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1943 if overlapping_params: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1944 raise PydanticUserError( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1945 f'Typed dictionary {unpack_type.__name__!r} overlaps with parameter'
1946 f'{"s" if len(overlapping_params) >= 2 else ""} '
1947 f'{", ".join(repr(p) for p in sorted(overlapping_params))}',
1948 code='overlapping-unpack-typed-dict',
1949 )
1951 var_kwargs_mode = 'unpacked-typed-dict' 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1952 var_kwargs_schema = self._typed_dict_schema(unpack_type, None) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1953 else:
1954 var_kwargs_mode = 'uniform' 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1955 var_kwargs_schema = self.generate_schema(annotation) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1957 return_schema: core_schema.CoreSchema | None = None 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1958 config_wrapper = self._config_wrapper 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1959 if config_wrapper.validate_return: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1960 return_hint = sig.return_annotation 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1961 if return_hint is not sig.empty: 1961 ↛ 1964line 1961 didn't jump to line 1964 because the condition on line 1961 was always true1acekoquwxCfbhilmrsyzDEdjgnptvABF
1962 return_schema = self.generate_schema(return_hint) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1964 return core_schema.call_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1965 core_schema.arguments_schema(
1966 arguments_list,
1967 var_args_schema=var_args_schema,
1968 var_kwargs_mode=var_kwargs_mode,
1969 var_kwargs_schema=var_kwargs_schema,
1970 populate_by_name=config_wrapper.populate_by_name,
1971 ),
1972 function,
1973 return_schema=return_schema,
1974 )
1976 def _unsubstituted_typevar_schema(self, typevar: typing.TypeVar) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1977 try: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1978 has_default = typevar.has_default() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1979 except AttributeError: 1acekoquwfbhilmrsyzLGHIJKdjgnptvA
1980 # Happens if using `typing.TypeVar` (and not `typing_extensions`) on Python < 3.13
1981 pass 1acekoquwfbhilmrsyzLGHIJKdjgnptvA
1982 else:
1983 if has_default: 1acekoquwxCfbhilmrsyzDEMdjgnptvABF
1984 return self.generate_schema(typevar.__default__) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1986 if constraints := typevar.__constraints__: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1987 return self._union_schema(typing.Union[constraints]) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1989 if bound := typevar.__bound__: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1990 schema = self.generate_schema(bound) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1991 schema['serialization'] = core_schema.wrap_serializer_function_ser_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1992 lambda x, h: h(x),
1993 schema=core_schema.any_schema(),
1994 )
1995 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
1997 return core_schema.any_schema() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
1999 def _computed_field_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2000 self,
2001 d: Decorator[ComputedFieldInfo],
2002 field_serializers: dict[str, Decorator[FieldSerializerDecoratorInfo]],
2003 ) -> core_schema.ComputedField:
2004 try: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2005 # Do not pass in globals as the function could be defined in a different module.
2006 # Instead, let `get_function_return_type` infer the globals to use, but still pass
2007 # in locals that may contain a parent/rebuild namespace:
2008 return_type = _decorators.get_function_return_type( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2009 d.func, d.info.return_type, localns=self._types_namespace.locals
2010 )
2011 except NameError as e: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2012 raise PydanticUndefinedAnnotation.from_name_error(e) from e 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2013 if return_type is PydanticUndefined: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2014 raise PydanticUserError( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2015 'Computed field is missing return type annotation or specifying `return_type`'
2016 ' to the `@computed_field` decorator (e.g. `@computed_field(return_type=int|str)`)',
2017 code='model-field-missing-annotation',
2018 )
2020 return_type = replace_types(return_type, self._typevars_map) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2021 # Create a new ComputedFieldInfo so that different type parametrizations of the same
2022 # generic model's computed field can have different return types.
2023 d.info = dataclasses.replace(d.info, return_type=return_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2024 return_type_schema = self.generate_schema(return_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2025 # Apply serializers to computed field if there exist
2026 return_type_schema = self._apply_field_serializers( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2027 return_type_schema,
2028 filter_field_decorator_info_by_field(field_serializers.values(), d.cls_var_name),
2029 )
2031 alias_generator = self._config_wrapper.alias_generator 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2032 if alias_generator is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2033 self._apply_alias_generator_to_computed_field_info( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2034 alias_generator=alias_generator, computed_field_info=d.info, computed_field_name=d.cls_var_name
2035 )
2036 self._apply_field_title_generator_to_field_info(self._config_wrapper, d.info, d.cls_var_name) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2038 pydantic_js_updates, pydantic_js_extra = _extract_json_schema_info_from_field_info(d.info) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2039 core_metadata: dict[str, Any] = {} 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2040 update_core_metadata( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2041 core_metadata,
2042 pydantic_js_updates={'readOnly': True, **(pydantic_js_updates if pydantic_js_updates else {})},
2043 pydantic_js_extra=pydantic_js_extra,
2044 )
2045 return core_schema.computed_field( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2046 d.cls_var_name, return_schema=return_type_schema, alias=d.info.alias, metadata=core_metadata
2047 )
2049 def _annotated_schema(self, annotated_type: Any) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2050 """Generate schema for an Annotated type, e.g. `Annotated[int, Field(...)]` or `Annotated[int, Gt(0)]`."""
2051 FieldInfo = import_cached_field_info() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2052 # Ideally, we should delegate all this to `_typing_extra.unpack_annotated`, e.g.:
2053 # `typ, annotations = _typing_extra.unpack_annotated(annotated_type); schema = self.apply_annotations(...)`
2054 # if it was able to use a `NsResolver`. But because `unpack_annotated` is also used
2055 # when constructing `FieldInfo` instances (where we don't have access to a `NsResolver`),
2056 # the implementation of the function does *not* resolve forward annotations. This could
2057 # be solved by calling `unpack_annotated` directly inside `collect_model_fields`.
2058 # For now, we at least resolve the annotated type if it is a forward ref, but note that
2059 # unexpected results will happen if you have something like `Annotated[Alias, ...]` and
2060 # `Alias` is a PEP 695 type alias containing forward references.
2061 typ, *annotations = get_args(annotated_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2062 if isinstance(typ, str): 2062 ↛ 2063line 2062 didn't jump to line 2063 because the condition on line 2062 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
2063 typ = _typing_extra._make_forward_ref(typ)
2064 if isinstance(typ, ForwardRef): 2064 ↛ 2065line 2064 didn't jump to line 2065 because the condition on line 2064 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
2065 typ = self._resolve_forward_ref(typ)
2067 typ, sub_annotations = _typing_extra.unpack_annotated(typ) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2068 annotations = sub_annotations + annotations 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2070 schema = self._apply_annotations(typ, annotations) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2071 # put the default validator last so that TypeAdapter.get_default_value() works
2072 # even if there are function validators involved
2073 for annotation in annotations: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2074 if isinstance(annotation, FieldInfo): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2075 schema = wrap_default(annotation, schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2076 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2078 def _apply_annotations( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2079 self,
2080 source_type: Any,
2081 annotations: list[Any],
2082 transform_inner_schema: Callable[[CoreSchema], CoreSchema] = lambda x: x,
2083 ) -> CoreSchema:
2084 """Apply arguments from `Annotated` or from `FieldInfo` to a schema.
2086 This gets called by `GenerateSchema._annotated_schema` but differs from it in that it does
2087 not expect `source_type` to be an `Annotated` object, it expects it to be the first argument of that
2088 (in other words, `GenerateSchema._annotated_schema` just unpacks `Annotated`, this process it).
2089 """
2090 annotations = list(_known_annotated_metadata.expand_grouped_metadata(annotations)) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2092 pydantic_js_annotation_functions: list[GetJsonSchemaFunction] = [] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2094 def inner_handler(obj: Any) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2095 schema = self._generate_schema_from_get_schema_method(obj, source_type) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2097 if schema is None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2098 schema = self._generate_schema_inner(obj) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2100 metadata_js_function = _extract_get_pydantic_json_schema(obj) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2101 if metadata_js_function is not None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2102 metadata_schema = resolve_original_schema(schema, self.defs) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2103 if metadata_schema is not None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2104 self._add_js_function(metadata_schema, metadata_js_function) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2105 return transform_inner_schema(schema) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2107 get_inner_schema = CallbackGetCoreSchemaHandler(inner_handler, self) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2109 for annotation in annotations: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2110 if annotation is None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2111 continue 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2112 get_inner_schema = self._get_wrapped_inner_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2113 get_inner_schema, annotation, pydantic_js_annotation_functions
2114 )
2116 schema = get_inner_schema(source_type) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2117 if pydantic_js_annotation_functions: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2118 core_metadata = schema.setdefault('metadata', {}) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2119 update_core_metadata(core_metadata, pydantic_js_annotation_functions=pydantic_js_annotation_functions) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2120 return _add_custom_serialization_from_json_encoders(self._config_wrapper.json_encoders, source_type, schema) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2122 def _apply_single_annotation(self, schema: core_schema.CoreSchema, metadata: Any) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2123 FieldInfo = import_cached_field_info() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2125 if isinstance(metadata, FieldInfo): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2126 for field_metadata in metadata.metadata: 2126 ↛ 2127line 2126 didn't jump to line 2127 because the loop on line 2126 never started1acekoquwxCfbhilmrsyzDEdjgnptvABF
2127 schema = self._apply_single_annotation(schema, field_metadata)
2129 if metadata.discriminator is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2130 schema = self._apply_discriminator_to_union(schema, metadata.discriminator) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2131 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2133 if schema['type'] == 'nullable': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2134 # for nullable schemas, metadata is automatically applied to the inner schema
2135 inner = schema.get('schema', core_schema.any_schema()) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2136 inner = self._apply_single_annotation(inner, metadata) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2137 if inner: 2137 ↛ 2139line 2137 didn't jump to line 2139 because the condition on line 2137 was always true1acekoquwxCfbhilmrsyzDEdjgnptvABF
2138 schema['schema'] = inner 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2139 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2141 original_schema = schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2142 ref = schema.get('ref') 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2143 if ref is not None: 2143 ↛ 2144line 2143 didn't jump to line 2144 because the condition on line 2143 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
2144 schema = schema.copy()
2145 new_ref = ref + f'_{repr(metadata)}'
2146 if (existing := self.defs.get_schema_from_ref(new_ref)) is not None:
2147 return existing
2148 schema['ref'] = new_ref # pyright: ignore[reportGeneralTypeIssues]
2149 elif schema['type'] == 'definition-ref': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2150 ref = schema['schema_ref'] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2151 if (referenced_schema := self.defs.get_schema_from_ref(ref)) is not None: 2151 ↛ 2158line 2151 didn't jump to line 2158 because the condition on line 2151 was always true1acekoquwxCfbhilmrsyzDEdjgnptvABF
2152 schema = referenced_schema.copy() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2153 new_ref = ref + f'_{repr(metadata)}' 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2154 if (existing := self.defs.get_schema_from_ref(new_ref)) is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2155 return existing 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2156 schema['ref'] = new_ref # pyright: ignore[reportGeneralTypeIssues] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2158 maybe_updated_schema = _known_annotated_metadata.apply_known_metadata(metadata, schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2160 if maybe_updated_schema is not None: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2161 return maybe_updated_schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2162 return original_schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2164 def _apply_single_annotation_json_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2165 self, schema: core_schema.CoreSchema, metadata: Any
2166 ) -> core_schema.CoreSchema:
2167 FieldInfo = import_cached_field_info() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2169 if isinstance(metadata, FieldInfo): 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2170 for field_metadata in metadata.metadata: 2170 ↛ 2171line 2170 didn't jump to line 2171 because the loop on line 2170 never started1acekoquwxCfbhilmrsyzDEdjgnptvABF
2171 schema = self._apply_single_annotation_json_schema(schema, field_metadata)
2173 pydantic_js_updates, pydantic_js_extra = _extract_json_schema_info_from_field_info(metadata) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2174 core_metadata = schema.setdefault('metadata', {}) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2175 update_core_metadata( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2176 core_metadata, pydantic_js_updates=pydantic_js_updates, pydantic_js_extra=pydantic_js_extra
2177 )
2178 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2180 def _get_wrapped_inner_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2181 self,
2182 get_inner_schema: GetCoreSchemaHandler,
2183 annotation: Any,
2184 pydantic_js_annotation_functions: list[GetJsonSchemaFunction],
2185 ) -> CallbackGetCoreSchemaHandler:
2186 annotation_get_schema: GetCoreSchemaFunction | None = getattr(annotation, '__get_pydantic_core_schema__', None) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2188 def new_handler(source: Any) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2189 if annotation_get_schema is not None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2190 schema = annotation_get_schema(source, get_inner_schema) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2191 else:
2192 schema = get_inner_schema(source) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2193 schema = self._apply_single_annotation(schema, annotation) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2194 schema = self._apply_single_annotation_json_schema(schema, annotation) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2196 metadata_js_function = _extract_get_pydantic_json_schema(annotation) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2197 if metadata_js_function is not None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2198 pydantic_js_annotation_functions.append(metadata_js_function) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2199 return schema 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2201 return CallbackGetCoreSchemaHandler(new_handler, self) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2203 def _apply_field_serializers( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2204 self,
2205 schema: core_schema.CoreSchema,
2206 serializers: list[Decorator[FieldSerializerDecoratorInfo]],
2207 ) -> core_schema.CoreSchema:
2208 """Apply field serializers to a schema."""
2209 if serializers: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2210 schema = copy(schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2211 if schema['type'] == 'definitions': 2211 ↛ 2212line 2211 didn't jump to line 2212 because the condition on line 2211 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
2212 inner_schema = schema['schema']
2213 schema['schema'] = self._apply_field_serializers(inner_schema, serializers)
2214 return schema
2215 elif 'ref' in schema: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2216 schema = self.defs.create_definition_reference_schema(schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2218 # use the last serializer to make it easy to override a serializer set on a parent model
2219 serializer = serializers[-1] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2220 is_field_serializer, info_arg = inspect_field_serializer(serializer.func, serializer.info.mode) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2222 try: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2223 # Do not pass in globals as the function could be defined in a different module.
2224 # Instead, let `get_function_return_type` infer the globals to use, but still pass
2225 # in locals that may contain a parent/rebuild namespace:
2226 return_type = _decorators.get_function_return_type( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2227 serializer.func, serializer.info.return_type, localns=self._types_namespace.locals
2228 )
2229 except NameError as e: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2230 raise PydanticUndefinedAnnotation.from_name_error(e) from e 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2232 if return_type is PydanticUndefined: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2233 return_schema = None 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2234 else:
2235 return_schema = self.generate_schema(return_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2237 if serializer.info.mode == 'wrap': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2238 schema['serialization'] = core_schema.wrap_serializer_function_ser_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2239 serializer.func,
2240 is_field_serializer=is_field_serializer,
2241 info_arg=info_arg,
2242 return_schema=return_schema,
2243 when_used=serializer.info.when_used,
2244 )
2245 else:
2246 assert serializer.info.mode == 'plain' 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2247 schema['serialization'] = core_schema.plain_serializer_function_ser_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2248 serializer.func,
2249 is_field_serializer=is_field_serializer,
2250 info_arg=info_arg,
2251 return_schema=return_schema,
2252 when_used=serializer.info.when_used,
2253 )
2254 return schema 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2256 def _apply_model_serializers( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2257 self, schema: core_schema.CoreSchema, serializers: Iterable[Decorator[ModelSerializerDecoratorInfo]]
2258 ) -> core_schema.CoreSchema:
2259 """Apply model serializers to a schema."""
2260 ref: str | None = schema.pop('ref', None) # type: ignore 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2261 if serializers: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2262 serializer = list(serializers)[-1] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2263 info_arg = inspect_model_serializer(serializer.func, serializer.info.mode) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2265 try: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2266 # Do not pass in globals as the function could be defined in a different module.
2267 # Instead, let `get_function_return_type` infer the globals to use, but still pass
2268 # in locals that may contain a parent/rebuild namespace:
2269 return_type = _decorators.get_function_return_type( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2270 serializer.func, serializer.info.return_type, localns=self._types_namespace.locals
2271 )
2272 except NameError as e:
2273 raise PydanticUndefinedAnnotation.from_name_error(e) from e
2274 if return_type is PydanticUndefined: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2275 return_schema = None 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2276 else:
2277 return_schema = self.generate_schema(return_type) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2279 if serializer.info.mode == 'wrap': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2280 ser_schema: core_schema.SerSchema = core_schema.wrap_serializer_function_ser_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2281 serializer.func,
2282 info_arg=info_arg,
2283 return_schema=return_schema,
2284 when_used=serializer.info.when_used,
2285 )
2286 else:
2287 # plain
2288 ser_schema = core_schema.plain_serializer_function_ser_schema( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2289 serializer.func,
2290 info_arg=info_arg,
2291 return_schema=return_schema,
2292 when_used=serializer.info.when_used,
2293 )
2294 schema['serialization'] = ser_schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2295 if ref: 2295 ↛ 2297line 2295 didn't jump to line 2297 because the condition on line 2295 was always true1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2296 schema['ref'] = ref # type: ignore 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2297 return schema 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2300_VALIDATOR_F_MATCH: Mapping[ 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2301 tuple[FieldValidatorModes, Literal['no-info', 'with-info']],
2302 Callable[[Callable[..., Any], core_schema.CoreSchema, str | None], core_schema.CoreSchema],
2303] = {
2304 ('before', 'no-info'): lambda f, schema, _: core_schema.no_info_before_validator_function(f, schema),
2305 ('after', 'no-info'): lambda f, schema, _: core_schema.no_info_after_validator_function(f, schema),
2306 ('plain', 'no-info'): lambda f, _1, _2: core_schema.no_info_plain_validator_function(f),
2307 ('wrap', 'no-info'): lambda f, schema, _: core_schema.no_info_wrap_validator_function(f, schema),
2308 ('before', 'with-info'): lambda f, schema, field_name: core_schema.with_info_before_validator_function(
2309 f, schema, field_name=field_name
2310 ),
2311 ('after', 'with-info'): lambda f, schema, field_name: core_schema.with_info_after_validator_function(
2312 f, schema, field_name=field_name
2313 ),
2314 ('plain', 'with-info'): lambda f, _, field_name: core_schema.with_info_plain_validator_function(
2315 f, field_name=field_name
2316 ),
2317 ('wrap', 'with-info'): lambda f, schema, field_name: core_schema.with_info_wrap_validator_function(
2318 f, schema, field_name=field_name
2319 ),
2320}
2323# TODO V3: this function is only used for deprecated decorators. It should
2324# be removed once we drop support for those.
2325def apply_validators( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2326 schema: core_schema.CoreSchema,
2327 validators: Iterable[Decorator[RootValidatorDecoratorInfo]]
2328 | Iterable[Decorator[ValidatorDecoratorInfo]]
2329 | Iterable[Decorator[FieldValidatorDecoratorInfo]],
2330 field_name: str | None,
2331) -> core_schema.CoreSchema:
2332 """Apply validators to a schema.
2334 Args:
2335 schema: The schema to apply validators on.
2336 validators: An iterable of validators.
2337 field_name: The name of the field if validators are being applied to a model field.
2339 Returns:
2340 The updated schema.
2341 """
2342 for validator in validators: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2343 info_arg = inspect_validator(validator.func, validator.info.mode) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2344 val_type = 'with-info' if info_arg else 'no-info' 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2346 schema = _VALIDATOR_F_MATCH[(validator.info.mode, val_type)](validator.func, schema, field_name) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2347 return schema 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2350def _validators_require_validate_default(validators: Iterable[Decorator[ValidatorDecoratorInfo]]) -> bool: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2351 """In v1, if any of the validators for a field had `always=True`, the default value would be validated.
2353 This serves as an auxiliary function for re-implementing that logic, by looping over a provided
2354 collection of (v1-style) ValidatorDecoratorInfo's and checking if any of them have `always=True`.
2356 We should be able to drop this function and the associated logic calling it once we drop support
2357 for v1-style validator decorators. (Or we can extend it and keep it if we add something equivalent
2358 to the v1-validator `always` kwarg to `field_validator`.)
2359 """
2360 for validator in validators: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2361 if validator.info.always: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2362 return True 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2363 return False 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2366def apply_model_validators( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2367 schema: core_schema.CoreSchema,
2368 validators: Iterable[Decorator[ModelValidatorDecoratorInfo]],
2369 mode: Literal['inner', 'outer', 'all'],
2370) -> core_schema.CoreSchema:
2371 """Apply model validators to a schema.
2373 If mode == 'inner', only "before" validators are applied
2374 If mode == 'outer', validators other than "before" are applied
2375 If mode == 'all', all validators are applied
2377 Args:
2378 schema: The schema to apply validators on.
2379 validators: An iterable of validators.
2380 mode: The validator mode.
2382 Returns:
2383 The updated schema.
2384 """
2385 ref: str | None = schema.pop('ref', None) # type: ignore 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2386 for validator in validators: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2387 if mode == 'inner' and validator.info.mode != 'before': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2388 continue 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2389 if mode == 'outer' and validator.info.mode == 'before': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2390 continue 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2391 info_arg = inspect_validator(validator.func, validator.info.mode) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2392 if validator.info.mode == 'wrap': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2393 if info_arg: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2394 schema = core_schema.with_info_wrap_validator_function(function=validator.func, schema=schema) 1uwxCyzDEvABF
2395 else:
2396 schema = core_schema.no_info_wrap_validator_function(function=validator.func, schema=schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2397 elif validator.info.mode == 'before': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2398 if info_arg: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2399 schema = core_schema.with_info_before_validator_function(function=validator.func, schema=schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2400 else:
2401 schema = core_schema.no_info_before_validator_function(function=validator.func, schema=schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2402 else:
2403 assert validator.info.mode == 'after' 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2404 if info_arg: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2405 schema = core_schema.with_info_after_validator_function(function=validator.func, schema=schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2406 else:
2407 schema = core_schema.no_info_after_validator_function(function=validator.func, schema=schema) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2408 if ref: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2409 schema['ref'] = ref # type: ignore 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2410 return schema 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2413def wrap_default(field_info: FieldInfo, schema: core_schema.CoreSchema) -> core_schema.CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2414 """Wrap schema with default schema if default value or `default_factory` are available.
2416 Args:
2417 field_info: The field info object.
2418 schema: The schema to apply default on.
2420 Returns:
2421 Updated schema by default value or `default_factory`.
2422 """
2423 if field_info.default_factory: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2424 return core_schema.with_default_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2425 schema,
2426 default_factory=field_info.default_factory,
2427 default_factory_takes_data=takes_validated_data_argument(field_info.default_factory),
2428 validate_default=field_info.validate_default,
2429 )
2430 elif field_info.default is not PydanticUndefined: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2431 return core_schema.with_default_schema( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2432 schema, default=field_info.default, validate_default=field_info.validate_default
2433 )
2434 else:
2435 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2438def _extract_get_pydantic_json_schema(tp: Any) -> GetJsonSchemaFunction | None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2439 """Extract `__get_pydantic_json_schema__` from a type, handling the deprecated `__modify_schema__`."""
2440 js_modify_function = getattr(tp, '__get_pydantic_json_schema__', None) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2442 if hasattr(tp, '__modify_schema__'): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2443 BaseModel = import_cached_base_model() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2445 has_custom_v2_modify_js_func = ( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2446 js_modify_function is not None
2447 and BaseModel.__get_pydantic_json_schema__.__func__ # type: ignore
2448 not in (js_modify_function, getattr(js_modify_function, '__func__', None))
2449 )
2451 if not has_custom_v2_modify_js_func: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2452 cls_name = getattr(tp, '__name__', None) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2453 raise PydanticUserError( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2454 f'The `__modify_schema__` method is not supported in Pydantic v2. '
2455 f'Use `__get_pydantic_json_schema__` instead{f" in class `{cls_name}`" if cls_name else ""}.',
2456 code='custom-json-schema',
2457 )
2459 # handle GenericAlias' but ignore Annotated which "lies" about its origin (in this case it would be `int`)
2460 if hasattr(tp, '__origin__') and not _typing_extra.is_annotated(tp): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2461 # Generic aliases proxy attribute access to the origin, *except* dunder attributes,
2462 # such as `__get_pydantic_json_schema__`, hence the explicit check.
2463 return _extract_get_pydantic_json_schema(tp.__origin__) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2465 if js_modify_function is None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2466 return None 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2468 return js_modify_function 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2471class _CommonField(TypedDict): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2472 schema: core_schema.CoreSchema 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2473 validation_alias: str | list[str | int] | list[list[str | int]] | None 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2474 serialization_alias: str | None 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2475 serialization_exclude: bool | None 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2476 frozen: bool | None 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2477 metadata: dict[str, Any] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2480def _common_field( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2481 schema: core_schema.CoreSchema,
2482 *,
2483 validation_alias: str | list[str | int] | list[list[str | int]] | None = None,
2484 serialization_alias: str | None = None,
2485 serialization_exclude: bool | None = None,
2486 frozen: bool | None = None,
2487 metadata: Any = None,
2488) -> _CommonField:
2489 return { 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2490 'schema': schema,
2491 'validation_alias': validation_alias,
2492 'serialization_alias': serialization_alias,
2493 'serialization_exclude': serialization_exclude,
2494 'frozen': frozen,
2495 'metadata': metadata,
2496 }
2499def resolve_original_schema(schema: CoreSchema, definitions: _Definitions) -> CoreSchema | None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2500 if schema['type'] == 'definition-ref': 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2501 return definitions.get_schema_from_ref(schema['schema_ref']) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2502 elif schema['type'] == 'definitions': 2502 ↛ 2503line 2502 didn't jump to line 2503 because the condition on line 2502 was never true1acekoquwxCfbhilmrsyzDEdjgnptvABF
2503 return schema['schema']
2504 else:
2505 return schema 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2508def _can_be_inlined(def_ref: core_schema.DefinitionReferenceSchema) -> bool: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2509 """Return whether the `'definition-ref'` schema can be replaced by its definition.
2511 This is true if no `'serialization'` schema is attached, or if it has at least one metadata entry.
2512 Inlining such schemas would remove the `'serialization'` schema or metadata.
2513 """
2514 return 'serialization' not in def_ref and not def_ref.get('metadata') 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2517class _Definitions: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2518 """Keeps track of references and definitions."""
2520 _recursively_seen: set[str] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2521 """A set of recursively seen references. 1ekoquwxCblmrsyzDEGHIJKMgnptvABF
2523 When a referenceable type is encountered, the `get_schema_or_ref` context manager is
2524 entered to compute the reference. If the type references itself by some way (e.g. for
2525 a dataclass a Pydantic model, the class can be referenced as a field annotation),
2526 entering the context manager again will yield a `'definition-ref'` schema that should
2527 short-circuit the normal generation process, as the reference was already in this set.
2528 """
2530 _definitions: dict[str, core_schema.CoreSchema] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2531 """A mapping of references to their corresponding schema. 1ekoquwxCblmrsyzDEGHIJKMgnptvABF
2533 When a schema for a referenceable type is generated, it is stored in this mapping. If the
2534 same type is encountered again, the reference is yielded by the `get_schema_or_ref` context
2535 manager.
2536 """
2538 def __init__(self) -> None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2539 self._recursively_seen = set() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2540 self._definitions = {} 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2542 @contextmanager 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2543 def get_schema_or_ref(self, tp: Any, /) -> Generator[tuple[str, core_schema.DefinitionReferenceSchema | None]]: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2544 """Get a definition for `tp` if one exists.
2546 If a definition exists, a tuple of `(ref_string, CoreSchema)` is returned.
2547 If no definition exists yet, a tuple of `(ref_string, None)` is returned.
2549 Note that the returned `CoreSchema` will always be a `DefinitionReferenceSchema`,
2550 not the actual definition itself.
2552 This should be called for any type that can be identified by reference.
2553 This includes any recursive types.
2555 At present the following types can be named/recursive:
2557 - Pydantic model
2558 - Pydantic and stdlib dataclasses
2559 - Typed dictionaries
2560 - Named tuples
2561 - `TypeAliasType` instances
2562 - Enums
2563 """
2564 ref = get_type_ref(tp) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2565 # return the reference if we're either (1) in a cycle or (2) it the reference was already encountered:
2566 if ref in self._recursively_seen or ref in self._definitions: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2567 yield (ref, core_schema.definition_reference_schema(ref)) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2568 else:
2569 self._recursively_seen.add(ref) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2570 try: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2571 yield (ref, None) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2572 finally:
2573 self._recursively_seen.discard(ref) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2575 def get_schema_from_ref(self, ref: str) -> CoreSchema | None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2576 """Resolve the schema from the given reference."""
2577 return self._definitions.get(ref) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2579 def create_definition_reference_schema(self, schema: CoreSchema) -> core_schema.DefinitionReferenceSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2580 """Store the schema as a definition and return a `'definition-reference'` schema pointing to it.
2582 The schema must have a reference attached to it.
2583 """
2584 ref = schema['ref'] # pyright: ignore 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2585 self._definitions[ref] = schema 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2586 return core_schema.definition_reference_schema(ref) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2588 def unpack_definitions(self, schema: core_schema.DefinitionsSchema) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2589 """Store the definitions of the `'definitions'` core schema and return the inner core schema."""
2590 for def_schema in schema['definitions']: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2591 self._definitions[def_schema['ref']] = def_schema # pyright: ignore 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2592 return schema['schema'] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2594 def finalize_schema(self, schema: CoreSchema) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2595 """Finalize the core schema.
2597 This traverses the core schema and referenced definitions, replaces `'definition-ref'` schemas
2598 by the referenced definition if possible, and applies deferred discriminators.
2599 """
2600 definitions = self._definitions 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2601 try: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2602 gather_result = gather_schemas_for_cleaning( 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2603 schema,
2604 definitions=definitions,
2605 )
2606 except MissingDefinitionError as e: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2607 raise InvalidSchemaError from e 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2609 remaining_defs: dict[str, CoreSchema] = {} 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2611 for ref, inlinable_def_ref in gather_result['collected_references'].items(): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2612 if inlinable_def_ref is not None and _can_be_inlined(inlinable_def_ref): 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2613 # `ref` was encountered, and only once:
2614 # - `inlinable_def_ref` is a `'definition-ref'` schema and is guaranteed to be
2615 # the only one. Transform it into the definition it points to.
2616 # - Do not store the definition in the `remaining_defs`.
2617 inlinable_def_ref.clear() # pyright: ignore[reportAttributeAccessIssue] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2618 inlinable_def_ref.update(self._resolve_definition(ref, definitions)) # pyright: ignore 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2619 else:
2620 # `ref` was encountered, at least two times:
2621 # - Do not inline the `'definition-ref'` schemas (they are not provided in the gather result anyway).
2622 # - Store the the definition in the `remaining_defs`
2623 remaining_defs[ref] = self._resolve_definition(ref, definitions) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2625 for cs in gather_result['deferred_discriminator_schemas']: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2626 discriminator = cs['metadata']['pydantic_internal_union_discriminator'] # pyright: ignore[reportTypedDictNotRequiredAccess] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2627 applied = _discriminated_union.apply_discriminator(cs.copy(), discriminator, remaining_defs) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2628 # Mutate the schema directly to have the discriminator applied
2629 cs.clear() # pyright: ignore[reportAttributeAccessIssue] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2630 cs.update(applied) # pyright: ignore 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2632 if remaining_defs: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2633 schema = core_schema.definitions_schema(schema=schema, definitions=[*remaining_defs.values()]) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2634 return schema 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2636 def _resolve_definition(self, ref: str, definitions: dict[str, CoreSchema]) -> CoreSchema: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2637 definition = definitions[ref] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2638 if definition['type'] != 'definition-ref': 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2639 return definition 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2641 # Some `'definition-ref'` schemas might act as "intermediate" references (e.g. when using
2642 # a PEP 695 type alias (which is referenceable) that references another PEP 695 type alias):
2643 visited: set[str] = set() 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2644 while definition['type'] == 'definition-ref': 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2645 schema_ref = definition['schema_ref'] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2646 if schema_ref in visited: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2647 raise PydanticUserError( 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2648 f'{ref} contains a circular reference to itself.', code='circular-reference-schema'
2649 )
2650 visited.add(schema_ref) 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2651 definition = definitions[schema_ref] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2652 return {**definition, 'ref': ref} # pyright: ignore[reportReturnType] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2655class _FieldNameStack: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2656 __slots__ = ('_stack',) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2658 def __init__(self) -> None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2659 self._stack: list[str] = [] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2661 @contextmanager 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2662 def push(self, field_name: str) -> Iterator[None]: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2663 self._stack.append(field_name) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2664 yield 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2665 self._stack.pop() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2667 def get(self) -> str | None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2668 if self._stack: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2669 return self._stack[-1] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2670 else:
2671 return None 1aeouxdgpvB
2674class _ModelTypeStack: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2675 __slots__ = ('_stack',) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2677 def __init__(self) -> None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2678 self._stack: list[type] = [] 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2680 @contextmanager 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2681 def push(self, type_obj: type) -> Iterator[None]: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2682 self._stack.append(type_obj) 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2683 yield 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2684 self._stack.pop() 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2686 def get(self) -> type | None: 1acekoquwxCfbhilmrsyzDELGHIJKMdjgnptvABF
2687 if self._stack: 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2688 return self._stack[-1] 1acekoquwxCfbhilmrsyzDEdjgnptvABF
2689 else:
2690 return None 1acekoquwxCfbhilmrsyzDEdjgnptvABF