Coverage for pydantic/_internal/_generate_schema.py: 95.63%
1158 statements
« prev ^ index » next coverage.py v7.5.4, created at 2024-07-03 19:29 +0000
« prev ^ index » next coverage.py v7.5.4, created at 2024-07-03 19:29 +0000
1"""Convert python types to pydantic-core schema."""
3from __future__ import annotations as _annotations 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
5import collections.abc 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
6import dataclasses 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
7import inspect 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
8import re 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
9import sys 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
10import typing 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
11import warnings 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
12from contextlib import ExitStack, contextmanager 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
13from copy import copy, deepcopy 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
14from enum import Enum 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
15from functools import partial 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
16from inspect import Parameter, _ParameterKind, signature 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
17from itertools import chain 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
18from operator import attrgetter 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
19from types import FunctionType, LambdaType, MethodType 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
20from typing import ( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
21 TYPE_CHECKING,
22 Any,
23 Callable,
24 Dict,
25 Final,
26 ForwardRef,
27 Iterable,
28 Iterator,
29 Mapping,
30 Type,
31 TypeVar,
32 Union,
33 cast,
34 overload,
35)
36from warnings import warn 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
38from pydantic_core import CoreSchema, PydanticUndefined, core_schema, to_jsonable_python 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
39from typing_extensions import Annotated, Literal, TypeAliasType, TypedDict, get_args, get_origin, is_typeddict 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
41from ..aliases import AliasGenerator 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
42from ..annotated_handlers import GetCoreSchemaHandler, GetJsonSchemaHandler 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
43from ..config import ConfigDict, JsonDict, JsonEncoder 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
44from ..errors import PydanticSchemaGenerationError, PydanticUndefinedAnnotation, PydanticUserError 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
45from ..json_schema import JsonSchemaValue 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
46from ..version import version_short 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
47from ..warnings import PydanticDeprecatedSince20 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
48from . import _core_utils, _decorators, _discriminated_union, _known_annotated_metadata, _typing_extra 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
49from ._config import ConfigWrapper, ConfigWrapperStack 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
50from ._core_metadata import CoreMetadataHandler, build_metadata_dict 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
51from ._core_utils import ( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
52 CoreSchemaOrField,
53 collect_invalid_schemas,
54 define_expected_missing_refs,
55 get_ref,
56 get_type_ref,
57 is_function_with_inner_schema,
58 is_list_like_schema_with_items_schema,
59 simplify_schema_references,
60 validate_core_schema,
61)
62from ._decorators import ( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
63 Decorator,
64 DecoratorInfos,
65 FieldSerializerDecoratorInfo,
66 FieldValidatorDecoratorInfo,
67 ModelSerializerDecoratorInfo,
68 ModelValidatorDecoratorInfo,
69 RootValidatorDecoratorInfo,
70 ValidatorDecoratorInfo,
71 get_attribute_from_bases,
72 inspect_field_serializer,
73 inspect_model_serializer,
74 inspect_validator,
75)
76from ._docs_extraction import extract_docstrings_from_cls 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
77from ._fields import collect_dataclass_fields, get_type_hints_infer_globalns 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
78from ._forward_ref import PydanticRecursiveRef 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
79from ._generics import get_standard_typevars_map, has_instance_in_type, recursively_defined_type_refs, replace_types 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
80from ._mock_val_ser import MockCoreSchema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
81from ._schema_generation_shared import CallbackGetCoreSchemaHandler 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
82from ._typing_extra import is_finalvar, is_self_type 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
83from ._utils import lenient_issubclass 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
85if TYPE_CHECKING: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
86 from ..fields import ComputedFieldInfo, FieldInfo
87 from ..main import BaseModel
88 from ..types import Discriminator
89 from ..validators import FieldValidatorModes
90 from ._dataclasses import StandardDataclass
91 from ._schema_generation_shared import GetJsonSchemaFunction
93_SUPPORTS_TYPEDDICT = sys.version_info >= (3, 12) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
94_AnnotatedType = type(Annotated[int, 123]) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
96FieldDecoratorInfo = Union[ValidatorDecoratorInfo, FieldValidatorDecoratorInfo, FieldSerializerDecoratorInfo] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
97FieldDecoratorInfoType = TypeVar('FieldDecoratorInfoType', bound=FieldDecoratorInfo) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
98AnyFieldDecorator = Union[ 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
99 Decorator[ValidatorDecoratorInfo],
100 Decorator[FieldValidatorDecoratorInfo],
101 Decorator[FieldSerializerDecoratorInfo],
102]
104ModifyCoreSchemaWrapHandler = GetCoreSchemaHandler 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
105GetCoreSchemaFunction = Callable[[Any, ModifyCoreSchemaWrapHandler], core_schema.CoreSchema] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
107TUPLE_TYPES: list[type] = [tuple, typing.Tuple] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
108LIST_TYPES: list[type] = [list, typing.List, collections.abc.MutableSequence] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
109SET_TYPES: list[type] = [set, typing.Set, collections.abc.MutableSet] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
110FROZEN_SET_TYPES: list[type] = [frozenset, typing.FrozenSet, collections.abc.Set] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
111DICT_TYPES: list[type] = [dict, typing.Dict, collections.abc.MutableMapping, collections.abc.Mapping] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
114def check_validator_fields_against_field_name( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
115 info: FieldDecoratorInfo,
116 field: str,
117) -> bool:
118 """Check if field name is in validator fields.
120 Args:
121 info: The field info.
122 field: The field name to check.
124 Returns:
125 `True` if field name is in validator fields, `False` otherwise.
126 """
127 if '*' in info.fields: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
128 return True 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
129 for v_field_name in info.fields: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
130 if v_field_name == field: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
131 return True 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
132 return False 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
135def check_decorator_fields_exist(decorators: Iterable[AnyFieldDecorator], fields: Iterable[str]) -> None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
136 """Check if the defined fields in decorators exist in `fields` param.
138 It ignores the check for a decorator if the decorator has `*` as field or `check_fields=False`.
140 Args:
141 decorators: An iterable of decorators.
142 fields: An iterable of fields name.
144 Raises:
145 PydanticUserError: If one of the field names does not exist in `fields` param.
146 """
147 fields = set(fields) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
148 for dec in decorators: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
149 if '*' in dec.info.fields: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
150 continue 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
151 if dec.info.check_fields is False: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
152 continue 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
153 for field in dec.info.fields: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
154 if field not in fields: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
155 raise PydanticUserError( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
156 f'Decorators defined with incorrect fields: {dec.cls_ref}.{dec.cls_var_name}'
157 " (use check_fields=False if you're inheriting from the model and intended this)",
158 code='decorator-missing-field',
159 )
162def filter_field_decorator_info_by_field( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
163 validator_functions: Iterable[Decorator[FieldDecoratorInfoType]], field: str
164) -> list[Decorator[FieldDecoratorInfoType]]:
165 return [dec for dec in validator_functions if check_validator_fields_against_field_name(dec.info, field)] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
168def apply_each_item_validators( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
169 schema: core_schema.CoreSchema,
170 each_item_validators: list[Decorator[ValidatorDecoratorInfo]],
171 field_name: str | None,
172) -> core_schema.CoreSchema:
173 # This V1 compatibility shim should eventually be removed
175 # push down any `each_item=True` validators
176 # note that this won't work for any Annotated types that get wrapped by a function validator
177 # but that's okay because that didn't exist in V1
178 if schema['type'] == 'nullable': 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
179 schema['schema'] = apply_each_item_validators(schema['schema'], each_item_validators, field_name) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
180 return schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
181 elif schema['type'] == 'tuple': 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
182 if (variadic_item_index := schema.get('variadic_item_index')) is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
183 schema['items_schema'][variadic_item_index] = apply_validators( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
184 schema['items_schema'][variadic_item_index], each_item_validators, field_name
185 )
186 elif is_list_like_schema_with_items_schema(schema): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
187 inner_schema = schema.get('items_schema', None) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
188 if inner_schema is None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
189 inner_schema = core_schema.any_schema() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
190 schema['items_schema'] = apply_validators(inner_schema, each_item_validators, field_name) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
191 elif schema['type'] == 'dict': 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
192 # push down any `each_item=True` validators onto dict _values_
193 # this is super arbitrary but it's the V1 behavior
194 inner_schema = schema.get('values_schema', None) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
195 if inner_schema is None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
196 inner_schema = core_schema.any_schema() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
197 schema['values_schema'] = apply_validators(inner_schema, each_item_validators, field_name) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
198 elif each_item_validators: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
199 raise TypeError( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
200 f"`@validator(..., each_item=True)` cannot be applied to fields with a schema of {schema['type']}"
201 )
202 return schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
205def modify_model_json_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
206 schema_or_field: CoreSchemaOrField,
207 handler: GetJsonSchemaHandler,
208 *,
209 cls: Any,
210 title: str | None = None,
211) -> JsonSchemaValue:
212 """Add title and description for model-like classes' JSON schema.
214 Args:
215 schema_or_field: The schema data to generate a JSON schema from.
216 handler: The `GetCoreSchemaHandler` instance.
217 cls: The model-like class.
218 title: The title to set for the model's schema, defaults to the model's name
220 Returns:
221 JsonSchemaValue: The updated JSON schema.
222 """
223 from ..dataclasses import is_pydantic_dataclass 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
224 from ..main import BaseModel 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
225 from ..root_model import RootModel 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
226 from ._dataclasses import is_builtin_dataclass 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
228 json_schema = handler(schema_or_field) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
229 original_schema = handler.resolve_ref_schema(json_schema) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
230 # Preserve the fact that definitions schemas should never have sibling keys:
231 if '$ref' in original_schema: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
232 ref = original_schema['$ref'] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
233 original_schema.clear() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
234 original_schema['allOf'] = [{'$ref': ref}] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
235 if title is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
236 original_schema['title'] = title 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
237 elif 'title' not in original_schema: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
238 original_schema['title'] = cls.__name__ 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
239 # BaseModel + Dataclass; don't use cls.__doc__ as it will contain the verbose class signature by default
240 docstring = None if cls is BaseModel or is_builtin_dataclass(cls) or is_pydantic_dataclass(cls) else cls.__doc__ 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
241 if docstring and 'description' not in original_schema: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
242 original_schema['description'] = inspect.cleandoc(docstring) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
243 elif issubclass(cls, RootModel) and cls.model_fields['root'].description: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
244 original_schema['description'] = cls.model_fields['root'].description 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
245 return json_schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
248JsonEncoders = Dict[Type[Any], JsonEncoder] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
251def _add_custom_serialization_from_json_encoders( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
252 json_encoders: JsonEncoders | None, tp: Any, schema: CoreSchema
253) -> CoreSchema:
254 """Iterate over the json_encoders and add the first matching encoder to the schema.
256 Args:
257 json_encoders: A dictionary of types and their encoder functions.
258 tp: The type to check for a matching encoder.
259 schema: The schema to add the encoder to.
260 """
261 if not json_encoders: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
262 return schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
263 if 'serialization' in schema: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
264 return schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
265 # Check the class type and its superclasses for a matching encoder
266 # Decimal.__class__.__mro__ (and probably other cases) doesn't include Decimal itself
267 # if the type is a GenericAlias (e.g. from list[int]) we need to use __class__ instead of .__mro__
268 for base in (tp, *getattr(tp, '__mro__', tp.__class__.__mro__)[:-1]): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
269 encoder = json_encoders.get(base) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
270 if encoder is None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
271 continue 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
273 warnings.warn( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
274 f'`json_encoders` is deprecated. See https://docs.pydantic.dev/{version_short()}/concepts/serialization/#custom-serializers for alternatives',
275 PydanticDeprecatedSince20,
276 )
278 # TODO: in theory we should check that the schema accepts a serialization key
279 schema['serialization'] = core_schema.plain_serializer_function_ser_schema(encoder, when_used='json') 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
280 return schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
282 return schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
285TypesNamespace = Union[Dict[str, Any], None] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
288class TypesNamespaceStack: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
289 """A stack of types namespaces."""
291 def __init__(self, types_namespace: TypesNamespace): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
292 self._types_namespace_stack: list[TypesNamespace] = [types_namespace] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
294 @property 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
295 def tail(self) -> TypesNamespace: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
296 return self._types_namespace_stack[-1] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
298 @contextmanager 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
299 def push(self, for_type: type[Any]): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
300 types_namespace = {**_typing_extra.get_cls_types_namespace(for_type), **(self.tail or {})} 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
301 self._types_namespace_stack.append(types_namespace) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
302 try: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
303 yield 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
304 finally:
305 self._types_namespace_stack.pop() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
308def _get_first_non_null(a: Any, b: Any) -> Any: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
309 """Return the first argument if it is not None, otherwise return the second argument.
311 Use case: serialization_alias (argument a) and alias (argument b) are both defined, and serialization_alias is ''.
312 This function will return serialization_alias, which is the first argument, even though it is an empty string.
313 """
314 return a if a is not None else b 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
317class GenerateSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
318 """Generate core schema for a Pydantic model, dataclass and types like `str`, `datetime`, ... ."""
320 __slots__ = ( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
321 '_config_wrapper_stack',
322 '_types_namespace_stack',
323 '_typevars_map',
324 'field_name_stack',
325 'model_type_stack',
326 'defs',
327 )
329 def __init__( 1eiacmpqyrzGHklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
330 self,
331 config_wrapper: ConfigWrapper,
332 types_namespace: dict[str, Any] | None,
333 typevars_map: dict[Any, Any] | None = None,
334 ) -> None:
335 # we need a stack for recursing into child models
336 self._config_wrapper_stack = ConfigWrapperStack(config_wrapper) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
337 self._types_namespace_stack = TypesNamespaceStack(types_namespace) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
338 self._typevars_map = typevars_map 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
339 self.field_name_stack = _FieldNameStack() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
340 self.model_type_stack = _ModelTypeStack() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
341 self.defs = _Definitions() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
343 @classmethod 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
344 def __from_parent( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
345 cls,
346 config_wrapper_stack: ConfigWrapperStack,
347 types_namespace_stack: TypesNamespaceStack,
348 model_type_stack: _ModelTypeStack,
349 typevars_map: dict[Any, Any] | None,
350 defs: _Definitions,
351 ) -> GenerateSchema:
352 obj = cls.__new__(cls) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
353 obj._config_wrapper_stack = config_wrapper_stack 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
354 obj._types_namespace_stack = types_namespace_stack 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
355 obj.model_type_stack = model_type_stack 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
356 obj._typevars_map = typevars_map 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
357 obj.field_name_stack = _FieldNameStack() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
358 obj.defs = defs 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
359 return obj 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
361 @property 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
362 def _config_wrapper(self) -> ConfigWrapper: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
363 return self._config_wrapper_stack.tail 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
365 @property 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
366 def _types_namespace(self) -> dict[str, Any] | None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
367 return self._types_namespace_stack.tail 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
369 @property 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
370 def _current_generate_schema(self) -> GenerateSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
371 cls = self._config_wrapper.schema_generator or GenerateSchema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
372 return cls.__from_parent( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
373 self._config_wrapper_stack,
374 self._types_namespace_stack,
375 self.model_type_stack,
376 self._typevars_map,
377 self.defs,
378 )
380 @property 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
381 def _arbitrary_types(self) -> bool: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
382 return self._config_wrapper.arbitrary_types_allowed 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
384 def str_schema(self) -> CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
385 """Generate a CoreSchema for `str`"""
386 return core_schema.str_schema() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
388 # the following methods can be overridden but should be considered
389 # unstable / private APIs
390 def _list_schema(self, tp: Any, items_type: Any) -> CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
391 return core_schema.list_schema(self.generate_schema(items_type)) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
393 def _dict_schema(self, tp: Any, keys_type: Any, values_type: Any) -> CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
394 return core_schema.dict_schema(self.generate_schema(keys_type), self.generate_schema(values_type)) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
396 def _set_schema(self, tp: Any, items_type: Any) -> CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
397 return core_schema.set_schema(self.generate_schema(items_type)) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
399 def _frozenset_schema(self, tp: Any, items_type: Any) -> CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
400 return core_schema.frozenset_schema(self.generate_schema(items_type)) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
402 def _arbitrary_type_schema(self, tp: Any) -> CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
403 if not isinstance(tp, type): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
404 warn( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
405 f'{tp!r} is not a Python type (it may be an instance of an object),'
406 ' Pydantic will allow any object with no validation since we cannot even'
407 ' enforce that the input is an instance of the given type.'
408 ' To get rid of this error wrap the type with `pydantic.SkipValidation`.',
409 UserWarning,
410 )
411 return core_schema.any_schema() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
412 return core_schema.is_instance_schema(tp) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
414 def _unknown_type_schema(self, obj: Any) -> CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
415 raise PydanticSchemaGenerationError( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
416 f'Unable to generate pydantic-core schema for {obj!r}. '
417 'Set `arbitrary_types_allowed=True` in the model_config to ignore this error'
418 ' or implement `__get_pydantic_core_schema__` on your type to fully support it.'
419 '\n\nIf you got this error by calling handler(<some type>) within'
420 ' `__get_pydantic_core_schema__` then you likely need to call'
421 ' `handler.generate_schema(<some type>)` since we do not call'
422 ' `__get_pydantic_core_schema__` on `<some type>` otherwise to avoid infinite recursion.'
423 )
425 def _apply_discriminator_to_union( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
426 self, schema: CoreSchema, discriminator: str | Discriminator | None
427 ) -> CoreSchema:
428 if discriminator is None: 428 ↛ 429line 428 didn't jump to line 429 because the condition on line 428 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
429 return schema
430 try: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
431 return _discriminated_union.apply_discriminator( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
432 schema,
433 discriminator,
434 )
435 except _discriminated_union.MissingDefinitionForUnionRef: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
436 # defer until defs are resolved
437 _discriminated_union.set_discriminator_in_metadata( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
438 schema,
439 discriminator,
440 )
441 return schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
443 class CollectedInvalid(Exception): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
444 pass 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
446 def clean_schema(self, schema: CoreSchema) -> CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
447 schema = self.collect_definitions(schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
448 schema = simplify_schema_references(schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
449 if collect_invalid_schemas(schema): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
450 raise self.CollectedInvalid() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
451 schema = _discriminated_union.apply_discriminators(schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
452 schema = validate_core_schema(schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
453 return schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
455 def collect_definitions(self, schema: CoreSchema) -> CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
456 ref = cast('str | None', schema.get('ref', None)) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
457 if ref: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
458 self.defs.definitions[ref] = schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
459 if 'ref' in schema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
460 schema = core_schema.definition_reference_schema(schema['ref']) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
461 return core_schema.definitions_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
462 schema,
463 list(self.defs.definitions.values()),
464 )
466 def _add_js_function(self, metadata_schema: CoreSchema, js_function: Callable[..., Any]) -> None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
467 metadata = CoreMetadataHandler(metadata_schema).metadata 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
468 pydantic_js_functions = metadata.setdefault('pydantic_js_functions', []) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
469 # because of how we generate core schemas for nested generic models
470 # we can end up adding `BaseModel.__get_pydantic_json_schema__` multiple times
471 # this check may fail to catch duplicates if the function is a `functools.partial`
472 # or something like that
473 # but if it does it'll fail by inserting the duplicate
474 if js_function not in pydantic_js_functions: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
475 pydantic_js_functions.append(js_function) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
477 def generate_schema( 1eiacmpqyrzGHklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
478 self,
479 obj: Any,
480 from_dunder_get_core_schema: bool = True,
481 ) -> core_schema.CoreSchema:
482 """Generate core schema.
484 Args:
485 obj: The object to generate core schema for.
486 from_dunder_get_core_schema: Whether to generate schema from either the
487 `__get_pydantic_core_schema__` function or `__pydantic_core_schema__` property.
489 Returns:
490 The generated core schema.
492 Raises:
493 PydanticUndefinedAnnotation:
494 If it is not possible to evaluate forward reference.
495 PydanticSchemaGenerationError:
496 If it is not possible to generate pydantic-core schema.
497 TypeError:
498 - If `alias_generator` returns a disallowed type (must be str, AliasPath or AliasChoices).
499 - If V1 style validator with `each_item=True` applied on a wrong field.
500 PydanticUserError:
501 - If `typing.TypedDict` is used instead of `typing_extensions.TypedDict` on Python < 3.12.
502 - If `__modify_schema__` method is used instead of `__get_pydantic_json_schema__`.
503 """
504 schema: CoreSchema | None = None 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
506 if from_dunder_get_core_schema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
507 from_property = self._generate_schema_from_property(obj, obj) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
508 if from_property is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
509 schema = from_property 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
511 if schema is None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
512 schema = self._generate_schema_inner(obj) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
514 metadata_js_function = _extract_get_pydantic_json_schema(obj, schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
515 if metadata_js_function is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
516 metadata_schema = resolve_original_schema(schema, self.defs.definitions) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
517 if metadata_schema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
518 self._add_js_function(metadata_schema, metadata_js_function) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
520 schema = _add_custom_serialization_from_json_encoders(self._config_wrapper.json_encoders, obj, schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
522 return schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
524 def _model_schema(self, cls: type[BaseModel]) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
525 """Generate schema for a Pydantic model."""
526 with self.defs.get_schema_or_ref(cls) as (model_ref, maybe_schema): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
527 if maybe_schema is not None: 527 ↛ 528line 527 didn't jump to line 528 because the condition on line 527 was never true1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
528 return maybe_schema
530 fields = cls.model_fields 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
531 decorators = cls.__pydantic_decorators__ 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
532 computed_fields = decorators.computed_fields 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
533 check_decorator_fields_exist( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
534 chain(
535 decorators.field_validators.values(),
536 decorators.field_serializers.values(),
537 decorators.validators.values(),
538 ),
539 {*fields.keys(), *computed_fields.keys()},
540 )
541 config_wrapper = ConfigWrapper(cls.model_config, check=False) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
542 core_config = config_wrapper.core_config(cls) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
543 title = self._get_model_title_from_config(cls, config_wrapper) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
544 metadata = build_metadata_dict(js_functions=[partial(modify_model_json_schema, cls=cls, title=title)]) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
546 model_validators = decorators.model_validators.values() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
548 extras_schema = None 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
549 if core_config.get('extra_fields_behavior') == 'allow': 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
550 assert cls.__mro__[0] is cls 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
551 assert cls.__mro__[-1] is object 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
552 for candidate_cls in cls.__mro__[:-1]: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
553 extras_annotation = getattr(candidate_cls, '__annotations__', {}).get('__pydantic_extra__', None) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
554 if extras_annotation is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
555 if isinstance(extras_annotation, str): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
556 extras_annotation = _typing_extra.eval_type_backport( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
557 _typing_extra._make_forward_ref(extras_annotation, is_argument=False, is_class=True),
558 self._types_namespace,
559 )
560 tp = get_origin(extras_annotation) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
561 if tp not in (Dict, dict): 561 ↛ 562line 561 didn't jump to line 562 because the condition on line 561 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
562 raise PydanticSchemaGenerationError(
563 'The type annotation for `__pydantic_extra__` must be `Dict[str, ...]`'
564 )
565 extra_items_type = self._get_args_resolving_forward_refs( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
566 extras_annotation,
567 required=True,
568 )[1]
569 if extra_items_type is not Any: 569 ↛ 552line 569 didn't jump to line 552 because the condition on line 569 was always true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
570 extras_schema = self.generate_schema(extra_items_type) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
571 break 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
573 with self._config_wrapper_stack.push(config_wrapper), self._types_namespace_stack.push(cls): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
574 self = self._current_generate_schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
575 if cls.__pydantic_root_model__: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
576 root_field = self._common_field_schema('root', fields['root'], decorators) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
577 inner_schema = root_field['schema'] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
578 inner_schema = apply_model_validators(inner_schema, model_validators, 'inner') 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
579 model_schema = core_schema.model_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
580 cls,
581 inner_schema,
582 custom_init=getattr(cls, '__pydantic_custom_init__', None),
583 root_model=True,
584 post_init=getattr(cls, '__pydantic_post_init__', None),
585 config=core_config,
586 ref=model_ref,
587 metadata=metadata,
588 )
589 else:
590 fields_schema: core_schema.CoreSchema = core_schema.model_fields_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
591 {k: self._generate_md_field_schema(k, v, decorators) for k, v in fields.items()},
592 computed_fields=[
593 self._computed_field_schema(d, decorators.field_serializers)
594 for d in computed_fields.values()
595 ],
596 extras_schema=extras_schema,
597 model_name=cls.__name__,
598 )
599 inner_schema = apply_validators(fields_schema, decorators.root_validators.values(), None) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
600 new_inner_schema = define_expected_missing_refs(inner_schema, recursively_defined_type_refs()) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
601 if new_inner_schema is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
602 inner_schema = new_inner_schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
603 inner_schema = apply_model_validators(inner_schema, model_validators, 'inner') 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
605 model_schema = core_schema.model_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
606 cls,
607 inner_schema,
608 custom_init=getattr(cls, '__pydantic_custom_init__', None),
609 root_model=False,
610 post_init=getattr(cls, '__pydantic_post_init__', None),
611 config=core_config,
612 ref=model_ref,
613 metadata=metadata,
614 )
616 schema = self._apply_model_serializers(model_schema, decorators.model_serializers.values()) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
617 schema = apply_model_validators(schema, model_validators, 'outer') 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
618 self.defs.definitions[model_ref] = schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
619 return core_schema.definition_reference_schema(model_ref) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
621 @staticmethod 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
622 def _get_model_title_from_config( 1eiacmpqyrzGHklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
623 model: type[BaseModel | StandardDataclass], config_wrapper: ConfigWrapper | None = None
624 ) -> str | None:
625 """Get the title of a model if `model_title_generator` or `title` are set in the config, else return None"""
626 if config_wrapper is None: 626 ↛ 627line 626 didn't jump to line 627 because the condition on line 626 was never true1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
627 return None
629 if config_wrapper.title: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
630 return config_wrapper.title 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
632 model_title_generator = config_wrapper.model_title_generator 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
633 if model_title_generator: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
634 title = model_title_generator(model) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
635 if not isinstance(title, str): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
636 raise TypeError(f'model_title_generator {model_title_generator} must return str, not {title.__class__}') 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
637 return title 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
639 return None 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
641 def _unpack_refs_defs(self, schema: CoreSchema) -> CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
642 """Unpack all 'definitions' schemas into `GenerateSchema.defs.definitions`
643 and return the inner schema.
644 """
646 def get_ref(s: CoreSchema) -> str: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
647 return s['ref'] # type: ignore 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
649 if schema['type'] == 'definitions': 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
650 self.defs.definitions.update({get_ref(s): s for s in schema['definitions']}) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
651 schema = schema['schema'] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
652 return schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
654 def _generate_schema_from_property(self, obj: Any, source: Any) -> core_schema.CoreSchema | None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
655 """Try to generate schema from either the `__get_pydantic_core_schema__` function or
656 `__pydantic_core_schema__` property.
658 Note: `__get_pydantic_core_schema__` takes priority so it can
659 decide whether to use a `__pydantic_core_schema__` attribute, or generate a fresh schema.
660 """
661 # avoid calling `__get_pydantic_core_schema__` if we've already visited this object
662 if is_self_type(obj): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
663 obj = self.model_type_stack.get() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
664 with self.defs.get_schema_or_ref(obj) as (_, maybe_schema): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
665 if maybe_schema is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
666 return maybe_schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
667 if obj is source: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
668 ref_mode = 'unpack' 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
669 else:
670 ref_mode = 'to-def' 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
672 schema: CoreSchema
674 if (get_schema := getattr(obj, '__get_pydantic_core_schema__', None)) is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
675 if len(inspect.signature(get_schema).parameters) == 1: 675 ↛ 677line 675 didn't jump to line 677 because the condition on line 675 was never true1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
676 # (source) -> CoreSchema
677 schema = get_schema(source)
678 else:
679 schema = get_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
680 source, CallbackGetCoreSchemaHandler(self._generate_schema_inner, self, ref_mode=ref_mode)
681 )
682 # fmt: off
683 elif ( 1eiacnsklfgMNhjbd
684 (existing_schema := getattr(obj, '__pydantic_core_schema__', None)) is not None
685 and not isinstance(existing_schema, MockCoreSchema)
686 and existing_schema.get('cls', None) == obj
687 ):
688 schema = existing_schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
689 # fmt: on
690 elif (validators := getattr(obj, '__get_validators__', None)) is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
691 warn( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
692 '`__get_validators__` is deprecated and will be removed, use `__get_pydantic_core_schema__` instead.',
693 PydanticDeprecatedSince20,
694 )
695 schema = core_schema.chain_schema([core_schema.with_info_plain_validator_function(v) for v in validators()]) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
696 else:
697 # we have no existing schema information on the property, exit early so that we can go generate a schema
698 return None 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
700 schema = self._unpack_refs_defs(schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
702 if is_function_with_inner_schema(schema): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
703 ref = schema['schema'].pop('ref', None) # pyright: ignore[reportCallIssue, reportArgumentType] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
704 if ref: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
705 schema['ref'] = ref 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
706 else:
707 ref = get_ref(schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
709 if ref: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
710 self.defs.definitions[ref] = schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
711 return core_schema.definition_reference_schema(ref) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
713 return schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
715 def _resolve_forward_ref(self, obj: Any) -> Any: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
716 # we assume that types_namespace has the target of forward references in its scope,
717 # but this could fail, for example, if calling Validator on an imported type which contains
718 # forward references to other types only defined in the module from which it was imported
719 # `Validator(SomeImportedTypeAliasWithAForwardReference)`
720 # or the equivalent for BaseModel
721 # class Model(BaseModel):
722 # x: SomeImportedTypeAliasWithAForwardReference
723 try: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
724 obj = _typing_extra.eval_type_backport(obj, globalns=self._types_namespace) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
725 except NameError as e: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
726 raise PydanticUndefinedAnnotation.from_name_error(e) from e 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
728 # if obj is still a ForwardRef, it means we can't evaluate it, raise PydanticUndefinedAnnotation
729 if isinstance(obj, ForwardRef): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
730 raise PydanticUndefinedAnnotation(obj.__forward_arg__, f'Unable to evaluate forward reference {obj}') 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
732 if self._typevars_map: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
733 obj = replace_types(obj, self._typevars_map) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
735 return obj 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
737 @overload 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
738 def _get_args_resolving_forward_refs(self, obj: Any, required: Literal[True]) -> tuple[Any, ...]: ... 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
740 @overload 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
741 def _get_args_resolving_forward_refs(self, obj: Any) -> tuple[Any, ...] | None: ... 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
743 def _get_args_resolving_forward_refs(self, obj: Any, required: bool = False) -> tuple[Any, ...] | None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
744 args = get_args(obj) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
745 if args: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
746 args = tuple([self._resolve_forward_ref(a) if isinstance(a, ForwardRef) else a for a in args]) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
747 elif required: # pragma: no cover 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
748 raise TypeError(f'Expected {obj} to have generic parameters but it had none')
749 return args 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
751 def _get_first_arg_or_any(self, obj: Any) -> Any: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
752 args = self._get_args_resolving_forward_refs(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
753 if not args: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
754 return Any 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
755 return args[0] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
757 def _get_first_two_args_or_any(self, obj: Any) -> tuple[Any, Any]: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
758 args = self._get_args_resolving_forward_refs(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
759 if not args: 759 ↛ 761line 759 didn't jump to line 761 because the condition on line 759 was always true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
760 return (Any, Any) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
761 if len(args) < 2:
762 origin = get_origin(obj)
763 raise TypeError(f'Expected two type arguments for {origin}, got 1')
764 return args[0], args[1]
766 def _generate_schema_inner(self, obj: Any) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
767 if isinstance(obj, _AnnotatedType): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
768 return self._annotated_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
770 if isinstance(obj, dict): 770 ↛ 772line 770 didn't jump to line 772 because the condition on line 770 was never true1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
771 # we assume this is already a valid schema
772 return obj # type: ignore[return-value]
774 if isinstance(obj, str): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
775 obj = ForwardRef(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
777 if isinstance(obj, ForwardRef): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
778 return self.generate_schema(self._resolve_forward_ref(obj)) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
780 from ..main import BaseModel 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
782 if lenient_issubclass(obj, BaseModel): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
783 with self.model_type_stack.push(obj): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
784 return self._model_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
786 if isinstance(obj, PydanticRecursiveRef): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
787 return core_schema.definition_reference_schema(schema_ref=obj.type_ref) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
789 return self.match_type(obj) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
791 def match_type(self, obj: Any) -> core_schema.CoreSchema: # noqa: C901 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
792 """Main mapping of types to schemas.
794 The general structure is a series of if statements starting with the simple cases
795 (non-generic primitive types) and then handling generics and other more complex cases.
797 Each case either generates a schema directly, calls into a public user-overridable method
798 (like `GenerateSchema.tuple_variable_schema`) or calls into a private method that handles some
799 boilerplate before calling into the user-facing method (e.g. `GenerateSchema._tuple_schema`).
801 The idea is that we'll evolve this into adding more and more user facing methods over time
802 as they get requested and we figure out what the right API for them is.
803 """
804 if obj is str: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
805 return self.str_schema() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
806 elif obj is bytes: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
807 return core_schema.bytes_schema() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
808 elif obj is int: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
809 return core_schema.int_schema() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
810 elif obj is float: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
811 return core_schema.float_schema() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
812 elif obj is bool: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
813 return core_schema.bool_schema() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
814 elif obj is Any or obj is object: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
815 return core_schema.any_schema() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
816 elif obj is None or obj is _typing_extra.NoneType: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
817 return core_schema.none_schema() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
818 elif obj in TUPLE_TYPES: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
819 return self._tuple_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
820 elif obj in LIST_TYPES: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
821 return self._list_schema(obj, self._get_first_arg_or_any(obj)) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
822 elif obj in SET_TYPES: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
823 return self._set_schema(obj, self._get_first_arg_or_any(obj)) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
824 elif obj in FROZEN_SET_TYPES: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
825 return self._frozenset_schema(obj, self._get_first_arg_or_any(obj)) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
826 elif obj in DICT_TYPES: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
827 return self._dict_schema(obj, *self._get_first_two_args_or_any(obj)) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
828 elif isinstance(obj, TypeAliasType): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
829 return self._type_alias_type_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
830 elif obj is type: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
831 return self._type_schema() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
832 elif _typing_extra.is_callable_type(obj): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
833 return core_schema.callable_schema() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
834 elif _typing_extra.is_literal_type(obj): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
835 return self._literal_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
836 elif is_typeddict(obj): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
837 return self._typed_dict_schema(obj, None) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
838 elif _typing_extra.is_namedtuple(obj): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
839 return self._namedtuple_schema(obj, None) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
840 elif _typing_extra.is_new_type(obj): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
841 # NewType, can't use isinstance because it fails <3.10
842 return self.generate_schema(obj.__supertype__) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
843 elif obj == re.Pattern: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
844 return self._pattern_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
845 elif obj is collections.abc.Hashable or obj is typing.Hashable: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
846 return self._hashable_schema() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
847 elif isinstance(obj, typing.TypeVar): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
848 return self._unsubstituted_typevar_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
849 elif is_finalvar(obj): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
850 if obj is Final: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
851 return core_schema.any_schema() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
852 return self.generate_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
853 self._get_first_arg_or_any(obj),
854 )
855 elif isinstance(obj, (FunctionType, LambdaType, MethodType, partial)): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
856 return self._callable_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
857 elif inspect.isclass(obj) and issubclass(obj, Enum): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
858 from ._std_types_schema import get_enum_core_schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
860 return get_enum_core_schema(obj, self._config_wrapper.config_dict) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
862 if _typing_extra.is_dataclass(obj): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
863 return self._dataclass_schema(obj, None) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
864 res = self._get_prepare_pydantic_annotations_for_known_type(obj, ()) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
865 if res is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
866 source_type, annotations = res 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
867 return self._apply_annotations(source_type, annotations) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
869 origin = get_origin(obj) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
870 if origin is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
871 return self._match_generic_type(obj, origin) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
873 if self._arbitrary_types: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
874 return self._arbitrary_type_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
875 return self._unknown_type_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
877 def _match_generic_type(self, obj: Any, origin: Any) -> CoreSchema: # noqa: C901 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
878 if isinstance(origin, TypeAliasType): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
879 return self._type_alias_type_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
881 # Need to handle generic dataclasses before looking for the schema properties because attribute accesses
882 # on _GenericAlias delegate to the origin type, so lose the information about the concrete parametrization
883 # As a result, currently, there is no way to cache the schema for generic dataclasses. This may be possible
884 # to resolve by modifying the value returned by `Generic.__class_getitem__`, but that is a dangerous game.
885 if _typing_extra.is_dataclass(origin): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
886 return self._dataclass_schema(obj, origin) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
887 if _typing_extra.is_namedtuple(origin): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
888 return self._namedtuple_schema(obj, origin) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
890 from_property = self._generate_schema_from_property(origin, obj) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
891 if from_property is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
892 return from_property 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
894 if _typing_extra.origin_is_union(origin): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
895 return self._union_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
896 elif origin in TUPLE_TYPES: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
897 return self._tuple_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
898 elif origin in LIST_TYPES: 898 ↛ 899line 898 didn't jump to line 899 because the condition on line 898 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
899 return self._list_schema(obj, self._get_first_arg_or_any(obj))
900 elif origin in SET_TYPES: 900 ↛ 901line 900 didn't jump to line 901 because the condition on line 900 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
901 return self._set_schema(obj, self._get_first_arg_or_any(obj))
902 elif origin in FROZEN_SET_TYPES: 902 ↛ 903line 902 didn't jump to line 903 because the condition on line 902 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
903 return self._frozenset_schema(obj, self._get_first_arg_or_any(obj))
904 elif origin in DICT_TYPES: 904 ↛ 905line 904 didn't jump to line 905 because the condition on line 904 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
905 return self._dict_schema(obj, *self._get_first_two_args_or_any(obj))
906 elif is_typeddict(origin): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
907 return self._typed_dict_schema(obj, origin) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
908 elif origin in (typing.Type, type): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
909 return self._subclass_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
910 elif origin in {typing.Sequence, collections.abc.Sequence}: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
911 return self._sequence_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
912 elif origin in {typing.Iterable, collections.abc.Iterable, typing.Generator, collections.abc.Generator}: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
913 return self._iterable_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
914 elif origin in (re.Pattern, typing.Pattern): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
915 return self._pattern_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
917 if self._arbitrary_types: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
918 return self._arbitrary_type_schema(origin) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
919 return self._unknown_type_schema(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
921 def _generate_td_field_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
922 self,
923 name: str,
924 field_info: FieldInfo,
925 decorators: DecoratorInfos,
926 *,
927 required: bool = True,
928 ) -> core_schema.TypedDictField:
929 """Prepare a TypedDictField to represent a model or typeddict field."""
930 common_field = self._common_field_schema(name, field_info, decorators) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
931 return core_schema.typed_dict_field( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
932 common_field['schema'],
933 required=False if not field_info.is_required() else required,
934 serialization_exclude=common_field['serialization_exclude'],
935 validation_alias=common_field['validation_alias'],
936 serialization_alias=common_field['serialization_alias'],
937 metadata=common_field['metadata'],
938 )
940 def _generate_md_field_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
941 self,
942 name: str,
943 field_info: FieldInfo,
944 decorators: DecoratorInfos,
945 ) -> core_schema.ModelField:
946 """Prepare a ModelField to represent a model field."""
947 common_field = self._common_field_schema(name, field_info, decorators) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
948 return core_schema.model_field( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
949 common_field['schema'],
950 serialization_exclude=common_field['serialization_exclude'],
951 validation_alias=common_field['validation_alias'],
952 serialization_alias=common_field['serialization_alias'],
953 frozen=common_field['frozen'],
954 metadata=common_field['metadata'],
955 )
957 def _generate_dc_field_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
958 self,
959 name: str,
960 field_info: FieldInfo,
961 decorators: DecoratorInfos,
962 ) -> core_schema.DataclassField:
963 """Prepare a DataclassField to represent the parameter/field, of a dataclass."""
964 common_field = self._common_field_schema(name, field_info, decorators) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
965 return core_schema.dataclass_field( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
966 name,
967 common_field['schema'],
968 init=field_info.init,
969 init_only=field_info.init_var or None,
970 kw_only=None if field_info.kw_only else False,
971 serialization_exclude=common_field['serialization_exclude'],
972 validation_alias=common_field['validation_alias'],
973 serialization_alias=common_field['serialization_alias'],
974 frozen=common_field['frozen'],
975 metadata=common_field['metadata'],
976 )
978 @staticmethod 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
979 def _apply_alias_generator_to_field_info( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
980 alias_generator: Callable[[str], str] | AliasGenerator, field_info: FieldInfo, field_name: str
981 ) -> None:
982 """Apply an alias_generator to aliases on a FieldInfo instance if appropriate.
984 Args:
985 alias_generator: A callable that takes a string and returns a string, or an AliasGenerator instance.
986 field_info: The FieldInfo instance to which the alias_generator is (maybe) applied.
987 field_name: The name of the field from which to generate the alias.
988 """
989 # Apply an alias_generator if
990 # 1. An alias is not specified
991 # 2. An alias is specified, but the priority is <= 1
992 if ( 1eiacnsklfghjbd
993 field_info.alias_priority is None
994 or field_info.alias_priority <= 1
995 or field_info.alias is None
996 or field_info.validation_alias is None
997 or field_info.serialization_alias is None
998 ):
999 alias, validation_alias, serialization_alias = None, None, None 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1001 if isinstance(alias_generator, AliasGenerator): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1002 alias, validation_alias, serialization_alias = alias_generator.generate_aliases(field_name) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1003 elif isinstance(alias_generator, Callable): 1003 ↛ 1011line 1003 didn't jump to line 1011 because the condition on line 1003 was always true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1004 alias = alias_generator(field_name) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1005 if not isinstance(alias, str): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1006 raise TypeError(f'alias_generator {alias_generator} must return str, not {alias.__class__}') 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1008 # if priority is not set, we set to 1
1009 # which supports the case where the alias_generator from a child class is used
1010 # to generate an alias for a field in a parent class
1011 if field_info.alias_priority is None or field_info.alias_priority <= 1: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1012 field_info.alias_priority = 1 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1014 # if the priority is 1, then we set the aliases to the generated alias
1015 if field_info.alias_priority == 1: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1016 field_info.serialization_alias = _get_first_non_null(serialization_alias, alias) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1017 field_info.validation_alias = _get_first_non_null(validation_alias, alias) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1018 field_info.alias = alias 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1020 # if any of the aliases are not set, then we set them to the corresponding generated alias
1021 if field_info.alias is None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1022 field_info.alias = alias 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1023 if field_info.serialization_alias is None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1024 field_info.serialization_alias = _get_first_non_null(serialization_alias, alias) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1025 if field_info.validation_alias is None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1026 field_info.validation_alias = _get_first_non_null(validation_alias, alias) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1028 @staticmethod 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1029 def _apply_alias_generator_to_computed_field_info( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1030 alias_generator: Callable[[str], str] | AliasGenerator,
1031 computed_field_info: ComputedFieldInfo,
1032 computed_field_name: str,
1033 ):
1034 """Apply an alias_generator to alias on a ComputedFieldInfo instance if appropriate.
1036 Args:
1037 alias_generator: A callable that takes a string and returns a string, or an AliasGenerator instance.
1038 computed_field_info: The ComputedFieldInfo instance to which the alias_generator is (maybe) applied.
1039 computed_field_name: The name of the computed field from which to generate the alias.
1040 """
1041 # Apply an alias_generator if
1042 # 1. An alias is not specified
1043 # 2. An alias is specified, but the priority is <= 1
1045 if ( 1eiacnshjbd
1046 computed_field_info.alias_priority is None
1047 or computed_field_info.alias_priority <= 1
1048 or computed_field_info.alias is None
1049 ):
1050 alias, validation_alias, serialization_alias = None, None, None 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1052 if isinstance(alias_generator, AliasGenerator): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1053 alias, validation_alias, serialization_alias = alias_generator.generate_aliases(computed_field_name) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1054 elif isinstance(alias_generator, Callable): 1054 ↛ 1062line 1054 didn't jump to line 1062 because the condition on line 1054 was always true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1055 alias = alias_generator(computed_field_name) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1056 if not isinstance(alias, str): 1056 ↛ 1057line 1056 didn't jump to line 1057 because the condition on line 1056 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1057 raise TypeError(f'alias_generator {alias_generator} must return str, not {alias.__class__}')
1059 # if priority is not set, we set to 1
1060 # which supports the case where the alias_generator from a child class is used
1061 # to generate an alias for a field in a parent class
1062 if computed_field_info.alias_priority is None or computed_field_info.alias_priority <= 1: 1062 ↛ 1068line 1062 didn't jump to line 1068 because the condition on line 1062 was always true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1063 computed_field_info.alias_priority = 1 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1065 # if the priority is 1, then we set the aliases to the generated alias
1066 # note that we use the serialization_alias with priority over alias, as computed_field
1067 # aliases are used for serialization only (not validation)
1068 if computed_field_info.alias_priority == 1: 1068 ↛ exitline 1068 didn't return from function '_apply_alias_generator_to_computed_field_info' because the condition on line 1068 was always true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1069 computed_field_info.alias = _get_first_non_null(serialization_alias, alias) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1071 @staticmethod 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1072 def _apply_field_title_generator_to_field_info( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1073 config_wrapper: ConfigWrapper, field_info: FieldInfo | ComputedFieldInfo, field_name: str
1074 ) -> None:
1075 """Apply a field_title_generator on a FieldInfo or ComputedFieldInfo instance if appropriate
1076 Args:
1077 config_wrapper: The config of the model
1078 field_info: The FieldInfo or ComputedField instance to which the title_generator is (maybe) applied.
1079 field_name: The name of the field from which to generate the title.
1080 """
1081 field_title_generator = field_info.field_title_generator or config_wrapper.field_title_generator 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1083 if field_title_generator is None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1084 return 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1086 if field_info.title is None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1087 title = field_title_generator(field_name, field_info) # type: ignore 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1088 if not isinstance(title, str): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1089 raise TypeError(f'field_title_generator {field_title_generator} must return str, not {title.__class__}') 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1091 field_info.title = title 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1093 def _common_field_schema( # C901 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1094 self, name: str, field_info: FieldInfo, decorators: DecoratorInfos
1095 ) -> _CommonField:
1096 # Update FieldInfo annotation if appropriate:
1097 from .. import AliasChoices, AliasPath 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1098 from ..fields import FieldInfo 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1100 if has_instance_in_type(field_info.annotation, (ForwardRef, str)): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1101 types_namespace = self._types_namespace 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1102 if self._typevars_map: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1103 types_namespace = (types_namespace or {}).copy() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1104 # Ensure that typevars get mapped to their concrete types:
1105 types_namespace.update({k.__name__: v for k, v in self._typevars_map.items()}) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1107 evaluated = _typing_extra.eval_type_lenient(field_info.annotation, types_namespace) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1108 if evaluated is not field_info.annotation and not has_instance_in_type(evaluated, PydanticRecursiveRef): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1109 new_field_info = FieldInfo.from_annotation(evaluated) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1110 field_info.annotation = new_field_info.annotation 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1112 # Handle any field info attributes that may have been obtained from now-resolved annotations
1113 for k, v in new_field_info._attributes_set.items(): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1114 # If an attribute is already set, it means it was set by assigning to a call to Field (or just a
1115 # default value), and that should take the highest priority. So don't overwrite existing attributes.
1116 # We skip over "attributes" that are present in the metadata_lookup dict because these won't
1117 # actually end up as attributes of the `FieldInfo` instance.
1118 if k not in field_info._attributes_set and k not in field_info.metadata_lookup: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1119 setattr(field_info, k, v) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1121 # Finally, ensure the field info also reflects all the `_attributes_set` that are actually metadata.
1122 field_info.metadata = [*new_field_info.metadata, *field_info.metadata] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1124 source_type, annotations = field_info.annotation, field_info.metadata 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1126 def set_discriminator(schema: CoreSchema) -> CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1127 schema = self._apply_discriminator_to_union(schema, field_info.discriminator) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1128 return schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1130 with self.field_name_stack.push(name): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1131 if field_info.discriminator is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1132 schema = self._apply_annotations(source_type, annotations, transform_inner_schema=set_discriminator) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1133 else:
1134 schema = self._apply_annotations( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1135 source_type,
1136 annotations,
1137 )
1139 # This V1 compatibility shim should eventually be removed
1140 # push down any `each_item=True` validators
1141 # note that this won't work for any Annotated types that get wrapped by a function validator
1142 # but that's okay because that didn't exist in V1
1143 this_field_validators = filter_field_decorator_info_by_field(decorators.validators.values(), name) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1144 if _validators_require_validate_default(this_field_validators): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1145 field_info.validate_default = True 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1146 each_item_validators = [v for v in this_field_validators if v.info.each_item is True] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1147 this_field_validators = [v for v in this_field_validators if v not in each_item_validators] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1148 schema = apply_each_item_validators(schema, each_item_validators, name) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1150 schema = apply_validators(schema, filter_field_decorator_info_by_field(this_field_validators, name), name) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1151 schema = apply_validators( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1152 schema, filter_field_decorator_info_by_field(decorators.field_validators.values(), name), name
1153 )
1155 # the default validator needs to go outside of any other validators
1156 # so that it is the topmost validator for the field validator
1157 # which uses it to check if the field has a default value or not
1158 if not field_info.is_required(): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1159 schema = wrap_default(field_info, schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1161 schema = self._apply_field_serializers( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1162 schema, filter_field_decorator_info_by_field(decorators.field_serializers.values(), name)
1163 )
1164 self._apply_field_title_generator_to_field_info(self._config_wrapper, field_info, name) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1166 json_schema_updates = { 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1167 'title': field_info.title,
1168 'description': field_info.description,
1169 'deprecated': bool(field_info.deprecated) or field_info.deprecated == '' or None,
1170 'examples': to_jsonable_python(field_info.examples),
1171 }
1172 json_schema_updates = {k: v for k, v in json_schema_updates.items() if v is not None} 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1174 json_schema_extra = field_info.json_schema_extra 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1176 metadata = build_metadata_dict( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1177 js_annotation_functions=[get_json_schema_update_func(json_schema_updates, json_schema_extra)]
1178 )
1180 alias_generator = self._config_wrapper.alias_generator 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1181 if alias_generator is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1182 self._apply_alias_generator_to_field_info(alias_generator, field_info, name) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1184 if isinstance(field_info.validation_alias, (AliasChoices, AliasPath)): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1185 validation_alias = field_info.validation_alias.convert_to_aliases() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1186 else:
1187 validation_alias = field_info.validation_alias 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1189 return _common_field( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1190 schema,
1191 serialization_exclude=True if field_info.exclude else None,
1192 validation_alias=validation_alias,
1193 serialization_alias=field_info.serialization_alias,
1194 frozen=field_info.frozen,
1195 metadata=metadata,
1196 )
1198 def _union_schema(self, union_type: Any) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1199 """Generate schema for a Union."""
1200 args = self._get_args_resolving_forward_refs(union_type, required=True) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1201 choices: list[CoreSchema] = [] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1202 nullable = False 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1203 for arg in args: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1204 if arg is None or arg is _typing_extra.NoneType: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1205 nullable = True 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1206 else:
1207 choices.append(self.generate_schema(arg)) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1209 if len(choices) == 1: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1210 s = choices[0] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1211 else:
1212 choices_with_tags: list[CoreSchema | tuple[CoreSchema, str]] = [] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1213 for choice in choices: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1214 tag = choice.get('metadata', {}).get(_core_utils.TAGGED_UNION_TAG_KEY) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1215 if tag is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1216 choices_with_tags.append((choice, tag)) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1217 else:
1218 choices_with_tags.append(choice) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1219 s = core_schema.union_schema(choices_with_tags) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1221 if nullable: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1222 s = core_schema.nullable_schema(s) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1223 return s 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1225 def _type_alias_type_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1226 self,
1227 obj: Any, # TypeAliasType
1228 ) -> CoreSchema:
1229 with self.defs.get_schema_or_ref(obj) as (ref, maybe_schema): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1230 if maybe_schema is not None: 1230 ↛ 1231line 1230 didn't jump to line 1231 because the condition on line 1230 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1231 return maybe_schema
1233 origin = get_origin(obj) or obj 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1235 annotation = origin.__value__ 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1236 typevars_map = get_standard_typevars_map(obj) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1238 with self._types_namespace_stack.push(origin): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1239 annotation = _typing_extra.eval_type_lenient(annotation, self._types_namespace) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1240 annotation = replace_types(annotation, typevars_map) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1241 schema = self.generate_schema(annotation) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1242 assert schema['type'] != 'definitions' 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1243 schema['ref'] = ref # type: ignore 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1244 self.defs.definitions[ref] = schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1245 return core_schema.definition_reference_schema(ref) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1247 def _literal_schema(self, literal_type: Any) -> CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1248 """Generate schema for a Literal."""
1249 expected = _typing_extra.all_literal_values(literal_type) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1250 assert expected, f'literal "expected" cannot be empty, obj={literal_type}' 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1251 schema = core_schema.literal_schema(expected) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1253 if self._config_wrapper.use_enum_values and any(isinstance(v, Enum) for v in expected): 1253 ↛ exitline 1253 didn't finish the generator expression on line 12531eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1254 schema = core_schema.no_info_after_validator_function( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1255 lambda v: v.value if isinstance(v, Enum) else v, schema
1256 )
1258 return schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1260 def _typed_dict_schema(self, typed_dict_cls: Any, origin: Any) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1261 """Generate schema for a TypedDict.
1263 It is not possible to track required/optional keys in TypedDict without __required_keys__
1264 since TypedDict.__new__ erases the base classes (it replaces them with just `dict`)
1265 and thus we can track usage of total=True/False
1266 __required_keys__ was added in Python 3.9
1267 (https://github.com/miss-islington/cpython/blob/1e9939657dd1f8eb9f596f77c1084d2d351172fc/Doc/library/typing.rst?plain=1#L1546-L1548)
1268 however it is buggy
1269 (https://github.com/python/typing_extensions/blob/ac52ac5f2cb0e00e7988bae1e2a1b8257ac88d6d/src/typing_extensions.py#L657-L666).
1271 On 3.11 but < 3.12 TypedDict does not preserve inheritance information.
1273 Hence to avoid creating validators that do not do what users expect we only
1274 support typing.TypedDict on Python >= 3.12 or typing_extension.TypedDict on all versions
1275 """
1276 from ..fields import FieldInfo 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1278 with self.model_type_stack.push(typed_dict_cls), self.defs.get_schema_or_ref(typed_dict_cls) as ( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1279 typed_dict_ref,
1280 maybe_schema,
1281 ):
1282 if maybe_schema is not None: 1282 ↛ 1283line 1282 didn't jump to line 1283 because the condition on line 1282 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1283 return maybe_schema
1285 typevars_map = get_standard_typevars_map(typed_dict_cls) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1286 if origin is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1287 typed_dict_cls = origin 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1289 if not _SUPPORTS_TYPEDDICT and type(typed_dict_cls).__module__ == 'typing': 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1290 raise PydanticUserError( 1eiacmpqynsklfgtuABhjbdovwE
1291 'Please use `typing_extensions.TypedDict` instead of `typing.TypedDict` on Python < 3.12.',
1292 code='typed-dict-version',
1293 )
1295 try: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1296 config: ConfigDict | None = get_attribute_from_bases(typed_dict_cls, '__pydantic_config__') 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1297 except AttributeError: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1298 config = None 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1300 with self._config_wrapper_stack.push(config), self._types_namespace_stack.push(typed_dict_cls): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1301 core_config = self._config_wrapper.core_config(typed_dict_cls) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1303 self = self._current_generate_schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1305 required_keys: frozenset[str] = typed_dict_cls.__required_keys__ 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1307 fields: dict[str, core_schema.TypedDictField] = {} 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1309 decorators = DecoratorInfos.build(typed_dict_cls) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1311 if self._config_wrapper.use_attribute_docstrings: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1312 field_docstrings = extract_docstrings_from_cls(typed_dict_cls, use_inspect=True) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1313 else:
1314 field_docstrings = None 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1316 for field_name, annotation in get_type_hints_infer_globalns( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1317 typed_dict_cls, localns=self._types_namespace, include_extras=True
1318 ).items():
1319 annotation = replace_types(annotation, typevars_map) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1320 required = field_name in required_keys 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1322 if get_origin(annotation) == _typing_extra.Required: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1323 required = True 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1324 annotation = self._get_args_resolving_forward_refs( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1325 annotation,
1326 required=True,
1327 )[0]
1328 elif get_origin(annotation) == _typing_extra.NotRequired: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1329 required = False 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1330 annotation = self._get_args_resolving_forward_refs( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1331 annotation,
1332 required=True,
1333 )[0]
1335 field_info = FieldInfo.from_annotation(annotation) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1336 if ( 1eiacnsklfghjbd
1337 field_docstrings is not None
1338 and field_info.description is None
1339 and field_name in field_docstrings
1340 ):
1341 field_info.description = field_docstrings[field_name] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1342 self._apply_field_title_generator_to_field_info(self._config_wrapper, field_info, field_name) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1343 fields[field_name] = self._generate_td_field_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1344 field_name, field_info, decorators, required=required
1345 )
1347 title = self._get_model_title_from_config(typed_dict_cls, ConfigWrapper(config)) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1348 metadata = build_metadata_dict( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1349 js_functions=[partial(modify_model_json_schema, cls=typed_dict_cls, title=title)],
1350 typed_dict_cls=typed_dict_cls,
1351 )
1352 td_schema = core_schema.typed_dict_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1353 fields,
1354 computed_fields=[
1355 self._computed_field_schema(d, decorators.field_serializers)
1356 for d in decorators.computed_fields.values()
1357 ],
1358 ref=typed_dict_ref,
1359 metadata=metadata,
1360 config=core_config,
1361 )
1363 schema = self._apply_model_serializers(td_schema, decorators.model_serializers.values()) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1364 schema = apply_model_validators(schema, decorators.model_validators.values(), 'all') 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1365 self.defs.definitions[typed_dict_ref] = schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1366 return core_schema.definition_reference_schema(typed_dict_ref) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1368 def _namedtuple_schema(self, namedtuple_cls: Any, origin: Any) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1369 """Generate schema for a NamedTuple."""
1370 with self.model_type_stack.push(namedtuple_cls), self.defs.get_schema_or_ref(namedtuple_cls) as ( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1371 namedtuple_ref,
1372 maybe_schema,
1373 ):
1374 if maybe_schema is not None: 1374 ↛ 1375line 1374 didn't jump to line 1375 because the condition on line 1374 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1375 return maybe_schema
1376 typevars_map = get_standard_typevars_map(namedtuple_cls) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1377 if origin is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1378 namedtuple_cls = origin 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1380 annotations: dict[str, Any] = get_type_hints_infer_globalns( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1381 namedtuple_cls, include_extras=True, localns=self._types_namespace
1382 )
1383 if not annotations: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1384 # annotations is empty, happens if namedtuple_cls defined via collections.namedtuple(...)
1385 annotations = {k: Any for k in namedtuple_cls._fields} 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1387 if typevars_map: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1388 annotations = { 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1389 field_name: replace_types(annotation, typevars_map)
1390 for field_name, annotation in annotations.items()
1391 }
1393 arguments_schema = core_schema.arguments_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1394 [
1395 self._generate_parameter_schema(
1396 field_name, annotation, default=namedtuple_cls._field_defaults.get(field_name, Parameter.empty)
1397 )
1398 for field_name, annotation in annotations.items()
1399 ],
1400 metadata=build_metadata_dict(js_prefer_positional_arguments=True),
1401 )
1402 return core_schema.call_schema(arguments_schema, namedtuple_cls, ref=namedtuple_ref) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1404 def _generate_parameter_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1405 self,
1406 name: str,
1407 annotation: type[Any],
1408 default: Any = Parameter.empty,
1409 mode: Literal['positional_only', 'positional_or_keyword', 'keyword_only'] | None = None,
1410 ) -> core_schema.ArgumentsParameter:
1411 """Prepare a ArgumentsParameter to represent a field in a namedtuple or function signature."""
1412 from ..fields import FieldInfo 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1414 if default is Parameter.empty: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1415 field = FieldInfo.from_annotation(annotation) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1416 else:
1417 field = FieldInfo.from_annotated_attribute(annotation, default) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1418 assert field.annotation is not None, 'field.annotation should not be None when generating a schema' 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1419 source_type, annotations = field.annotation, field.metadata 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1420 with self.field_name_stack.push(name): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1421 schema = self._apply_annotations(source_type, annotations) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1423 if not field.is_required(): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1424 schema = wrap_default(field, schema) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1426 parameter_schema = core_schema.arguments_parameter(name, schema) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1427 if mode is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1428 parameter_schema['mode'] = mode 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1429 if field.alias is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1430 parameter_schema['alias'] = field.alias 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1431 else:
1432 alias_generator = self._config_wrapper.alias_generator 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1433 if isinstance(alias_generator, AliasGenerator) and alias_generator.alias is not None: 1433 ↛ 1434line 1433 didn't jump to line 1434 because the condition on line 1433 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1434 parameter_schema['alias'] = alias_generator.alias(name)
1435 elif isinstance(alias_generator, Callable): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1436 parameter_schema['alias'] = alias_generator(name) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1437 return parameter_schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1439 def _tuple_schema(self, tuple_type: Any) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1440 """Generate schema for a Tuple, e.g. `tuple[int, str]` or `tuple[int, ...]`."""
1441 # TODO: do we really need to resolve type vars here?
1442 typevars_map = get_standard_typevars_map(tuple_type) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1443 params = self._get_args_resolving_forward_refs(tuple_type) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1445 if typevars_map and params: 1445 ↛ 1446line 1445 didn't jump to line 1446 because the condition on line 1445 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1446 params = tuple(replace_types(param, typevars_map) for param in params)
1448 # NOTE: subtle difference: `tuple[()]` gives `params=()`, whereas `typing.Tuple[()]` gives `params=((),)`
1449 # This is only true for <3.11, on Python 3.11+ `typing.Tuple[()]` gives `params=()`
1450 if not params: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1451 if tuple_type in TUPLE_TYPES: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1452 return core_schema.tuple_schema([core_schema.any_schema()], variadic_item_index=0) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1453 else:
1454 # special case for `tuple[()]` which means `tuple[]` - an empty tuple
1455 return core_schema.tuple_schema([]) 1acmpqyrzGHnsfgtuABCDIJbdovwExFKL
1456 elif params[-1] is Ellipsis: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1457 if len(params) == 2: 1457 ↛ 1461line 1457 didn't jump to line 1461 because the condition on line 1457 was always true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1458 return core_schema.tuple_schema([self.generate_schema(params[0])], variadic_item_index=0) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1459 else:
1460 # TODO: something like https://github.com/pydantic/pydantic/issues/5952
1461 raise ValueError('Variable tuples can only have one type')
1462 elif len(params) == 1 and params[0] == (): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1463 # special case for `Tuple[()]` which means `Tuple[]` - an empty tuple
1464 # NOTE: This conditional can be removed when we drop support for Python 3.10.
1465 return core_schema.tuple_schema([]) 1eiacmpnsklfgtuhjbdov
1466 else:
1467 return core_schema.tuple_schema([self.generate_schema(param) for param in params]) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1469 def _type_schema(self) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1470 return core_schema.custom_error_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1471 core_schema.is_instance_schema(type),
1472 custom_error_type='is_type',
1473 custom_error_message='Input should be a type',
1474 )
1476 def _union_is_subclass_schema(self, union_type: Any) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1477 """Generate schema for `Type[Union[X, ...]]`."""
1478 args = self._get_args_resolving_forward_refs(union_type, required=True) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1479 return core_schema.union_schema([self.generate_schema(typing.Type[args]) for args in args]) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1481 def _subclass_schema(self, type_: Any) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1482 """Generate schema for a Type, e.g. `Type[int]`."""
1483 type_param = self._get_first_arg_or_any(type_) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1484 if type_param == Any: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1485 return self._type_schema() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1486 elif isinstance(type_param, typing.TypeVar): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1487 if type_param.__bound__: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1488 if _typing_extra.origin_is_union(get_origin(type_param.__bound__)): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1489 return self._union_is_subclass_schema(type_param.__bound__) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1490 return core_schema.is_subclass_schema(type_param.__bound__) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1491 elif type_param.__constraints__: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1492 return core_schema.union_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1493 [self.generate_schema(typing.Type[c]) for c in type_param.__constraints__]
1494 )
1495 else:
1496 return self._type_schema() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1497 elif _typing_extra.origin_is_union(get_origin(type_param)): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1498 return self._union_is_subclass_schema(type_param) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1499 else:
1500 return core_schema.is_subclass_schema(type_param) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1502 def _sequence_schema(self, sequence_type: Any) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1503 """Generate schema for a Sequence, e.g. `Sequence[int]`."""
1504 from ._std_types_schema import serialize_sequence_via_list 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1506 item_type = self._get_first_arg_or_any(sequence_type) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1507 item_type_schema = self.generate_schema(item_type) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1508 list_schema = core_schema.list_schema(item_type_schema) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1510 python_schema = core_schema.is_instance_schema(typing.Sequence, cls_repr='Sequence') 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1511 if item_type != Any: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1512 from ._validators import sequence_validator 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1514 python_schema = core_schema.chain_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1515 [python_schema, core_schema.no_info_wrap_validator_function(sequence_validator, list_schema)],
1516 )
1518 serialization = core_schema.wrap_serializer_function_ser_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1519 serialize_sequence_via_list, schema=item_type_schema, info_arg=True
1520 )
1521 return core_schema.json_or_python_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1522 json_schema=list_schema, python_schema=python_schema, serialization=serialization
1523 )
1525 def _iterable_schema(self, type_: Any) -> core_schema.GeneratorSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1526 """Generate a schema for an `Iterable`."""
1527 item_type = self._get_first_arg_or_any(type_) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1529 return core_schema.generator_schema(self.generate_schema(item_type)) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1531 def _pattern_schema(self, pattern_type: Any) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1532 from . import _validators 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1534 metadata = build_metadata_dict(js_functions=[lambda _1, _2: {'type': 'string', 'format': 'regex'}]) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1535 ser = core_schema.plain_serializer_function_ser_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1536 attrgetter('pattern'), when_used='json', return_schema=core_schema.str_schema()
1537 )
1538 if pattern_type == typing.Pattern or pattern_type == re.Pattern: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1539 # bare type
1540 return core_schema.no_info_plain_validator_function( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1541 _validators.pattern_either_validator, serialization=ser, metadata=metadata
1542 )
1544 param = self._get_args_resolving_forward_refs( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1545 pattern_type,
1546 required=True,
1547 )[0]
1548 if param is str: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1549 return core_schema.no_info_plain_validator_function( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1550 _validators.pattern_str_validator, serialization=ser, metadata=metadata
1551 )
1552 elif param is bytes: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1553 return core_schema.no_info_plain_validator_function( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1554 _validators.pattern_bytes_validator, serialization=ser, metadata=metadata
1555 )
1556 else:
1557 raise PydanticSchemaGenerationError(f'Unable to generate pydantic-core schema for {pattern_type!r}.') 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1559 def _hashable_schema(self) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1560 return core_schema.custom_error_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1561 core_schema.is_instance_schema(collections.abc.Hashable),
1562 custom_error_type='is_hashable',
1563 custom_error_message='Input should be hashable',
1564 )
1566 def _dataclass_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1567 self, dataclass: type[StandardDataclass], origin: type[StandardDataclass] | None
1568 ) -> core_schema.CoreSchema:
1569 """Generate schema for a dataclass."""
1570 with self.model_type_stack.push(dataclass), self.defs.get_schema_or_ref(dataclass) as ( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1571 dataclass_ref,
1572 maybe_schema,
1573 ):
1574 if maybe_schema is not None: 1574 ↛ 1575line 1574 didn't jump to line 1575 because the condition on line 1574 was never true1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1575 return maybe_schema
1577 typevars_map = get_standard_typevars_map(dataclass) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1578 if origin is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1579 dataclass = origin 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1581 with ExitStack() as dataclass_bases_stack: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1582 # Pushing a namespace prioritises items already in the stack, so iterate though the MRO forwards
1583 for dataclass_base in dataclass.__mro__: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1584 if dataclasses.is_dataclass(dataclass_base): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1585 dataclass_bases_stack.enter_context(self._types_namespace_stack.push(dataclass_base)) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1587 # Pushing a config overwrites the previous config, so iterate though the MRO backwards
1588 config = None 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1589 for dataclass_base in reversed(dataclass.__mro__): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1590 if dataclasses.is_dataclass(dataclass_base): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1591 config = getattr(dataclass_base, '__pydantic_config__', None) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1592 dataclass_bases_stack.enter_context(self._config_wrapper_stack.push(config)) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1594 core_config = self._config_wrapper.core_config(dataclass) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1596 self = self._current_generate_schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1598 from ..dataclasses import is_pydantic_dataclass 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1600 if is_pydantic_dataclass(dataclass): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1601 fields = deepcopy(dataclass.__pydantic_fields__) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1602 if typevars_map: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1603 for field in fields.values(): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1604 field.apply_typevars_map(typevars_map, self._types_namespace) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1605 else:
1606 fields = collect_dataclass_fields( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1607 dataclass,
1608 self._types_namespace,
1609 typevars_map=typevars_map,
1610 )
1612 # disallow combination of init=False on a dataclass field and extra='allow' on a dataclass
1613 if self._config_wrapper_stack.tail.extra == 'allow': 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1614 # disallow combination of init=False on a dataclass field and extra='allow' on a dataclass
1615 for field_name, field in fields.items(): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1616 if field.init is False: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1617 raise PydanticUserError( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1618 f'Field {field_name} has `init=False` and dataclass has config setting `extra="allow"`. '
1619 f'This combination is not allowed.',
1620 code='dataclass-init-false-extra-allow',
1621 )
1623 decorators = dataclass.__dict__.get('__pydantic_decorators__') or DecoratorInfos.build(dataclass) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1624 # Move kw_only=False args to the start of the list, as this is how vanilla dataclasses work.
1625 # Note that when kw_only is missing or None, it is treated as equivalent to kw_only=True
1626 args = sorted( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1627 (self._generate_dc_field_schema(k, v, decorators) for k, v in fields.items()),
1628 key=lambda a: a.get('kw_only') is not False,
1629 )
1630 has_post_init = hasattr(dataclass, '__post_init__') 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1631 has_slots = hasattr(dataclass, '__slots__') 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1633 args_schema = core_schema.dataclass_args_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1634 dataclass.__name__,
1635 args,
1636 computed_fields=[
1637 self._computed_field_schema(d, decorators.field_serializers)
1638 for d in decorators.computed_fields.values()
1639 ],
1640 collect_init_only=has_post_init,
1641 )
1643 inner_schema = apply_validators(args_schema, decorators.root_validators.values(), None) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1645 model_validators = decorators.model_validators.values() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1646 inner_schema = apply_model_validators(inner_schema, model_validators, 'inner') 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1648 title = self._get_model_title_from_config(dataclass, ConfigWrapper(config)) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1649 metadata = build_metadata_dict( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1650 js_functions=[partial(modify_model_json_schema, cls=dataclass, title=title)]
1651 )
1653 dc_schema = core_schema.dataclass_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1654 dataclass,
1655 inner_schema,
1656 post_init=has_post_init,
1657 ref=dataclass_ref,
1658 fields=[field.name for field in dataclasses.fields(dataclass)],
1659 slots=has_slots,
1660 config=core_config,
1661 metadata=metadata,
1662 )
1663 schema = self._apply_model_serializers(dc_schema, decorators.model_serializers.values()) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1664 schema = apply_model_validators(schema, model_validators, 'outer') 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1665 self.defs.definitions[dataclass_ref] = schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1666 return core_schema.definition_reference_schema(dataclass_ref) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1668 # Type checkers seem to assume ExitStack may suppress exceptions and therefore
1669 # control flow can exit the `with` block without returning.
1670 assert False, 'Unreachable' 1acnfgbd
1672 def _callable_schema(self, function: Callable[..., Any]) -> core_schema.CallSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1673 """Generate schema for a Callable.
1675 TODO support functional validators once we support them in Config
1676 """
1677 sig = signature(function) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1679 type_hints = _typing_extra.get_function_type_hints(function, types_namespace=self._types_namespace) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1681 mode_lookup: dict[_ParameterKind, Literal['positional_only', 'positional_or_keyword', 'keyword_only']] = { 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1682 Parameter.POSITIONAL_ONLY: 'positional_only',
1683 Parameter.POSITIONAL_OR_KEYWORD: 'positional_or_keyword',
1684 Parameter.KEYWORD_ONLY: 'keyword_only',
1685 }
1687 arguments_list: list[core_schema.ArgumentsParameter] = [] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1688 var_args_schema: core_schema.CoreSchema | None = None 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1689 var_kwargs_schema: core_schema.CoreSchema | None = None 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1691 for name, p in sig.parameters.items(): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1692 if p.annotation is sig.empty: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1693 annotation = typing.cast(Any, Any) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1694 else:
1695 annotation = type_hints[name] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1697 parameter_mode = mode_lookup.get(p.kind) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1698 if parameter_mode is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1699 arg_schema = self._generate_parameter_schema(name, annotation, p.default, parameter_mode) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1700 arguments_list.append(arg_schema) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1701 elif p.kind == Parameter.VAR_POSITIONAL: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1702 var_args_schema = self.generate_schema(annotation) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1703 else:
1704 assert p.kind == Parameter.VAR_KEYWORD, p.kind 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1705 var_kwargs_schema = self.generate_schema(annotation) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1707 return_schema: core_schema.CoreSchema | None = None 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1708 config_wrapper = self._config_wrapper 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1709 if config_wrapper.validate_return: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1710 return_hint = type_hints.get('return') 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1711 if return_hint is not None: 1711 ↛ 1714line 1711 didn't jump to line 1714 because the condition on line 1711 was always true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1712 return_schema = self.generate_schema(return_hint) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1714 return core_schema.call_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1715 core_schema.arguments_schema(
1716 arguments_list,
1717 var_args_schema=var_args_schema,
1718 var_kwargs_schema=var_kwargs_schema,
1719 populate_by_name=config_wrapper.populate_by_name,
1720 ),
1721 function,
1722 return_schema=return_schema,
1723 )
1725 def _unsubstituted_typevar_schema(self, typevar: typing.TypeVar) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1726 assert isinstance(typevar, typing.TypeVar) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1728 bound = typevar.__bound__ 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1729 constraints = typevar.__constraints__ 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1731 try: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1732 typevar_has_default = typevar.has_default() # type: ignore 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1733 except AttributeError: 1eiacmpqyrznsklfgtuABCDMNOPQRSTUhjbdovwExF
1734 # could still have a default if it's an old version of typing_extensions.TypeVar
1735 typevar_has_default = getattr(typevar, '__default__', None) is not None 1eiacmpqyrznsklfgtuABCDMNOPQRSTUhjbdovwExF
1737 if (bound is not None) + (len(constraints) != 0) + typevar_has_default > 1: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1738 raise NotImplementedError( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1739 'Pydantic does not support mixing more than one of TypeVar bounds, constraints and defaults'
1740 )
1742 if typevar_has_default: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1743 return self.generate_schema(typevar.__default__) # type: ignore 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1744 elif constraints: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1745 return self._union_schema(typing.Union[constraints]) # type: ignore 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1746 elif bound: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1747 schema = self.generate_schema(bound) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1748 schema['serialization'] = core_schema.wrap_serializer_function_ser_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1749 lambda x, h: h(x), schema=core_schema.any_schema()
1750 )
1751 return schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1752 else:
1753 return core_schema.any_schema() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1755 def _computed_field_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1756 self,
1757 d: Decorator[ComputedFieldInfo],
1758 field_serializers: dict[str, Decorator[FieldSerializerDecoratorInfo]],
1759 ) -> core_schema.ComputedField:
1760 try: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1761 return_type = _decorators.get_function_return_type(d.func, d.info.return_type, self._types_namespace) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1762 except NameError as e: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1763 raise PydanticUndefinedAnnotation.from_name_error(e) from e 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1764 if return_type is PydanticUndefined: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1765 raise PydanticUserError( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1766 'Computed field is missing return type annotation or specifying `return_type`'
1767 ' to the `@computed_field` decorator (e.g. `@computed_field(return_type=int|str)`)',
1768 code='model-field-missing-annotation',
1769 )
1771 return_type = replace_types(return_type, self._typevars_map) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1772 # Create a new ComputedFieldInfo so that different type parametrizations of the same
1773 # generic model's computed field can have different return types.
1774 d.info = dataclasses.replace(d.info, return_type=return_type) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1775 return_type_schema = self.generate_schema(return_type) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1776 # Apply serializers to computed field if there exist
1777 return_type_schema = self._apply_field_serializers( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1778 return_type_schema,
1779 filter_field_decorator_info_by_field(field_serializers.values(), d.cls_var_name),
1780 computed_field=True,
1781 )
1783 alias_generator = self._config_wrapper.alias_generator 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1784 if alias_generator is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1785 self._apply_alias_generator_to_computed_field_info( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1786 alias_generator=alias_generator, computed_field_info=d.info, computed_field_name=d.cls_var_name
1787 )
1788 self._apply_field_title_generator_to_field_info(self._config_wrapper, d.info, d.cls_var_name) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1790 def set_computed_field_metadata(schema: CoreSchemaOrField, handler: GetJsonSchemaHandler) -> JsonSchemaValue: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1791 json_schema = handler(schema) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1793 json_schema['readOnly'] = True 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1795 title = d.info.title 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1796 if title is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1797 json_schema['title'] = title 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1799 description = d.info.description 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1800 if description is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1801 json_schema['description'] = description 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1803 if d.info.deprecated or d.info.deprecated == '': 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1804 json_schema['deprecated'] = True 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1806 examples = d.info.examples 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1807 if examples is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1808 json_schema['examples'] = to_jsonable_python(examples) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1810 json_schema_extra = d.info.json_schema_extra 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1811 if json_schema_extra is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1812 add_json_schema_extra(json_schema, json_schema_extra) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1814 return json_schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1816 metadata = build_metadata_dict(js_annotation_functions=[set_computed_field_metadata]) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1817 return core_schema.computed_field( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1818 d.cls_var_name, return_schema=return_type_schema, alias=d.info.alias, metadata=metadata
1819 )
1821 def _annotated_schema(self, annotated_type: Any) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1822 """Generate schema for an Annotated type, e.g. `Annotated[int, Field(...)]` or `Annotated[int, Gt(0)]`."""
1823 from ..fields import FieldInfo 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1825 source_type, *annotations = self._get_args_resolving_forward_refs( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1826 annotated_type,
1827 required=True,
1828 )
1829 schema = self._apply_annotations(source_type, annotations) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1830 # put the default validator last so that TypeAdapter.get_default_value() works
1831 # even if there are function validators involved
1832 for annotation in annotations: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1833 if isinstance(annotation, FieldInfo): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1834 schema = wrap_default(annotation, schema) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1835 return schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1837 def _get_prepare_pydantic_annotations_for_known_type( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1838 self, obj: Any, annotations: tuple[Any, ...]
1839 ) -> tuple[Any, list[Any]] | None:
1840 from ._std_types_schema import PREPARE_METHODS 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1842 # Check for hashability
1843 try: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1844 hash(obj) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1845 except TypeError: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1846 # obj is definitely not a known type if this fails
1847 return None 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1849 for gen in PREPARE_METHODS: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1850 res = gen(obj, annotations, self._config_wrapper.config_dict) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1851 if res is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1852 return res 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1854 return None 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1856 def _apply_annotations( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1857 self,
1858 source_type: Any,
1859 annotations: list[Any],
1860 transform_inner_schema: Callable[[CoreSchema], CoreSchema] = lambda x: x,
1861 ) -> CoreSchema:
1862 """Apply arguments from `Annotated` or from `FieldInfo` to a schema.
1864 This gets called by `GenerateSchema._annotated_schema` but differs from it in that it does
1865 not expect `source_type` to be an `Annotated` object, it expects it to be the first argument of that
1866 (in other words, `GenerateSchema._annotated_schema` just unpacks `Annotated`, this process it).
1867 """
1868 annotations = list(_known_annotated_metadata.expand_grouped_metadata(annotations)) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1869 res = self._get_prepare_pydantic_annotations_for_known_type(source_type, tuple(annotations)) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1870 if res is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1871 source_type, annotations = res 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1873 pydantic_js_annotation_functions: list[GetJsonSchemaFunction] = [] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1875 def inner_handler(obj: Any) -> CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1876 from_property = self._generate_schema_from_property(obj, source_type) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1877 if from_property is None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1878 schema = self._generate_schema_inner(obj) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1879 else:
1880 schema = from_property 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1881 metadata_js_function = _extract_get_pydantic_json_schema(obj, schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1882 if metadata_js_function is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1883 metadata_schema = resolve_original_schema(schema, self.defs.definitions) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1884 if metadata_schema is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1885 self._add_js_function(metadata_schema, metadata_js_function) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1886 return transform_inner_schema(schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1888 get_inner_schema = CallbackGetCoreSchemaHandler(inner_handler, self) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1890 for annotation in annotations: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1891 if annotation is None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1892 continue 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1893 get_inner_schema = self._get_wrapped_inner_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1894 get_inner_schema, annotation, pydantic_js_annotation_functions
1895 )
1897 schema = get_inner_schema(source_type) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1898 if pydantic_js_annotation_functions: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1899 metadata = CoreMetadataHandler(schema).metadata 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1900 metadata.setdefault('pydantic_js_annotation_functions', []).extend(pydantic_js_annotation_functions) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1901 return _add_custom_serialization_from_json_encoders(self._config_wrapper.json_encoders, source_type, schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1903 def _apply_single_annotation(self, schema: core_schema.CoreSchema, metadata: Any) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1904 from ..fields import FieldInfo 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1906 if isinstance(metadata, FieldInfo): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1907 for field_metadata in metadata.metadata: 1907 ↛ 1908line 1907 didn't jump to line 1908 because the loop on line 1907 never started1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1908 schema = self._apply_single_annotation(schema, field_metadata)
1910 if metadata.discriminator is not None: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1911 schema = self._apply_discriminator_to_union(schema, metadata.discriminator) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1912 return schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1914 if schema['type'] == 'nullable': 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1915 # for nullable schemas, metadata is automatically applied to the inner schema
1916 inner = schema.get('schema', core_schema.any_schema()) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1917 inner = self._apply_single_annotation(inner, metadata) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1918 if inner: 1918 ↛ 1920line 1918 didn't jump to line 1920 because the condition on line 1918 was always true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1919 schema['schema'] = inner 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1920 return schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1922 original_schema = schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1923 ref = schema.get('ref', None) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1924 if ref is not None: 1924 ↛ 1925line 1924 didn't jump to line 1925 because the condition on line 1924 was never true1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1925 schema = schema.copy()
1926 new_ref = ref + f'_{repr(metadata)}'
1927 if new_ref in self.defs.definitions:
1928 return self.defs.definitions[new_ref]
1929 schema['ref'] = new_ref # type: ignore
1930 elif schema['type'] == 'definition-ref': 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1931 ref = schema['schema_ref'] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1932 if ref in self.defs.definitions: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1933 schema = self.defs.definitions[ref].copy() 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1934 new_ref = ref + f'_{repr(metadata)}' 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1935 if new_ref in self.defs.definitions: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1936 return self.defs.definitions[new_ref] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1937 schema['ref'] = new_ref # type: ignore 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1939 maybe_updated_schema = _known_annotated_metadata.apply_known_metadata(metadata, schema.copy()) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1941 if maybe_updated_schema is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1942 return maybe_updated_schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1943 return original_schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1945 def _apply_single_annotation_json_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1946 self, schema: core_schema.CoreSchema, metadata: Any
1947 ) -> core_schema.CoreSchema:
1948 from ..fields import FieldInfo 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1950 if isinstance(metadata, FieldInfo): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1951 for field_metadata in metadata.metadata: 1951 ↛ 1952line 1951 didn't jump to line 1952 because the loop on line 1951 never started1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1952 schema = self._apply_single_annotation_json_schema(schema, field_metadata)
1953 json_schema_update: JsonSchemaValue = {} 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1954 if metadata.title: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1955 json_schema_update['title'] = metadata.title 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1956 if metadata.description: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1957 json_schema_update['description'] = metadata.description 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1958 if metadata.examples: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1959 json_schema_update['examples'] = to_jsonable_python(metadata.examples) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1961 json_schema_extra = metadata.json_schema_extra 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1962 if json_schema_update or json_schema_extra: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1963 CoreMetadataHandler(schema).metadata.setdefault('pydantic_js_annotation_functions', []).append( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1964 get_json_schema_update_func(json_schema_update, json_schema_extra)
1965 )
1966 return schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1968 def _get_wrapped_inner_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1969 self,
1970 get_inner_schema: GetCoreSchemaHandler,
1971 annotation: Any,
1972 pydantic_js_annotation_functions: list[GetJsonSchemaFunction],
1973 ) -> CallbackGetCoreSchemaHandler:
1974 metadata_get_schema: GetCoreSchemaFunction = getattr(annotation, '__get_pydantic_core_schema__', None) or ( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1975 lambda source, handler: handler(source)
1976 )
1978 def new_handler(source: Any) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1979 schema = metadata_get_schema(source, get_inner_schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1980 schema = self._apply_single_annotation(schema, annotation) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1981 schema = self._apply_single_annotation_json_schema(schema, annotation) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1983 metadata_js_function = _extract_get_pydantic_json_schema(annotation, schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1984 if metadata_js_function is not None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1985 pydantic_js_annotation_functions.append(metadata_js_function) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1986 return schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1988 return CallbackGetCoreSchemaHandler(new_handler, self) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1990 def _apply_field_serializers( 1eiacmpqyrzGHklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1991 self,
1992 schema: core_schema.CoreSchema,
1993 serializers: list[Decorator[FieldSerializerDecoratorInfo]],
1994 computed_field: bool = False,
1995 ) -> core_schema.CoreSchema:
1996 """Apply field serializers to a schema."""
1997 if serializers: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
1998 schema = copy(schema) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
1999 if schema['type'] == 'definitions': 1999 ↛ 2000line 1999 didn't jump to line 2000 because the condition on line 1999 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2000 inner_schema = schema['schema']
2001 schema['schema'] = self._apply_field_serializers(inner_schema, serializers)
2002 return schema
2003 else:
2004 ref = typing.cast('str|None', schema.get('ref', None)) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2005 if ref is not None: 2005 ↛ 2006line 2005 didn't jump to line 2006 because the condition on line 2005 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2006 schema = core_schema.definition_reference_schema(ref)
2008 # use the last serializer to make it easy to override a serializer set on a parent model
2009 serializer = serializers[-1] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2010 is_field_serializer, info_arg = inspect_field_serializer( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2011 serializer.func, serializer.info.mode, computed_field=computed_field
2012 )
2014 try: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2015 return_type = _decorators.get_function_return_type( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2016 serializer.func, serializer.info.return_type, self._types_namespace
2017 )
2018 except NameError as e: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2019 raise PydanticUndefinedAnnotation.from_name_error(e) from e 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2021 if return_type is PydanticUndefined: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2022 return_schema = None 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2023 else:
2024 return_schema = self.generate_schema(return_type) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2026 if serializer.info.mode == 'wrap': 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2027 schema['serialization'] = core_schema.wrap_serializer_function_ser_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2028 serializer.func,
2029 is_field_serializer=is_field_serializer,
2030 info_arg=info_arg,
2031 return_schema=return_schema,
2032 when_used=serializer.info.when_used,
2033 )
2034 else:
2035 assert serializer.info.mode == 'plain' 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2036 schema['serialization'] = core_schema.plain_serializer_function_ser_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2037 serializer.func,
2038 is_field_serializer=is_field_serializer,
2039 info_arg=info_arg,
2040 return_schema=return_schema,
2041 when_used=serializer.info.when_used,
2042 )
2043 return schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2045 def _apply_model_serializers( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2046 self, schema: core_schema.CoreSchema, serializers: Iterable[Decorator[ModelSerializerDecoratorInfo]]
2047 ) -> core_schema.CoreSchema:
2048 """Apply model serializers to a schema."""
2049 ref: str | None = schema.pop('ref', None) # type: ignore 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2050 if serializers: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2051 serializer = list(serializers)[-1] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2052 info_arg = inspect_model_serializer(serializer.func, serializer.info.mode) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2054 try: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2055 return_type = _decorators.get_function_return_type( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2056 serializer.func, serializer.info.return_type, self._types_namespace
2057 )
2058 except NameError as e:
2059 raise PydanticUndefinedAnnotation.from_name_error(e) from e
2060 if return_type is PydanticUndefined: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2061 return_schema = None 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2062 else:
2063 return_schema = self.generate_schema(return_type) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2065 if serializer.info.mode == 'wrap': 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2066 ser_schema: core_schema.SerSchema = core_schema.wrap_serializer_function_ser_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2067 serializer.func,
2068 info_arg=info_arg,
2069 return_schema=return_schema,
2070 when_used=serializer.info.when_used,
2071 )
2072 else:
2073 # plain
2074 ser_schema = core_schema.plain_serializer_function_ser_schema( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2075 serializer.func,
2076 info_arg=info_arg,
2077 return_schema=return_schema,
2078 when_used=serializer.info.when_used,
2079 )
2080 schema['serialization'] = ser_schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2081 if ref: 2081 ↛ 2083line 2081 didn't jump to line 2083 because the condition on line 2081 was always true1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2082 schema['ref'] = ref # type: ignore 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2083 return schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2086_VALIDATOR_F_MATCH: Mapping[ 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2087 tuple[FieldValidatorModes, Literal['no-info', 'with-info']],
2088 Callable[[Callable[..., Any], core_schema.CoreSchema, str | None], core_schema.CoreSchema],
2089] = {
2090 ('before', 'no-info'): lambda f, schema, _: core_schema.no_info_before_validator_function(f, schema),
2091 ('after', 'no-info'): lambda f, schema, _: core_schema.no_info_after_validator_function(f, schema),
2092 ('plain', 'no-info'): lambda f, _1, _2: core_schema.no_info_plain_validator_function(f),
2093 ('wrap', 'no-info'): lambda f, schema, _: core_schema.no_info_wrap_validator_function(f, schema),
2094 ('before', 'with-info'): lambda f, schema, field_name: core_schema.with_info_before_validator_function(
2095 f, schema, field_name=field_name
2096 ),
2097 ('after', 'with-info'): lambda f, schema, field_name: core_schema.with_info_after_validator_function(
2098 f, schema, field_name=field_name
2099 ),
2100 ('plain', 'with-info'): lambda f, _, field_name: core_schema.with_info_plain_validator_function(
2101 f, field_name=field_name
2102 ),
2103 ('wrap', 'with-info'): lambda f, schema, field_name: core_schema.with_info_wrap_validator_function(
2104 f, schema, field_name=field_name
2105 ),
2106}
2109def apply_validators( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2110 schema: core_schema.CoreSchema,
2111 validators: Iterable[Decorator[RootValidatorDecoratorInfo]]
2112 | Iterable[Decorator[ValidatorDecoratorInfo]]
2113 | Iterable[Decorator[FieldValidatorDecoratorInfo]],
2114 field_name: str | None,
2115) -> core_schema.CoreSchema:
2116 """Apply validators to a schema.
2118 Args:
2119 schema: The schema to apply validators on.
2120 validators: An iterable of validators.
2121 field_name: The name of the field if validators are being applied to a model field.
2123 Returns:
2124 The updated schema.
2125 """
2126 for validator in validators: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2127 info_arg = inspect_validator(validator.func, validator.info.mode) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2128 val_type = 'with-info' if info_arg else 'no-info' 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2130 schema = _VALIDATOR_F_MATCH[(validator.info.mode, val_type)](validator.func, schema, field_name) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2131 return schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2134def _validators_require_validate_default(validators: Iterable[Decorator[ValidatorDecoratorInfo]]) -> bool: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2135 """In v1, if any of the validators for a field had `always=True`, the default value would be validated.
2137 This serves as an auxiliary function for re-implementing that logic, by looping over a provided
2138 collection of (v1-style) ValidatorDecoratorInfo's and checking if any of them have `always=True`.
2140 We should be able to drop this function and the associated logic calling it once we drop support
2141 for v1-style validator decorators. (Or we can extend it and keep it if we add something equivalent
2142 to the v1-validator `always` kwarg to `field_validator`.)
2143 """
2144 for validator in validators: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2145 if validator.info.always: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2146 return True 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2147 return False 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2150def apply_model_validators( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2151 schema: core_schema.CoreSchema,
2152 validators: Iterable[Decorator[ModelValidatorDecoratorInfo]],
2153 mode: Literal['inner', 'outer', 'all'],
2154) -> core_schema.CoreSchema:
2155 """Apply model validators to a schema.
2157 If mode == 'inner', only "before" validators are applied
2158 If mode == 'outer', validators other than "before" are applied
2159 If mode == 'all', all validators are applied
2161 Args:
2162 schema: The schema to apply validators on.
2163 validators: An iterable of validators.
2164 mode: The validator mode.
2166 Returns:
2167 The updated schema.
2168 """
2169 ref: str | None = schema.pop('ref', None) # type: ignore 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2170 for validator in validators: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2171 if mode == 'inner' and validator.info.mode != 'before': 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2172 continue 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2173 if mode == 'outer' and validator.info.mode == 'before': 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2174 continue 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2175 info_arg = inspect_validator(validator.func, validator.info.mode) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2176 if validator.info.mode == 'wrap': 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2177 if info_arg: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2178 schema = core_schema.with_info_wrap_validator_function(function=validator.func, schema=schema) 1rzGHCDIJxFKL
2179 else:
2180 schema = core_schema.no_info_wrap_validator_function(function=validator.func, schema=schema) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2181 elif validator.info.mode == 'before': 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2182 if info_arg: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2183 schema = core_schema.with_info_before_validator_function(function=validator.func, schema=schema) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2184 else:
2185 schema = core_schema.no_info_before_validator_function(function=validator.func, schema=schema) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2186 else:
2187 assert validator.info.mode == 'after' 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2188 if info_arg: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2189 schema = core_schema.with_info_after_validator_function(function=validator.func, schema=schema) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2190 else:
2191 schema = core_schema.no_info_after_validator_function(function=validator.func, schema=schema) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2192 if ref: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2193 schema['ref'] = ref # type: ignore 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2194 return schema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2197def wrap_default(field_info: FieldInfo, schema: core_schema.CoreSchema) -> core_schema.CoreSchema: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2198 """Wrap schema with default schema if default value or `default_factory` are available.
2200 Args:
2201 field_info: The field info object.
2202 schema: The schema to apply default on.
2204 Returns:
2205 Updated schema by default value or `default_factory`.
2206 """
2207 if field_info.default_factory: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2208 return core_schema.with_default_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2209 schema, default_factory=field_info.default_factory, validate_default=field_info.validate_default
2210 )
2211 elif field_info.default is not PydanticUndefined: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2212 return core_schema.with_default_schema( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2213 schema, default=field_info.default, validate_default=field_info.validate_default
2214 )
2215 else:
2216 return schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2219def _extract_get_pydantic_json_schema(tp: Any, schema: CoreSchema) -> GetJsonSchemaFunction | None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2220 """Extract `__get_pydantic_json_schema__` from a type, handling the deprecated `__modify_schema__`."""
2221 js_modify_function = getattr(tp, '__get_pydantic_json_schema__', None) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2223 if hasattr(tp, '__modify_schema__'): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2224 from pydantic import BaseModel # circular reference 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2226 has_custom_v2_modify_js_func = ( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2227 js_modify_function is not None
2228 and BaseModel.__get_pydantic_json_schema__.__func__ # type: ignore
2229 not in (js_modify_function, getattr(js_modify_function, '__func__', None))
2230 )
2232 if not has_custom_v2_modify_js_func: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2233 cls_name = getattr(tp, '__name__', None) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2234 raise PydanticUserError( 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2235 f'The `__modify_schema__` method is not supported in Pydantic v2. '
2236 f'Use `__get_pydantic_json_schema__` instead{f" in class `{cls_name}`" if cls_name else ""}.',
2237 code='custom-json-schema',
2238 )
2240 # handle GenericAlias' but ignore Annotated which "lies" about its origin (in this case it would be `int`)
2241 if hasattr(tp, '__origin__') and not isinstance(tp, type(Annotated[int, 'placeholder'])): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2242 return _extract_get_pydantic_json_schema(tp.__origin__, schema) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2244 if js_modify_function is None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2245 return None 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2247 return js_modify_function 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2250def get_json_schema_update_func( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2251 json_schema_update: JsonSchemaValue, json_schema_extra: JsonDict | typing.Callable[[JsonDict], None] | None
2252) -> GetJsonSchemaFunction:
2253 def json_schema_update_func( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2254 core_schema_or_field: CoreSchemaOrField, handler: GetJsonSchemaHandler
2255 ) -> JsonSchemaValue:
2256 json_schema = {**handler(core_schema_or_field), **json_schema_update} 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2257 add_json_schema_extra(json_schema, json_schema_extra) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2258 return json_schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2260 return json_schema_update_func 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2263def add_json_schema_extra( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2264 json_schema: JsonSchemaValue, json_schema_extra: JsonDict | typing.Callable[[JsonDict], None] | None
2265):
2266 if isinstance(json_schema_extra, dict): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2267 json_schema.update(to_jsonable_python(json_schema_extra)) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2268 elif callable(json_schema_extra): 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2269 json_schema_extra(json_schema) 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2272class _CommonField(TypedDict): 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2273 schema: core_schema.CoreSchema 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2274 validation_alias: str | list[str | int] | list[list[str | int]] | None 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2275 serialization_alias: str | None 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2276 serialization_exclude: bool | None 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2277 frozen: bool | None 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2278 metadata: dict[str, Any] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2281def _common_field( 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2282 schema: core_schema.CoreSchema,
2283 *,
2284 validation_alias: str | list[str | int] | list[list[str | int]] | None = None,
2285 serialization_alias: str | None = None,
2286 serialization_exclude: bool | None = None,
2287 frozen: bool | None = None,
2288 metadata: Any = None,
2289) -> _CommonField:
2290 return { 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2291 'schema': schema,
2292 'validation_alias': validation_alias,
2293 'serialization_alias': serialization_alias,
2294 'serialization_exclude': serialization_exclude,
2295 'frozen': frozen,
2296 'metadata': metadata,
2297 }
2300class _Definitions: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2301 """Keeps track of references and definitions."""
2303 def __init__(self) -> None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2304 self.seen: set[str] = set() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2305 self.definitions: dict[str, core_schema.CoreSchema] = {} 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2307 @contextmanager 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2308 def get_schema_or_ref(self, tp: Any) -> Iterator[tuple[str, None] | tuple[str, CoreSchema]]: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2309 """Get a definition for `tp` if one exists.
2311 If a definition exists, a tuple of `(ref_string, CoreSchema)` is returned.
2312 If no definition exists yet, a tuple of `(ref_string, None)` is returned.
2314 Note that the returned `CoreSchema` will always be a `DefinitionReferenceSchema`,
2315 not the actual definition itself.
2317 This should be called for any type that can be identified by reference.
2318 This includes any recursive types.
2320 At present the following types can be named/recursive:
2322 - BaseModel
2323 - Dataclasses
2324 - TypedDict
2325 - TypeAliasType
2326 """
2327 ref = get_type_ref(tp) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2328 # return the reference if we're either (1) in a cycle or (2) it was already defined
2329 if ref in self.seen or ref in self.definitions: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2330 yield (ref, core_schema.definition_reference_schema(ref)) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2331 else:
2332 self.seen.add(ref) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2333 try: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2334 yield (ref, None) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2335 finally:
2336 self.seen.discard(ref) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2339def resolve_original_schema(schema: CoreSchema, definitions: dict[str, CoreSchema]) -> CoreSchema | None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2340 if schema['type'] == 'definition-ref': 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2341 return definitions.get(schema['schema_ref'], None) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2342 elif schema['type'] == 'definitions': 2342 ↛ 2343line 2342 didn't jump to line 2343 because the condition on line 2342 was never true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2343 return schema['schema']
2344 else:
2345 return schema 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2348class _FieldNameStack: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2349 __slots__ = ('_stack',) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2351 def __init__(self) -> None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2352 self._stack: list[str] = [] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2354 @contextmanager 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2355 def push(self, field_name: str) -> Iterator[None]: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2356 self._stack.append(field_name) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2357 yield 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2358 self._stack.pop() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2360 def get(self) -> str | None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2361 if self._stack: 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2362 return self._stack[-1] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2363 else:
2364 return None 1eamqrhbowx
2367class _ModelTypeStack: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2368 __slots__ = ('_stack',) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2370 def __init__(self) -> None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2371 self._stack: list[type] = [] 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2373 @contextmanager 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2374 def push(self, type_obj: type) -> Iterator[None]: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2375 self._stack.append(type_obj) 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2376 yield 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2377 self._stack.pop() 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2379 def get(self) -> type | None: 1eiacmpqyrzGHnsklfgtuABCDIJMNOPQRSTUVhjbdovwExFKL
2380 if self._stack: 2380 ↛ 2383line 2380 didn't jump to line 2383 because the condition on line 2380 was always true1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2381 return self._stack[-1] 1eiacmpqyrzGHnsklfgtuABCDIJhjbdovwExFKL
2382 else:
2383 return None