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