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