Coverage for pydantic/json_schema.py: 94.57%

1020 statements  

« prev     ^ index     » next       coverage.py v7.5.4, created at 2024-07-03 19:29 +0000

1""" 

2Usage docs: https://docs.pydantic.dev/2.5/concepts/json_schema/ 

3 

4The `json_schema` module contains classes and functions to allow the way [JSON Schema](https://json-schema.org/) 

5is generated to be customized. 

6 

7In general you shouldn't need to use this module directly; instead, you can use 

8[`BaseModel.model_json_schema`][pydantic.BaseModel.model_json_schema] and 

9[`TypeAdapter.json_schema`][pydantic.TypeAdapter.json_schema]. 

10""" 

11 

12from __future__ import annotations as _annotations 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

13 

14import dataclasses 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

15import inspect 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

16import math 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

17import re 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

18import warnings 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

19from collections import defaultdict 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

20from copy import deepcopy 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

21from dataclasses import is_dataclass 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

22from enum import Enum 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

23from typing import ( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

24 TYPE_CHECKING, 

25 Any, 

26 Callable, 

27 Counter, 

28 Dict, 

29 Hashable, 

30 Iterable, 

31 NewType, 

32 Pattern, 

33 Sequence, 

34 Tuple, 

35 TypeVar, 

36 Union, 

37 cast, 

38) 

39 

40import pydantic_core 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

41from pydantic_core import CoreSchema, PydanticOmit, core_schema, to_jsonable_python 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

42from pydantic_core.core_schema import ComputedField 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

43from typing_extensions import Annotated, Literal, TypeAlias, assert_never, deprecated, final 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

44 

45from pydantic.warnings import PydanticDeprecatedSince26 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

46 

47from ._internal import ( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

48 _config, 

49 _core_metadata, 

50 _core_utils, 

51 _decorators, 

52 _internal_dataclass, 

53 _mock_val_ser, 

54 _schema_generation_shared, 

55 _typing_extra, 

56) 

57from .annotated_handlers import GetJsonSchemaHandler 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

58from .config import JsonDict, JsonSchemaExtraCallable, JsonValue 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

59from .errors import PydanticInvalidForJsonSchema, PydanticSchemaGenerationError, PydanticUserError 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

60 

61if TYPE_CHECKING: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

62 from . import ConfigDict 

63 from ._internal._core_utils import CoreSchemaField, CoreSchemaOrField 

64 from ._internal._dataclasses import PydanticDataclass 

65 from ._internal._schema_generation_shared import GetJsonSchemaFunction 

66 from .main import BaseModel 

67 

68 

69CoreSchemaOrFieldType = Literal[core_schema.CoreSchemaType, core_schema.CoreSchemaFieldType] 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

70""" 1adejkpqrbfglmstuvMNOPQRSTchinowxy

71A type alias for defined schema types that represents a union of 

72`core_schema.CoreSchemaType` and 

73`core_schema.CoreSchemaFieldType`. 

74""" 

75 

76JsonSchemaValue = Dict[str, Any] 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

77""" 1adejkpqrbfglmstuvMNOPQRSTchinowxy

78A type alias for a JSON schema value. This is a dictionary of string keys to arbitrary JSON values. 

79""" 

80 

81JsonSchemaMode = Literal['validation', 'serialization'] 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

82""" 1adejkpqrbfglmstuvMNOPQRSTchinowxy

83A type alias that represents the mode of a JSON schema; either 'validation' or 'serialization'. 

84 

85For some types, the inputs to validation differ from the outputs of serialization. For example, 

86computed fields will only be present when serializing, and should not be provided when 

87validating. This flag provides a way to indicate whether you want the JSON schema required 

88for validation inputs, or that will be matched by serialization outputs. 

89""" 

90 

91_MODE_TITLE_MAPPING: dict[JsonSchemaMode, str] = {'validation': 'Input', 'serialization': 'Output'} 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

92 

93 

94@deprecated( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

95 '`update_json_schema` is deprecated, use a simple `my_dict.update(update_dict)` call instead.', 

96 category=None, 

97) 

98def update_json_schema(schema: JsonSchemaValue, updates: dict[str, Any]) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

99 """Update a JSON schema in-place by providing a dictionary of updates. 

100 

101 This function sets the provided key-value pairs in the schema and returns the updated schema. 

102 

103 Args: 

104 schema: The JSON schema to update. 

105 updates: A dictionary of key-value pairs to set in the schema. 

106 

107 Returns: 

108 The updated JSON schema. 

109 """ 

110 schema.update(updates) 

111 return schema 

112 

113 

114JsonSchemaWarningKind = Literal['skipped-choice', 'non-serializable-default'] 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

115""" 1adejkpqrbfglmstuvMNOPQRSTchinowxy

116A type alias representing the kinds of warnings that can be emitted during JSON schema generation. 

117 

118See [`GenerateJsonSchema.render_warning_message`][pydantic.json_schema.GenerateJsonSchema.render_warning_message] 

119for more details. 

120""" 

121 

122 

123class PydanticJsonSchemaWarning(UserWarning): 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

124 """This class is used to emit warnings produced during JSON schema generation. 

125 See the [`GenerateJsonSchema.emit_warning`][pydantic.json_schema.GenerateJsonSchema.emit_warning] and 

126 [`GenerateJsonSchema.render_warning_message`][pydantic.json_schema.GenerateJsonSchema.render_warning_message] 

127 methods for more details; these can be overridden to control warning behavior. 

128 """ 

129 

130 

131# ##### JSON Schema Generation ##### 

132DEFAULT_REF_TEMPLATE = '#/$defs/{model}' 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

133"""The default format string used to generate reference names.""" 1adejkpqrbfglmstuvMNOPQRSTchinowxy

134 

135# There are three types of references relevant to building JSON schemas: 

136# 1. core_schema "ref" values; these are not exposed as part of the JSON schema 

137# * these might look like the fully qualified path of a model, its id, or something similar 

138CoreRef = NewType('CoreRef', str) 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

139# 2. keys of the "definitions" object that will eventually go into the JSON schema 

140# * by default, these look like "MyModel", though may change in the presence of collisions 

141# * eventually, we may want to make it easier to modify the way these names are generated 

142DefsRef = NewType('DefsRef', str) 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

143# 3. the values corresponding to the "$ref" key in the schema 

144# * By default, these look like "#/$defs/MyModel", as in {"$ref": "#/$defs/MyModel"} 

145JsonRef = NewType('JsonRef', str) 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

146 

147CoreModeRef = Tuple[CoreRef, JsonSchemaMode] 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

148JsonSchemaKeyT = TypeVar('JsonSchemaKeyT', bound=Hashable) 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

149 

150 

151@dataclasses.dataclass(**_internal_dataclass.slots_true) 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

152class _DefinitionsRemapping: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

153 defs_remapping: dict[DefsRef, DefsRef] 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

154 json_remapping: dict[JsonRef, JsonRef] 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

155 

156 @staticmethod 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

157 def from_prioritized_choices( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

158 prioritized_choices: dict[DefsRef, list[DefsRef]], 

159 defs_to_json: dict[DefsRef, JsonRef], 

160 definitions: dict[DefsRef, JsonSchemaValue], 

161 ) -> _DefinitionsRemapping: 

162 """ 

163 This function should produce a remapping that replaces complex DefsRef with the simpler ones from the 

164 prioritized_choices such that applying the name remapping would result in an equivalent JSON schema. 

165 """ 

166 # We need to iteratively simplify the definitions until we reach a fixed point. 

167 # The reason for this is that outer definitions may reference inner definitions that get simplified 

168 # into an equivalent reference, and the outer definitions won't be equivalent until we've simplified 

169 # the inner definitions. 

170 copied_definitions = deepcopy(definitions) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

171 definitions_schema = {'$defs': copied_definitions} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

172 for _iter in range(100): # prevent an infinite loop in the case of a bug, 100 iterations should be enough 172 ↛ 201line 172 didn't jump to line 201 because the loop on line 172 didn't complete1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

173 # For every possible remapped DefsRef, collect all schemas that that DefsRef might be used for: 

174 schemas_for_alternatives: dict[DefsRef, list[JsonSchemaValue]] = defaultdict(list) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

175 for defs_ref in copied_definitions: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

176 alternatives = prioritized_choices[defs_ref] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

177 for alternative in alternatives: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

178 schemas_for_alternatives[alternative].append(copied_definitions[defs_ref]) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

179 

180 # Deduplicate the schemas for each alternative; the idea is that we only want to remap to a new DefsRef 

181 # if it introduces no ambiguity, i.e., there is only one distinct schema for that DefsRef. 

182 for defs_ref, schemas in schemas_for_alternatives.items(): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

183 schemas_for_alternatives[defs_ref] = _deduplicate_schemas(schemas_for_alternatives[defs_ref]) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

184 

185 # Build the remapping 

186 defs_remapping: dict[DefsRef, DefsRef] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

187 json_remapping: dict[JsonRef, JsonRef] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

188 for original_defs_ref in definitions: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

189 alternatives = prioritized_choices[original_defs_ref] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

190 # Pick the first alternative that has only one schema, since that means there is no collision 

191 remapped_defs_ref = next(x for x in alternatives if len(schemas_for_alternatives[x]) == 1) 191 ↛ exitline 191 didn't finish the generator expression on line 1911EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

192 defs_remapping[original_defs_ref] = remapped_defs_ref 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

193 json_remapping[defs_to_json[original_defs_ref]] = defs_to_json[remapped_defs_ref] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

194 remapping = _DefinitionsRemapping(defs_remapping, json_remapping) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

195 new_definitions_schema = remapping.remap_json_schema({'$defs': copied_definitions}) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

196 if definitions_schema == new_definitions_schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

197 # We've reached the fixed point 

198 return remapping 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

199 definitions_schema = new_definitions_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

200 

201 raise PydanticInvalidForJsonSchema('Failed to simplify the JSON schema definitions') 

202 

203 def remap_defs_ref(self, ref: DefsRef) -> DefsRef: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

204 return self.defs_remapping.get(ref, ref) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

205 

206 def remap_json_ref(self, ref: JsonRef) -> JsonRef: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

207 return self.json_remapping.get(ref, ref) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

208 

209 def remap_json_schema(self, schema: Any) -> Any: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

210 """ 

211 Recursively update the JSON schema replacing all $refs 

212 """ 

213 if isinstance(schema, str): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

214 # Note: this may not really be a JsonRef; we rely on having no collisions between JsonRefs and other strings 

215 return self.remap_json_ref(JsonRef(schema)) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

216 elif isinstance(schema, list): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

217 return [self.remap_json_schema(item) for item in schema] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

218 elif isinstance(schema, dict): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

219 for key, value in schema.items(): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

220 if key == '$ref' and isinstance(value, str): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

221 schema['$ref'] = self.remap_json_ref(JsonRef(value)) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

222 elif key == '$defs': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

223 schema['$defs'] = { 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

224 self.remap_defs_ref(DefsRef(key)): self.remap_json_schema(value) 

225 for key, value in schema['$defs'].items() 

226 } 

227 else: 

228 schema[key] = self.remap_json_schema(value) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

229 return schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

230 

231 

232class GenerateJsonSchema: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

233 """Usage docs: https://docs.pydantic.dev/2.8/concepts/json_schema/#customizing-the-json-schema-generation-process 

234 

235 A class for generating JSON schemas. 

236 

237 This class generates JSON schemas based on configured parameters. The default schema dialect 

238 is [https://json-schema.org/draft/2020-12/schema](https://json-schema.org/draft/2020-12/schema). 

239 The class uses `by_alias` to configure how fields with 

240 multiple names are handled and `ref_template` to format reference names. 

241 

242 Attributes: 

243 schema_dialect: The JSON schema dialect used to generate the schema. See 

244 [Declaring a Dialect](https://json-schema.org/understanding-json-schema/reference/schema.html#id4) 

245 in the JSON Schema documentation for more information about dialects. 

246 ignored_warning_kinds: Warnings to ignore when generating the schema. `self.render_warning_message` will 

247 do nothing if its argument `kind` is in `ignored_warning_kinds`; 

248 this value can be modified on subclasses to easily control which warnings are emitted. 

249 by_alias: Whether to use field aliases when generating the schema. 

250 ref_template: The format string used when generating reference names. 

251 core_to_json_refs: A mapping of core refs to JSON refs. 

252 core_to_defs_refs: A mapping of core refs to definition refs. 

253 defs_to_core_refs: A mapping of definition refs to core refs. 

254 json_to_defs_refs: A mapping of JSON refs to definition refs. 

255 definitions: Definitions in the schema. 

256 

257 Args: 

258 by_alias: Whether to use field aliases in the generated schemas. 

259 ref_template: The format string to use when generating reference names. 

260 

261 Raises: 

262 JsonSchemaError: If the instance of the class is inadvertently re-used after generating a schema. 

263 """ 

264 

265 schema_dialect = 'https://json-schema.org/draft/2020-12/schema' 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

266 

267 # `self.render_warning_message` will do nothing if its argument `kind` is in `ignored_warning_kinds`; 

268 # this value can be modified on subclasses to easily control which warnings are emitted 

269 ignored_warning_kinds: set[JsonSchemaWarningKind] = {'skipped-choice'} 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

270 

271 def __init__(self, by_alias: bool = True, ref_template: str = DEFAULT_REF_TEMPLATE): 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

272 self.by_alias = by_alias 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

273 self.ref_template = ref_template 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

274 

275 self.core_to_json_refs: dict[CoreModeRef, JsonRef] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

276 self.core_to_defs_refs: dict[CoreModeRef, DefsRef] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

277 self.defs_to_core_refs: dict[DefsRef, CoreModeRef] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

278 self.json_to_defs_refs: dict[JsonRef, DefsRef] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

279 

280 self.definitions: dict[DefsRef, JsonSchemaValue] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

281 self._config_wrapper_stack = _config.ConfigWrapperStack(_config.ConfigWrapper({})) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

282 

283 self._mode: JsonSchemaMode = 'validation' 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

284 

285 # The following includes a mapping of a fully-unique defs ref choice to a list of preferred 

286 # alternatives, which are generally simpler, such as only including the class name. 

287 # At the end of schema generation, we use these to produce a JSON schema with more human-readable 

288 # definitions, which would also work better in a generated OpenAPI client, etc. 

289 self._prioritized_defsref_choices: dict[DefsRef, list[DefsRef]] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

290 self._collision_counter: dict[str, int] = defaultdict(int) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

291 self._collision_index: dict[str, int] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

292 

293 self._schema_type_to_method = self.build_schema_type_to_method() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

294 

295 # When we encounter definitions we need to try to build them immediately 

296 # so that they are available schemas that reference them 

297 # But it's possible that CoreSchema was never going to be used 

298 # (e.g. because the CoreSchema that references short circuits is JSON schema generation without needing 

299 # the reference) so instead of failing altogether if we can't build a definition we 

300 # store the error raised and re-throw it if we end up needing that def 

301 self._core_defs_invalid_for_json_schema: dict[DefsRef, PydanticInvalidForJsonSchema] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

302 

303 # This changes to True after generating a schema, to prevent issues caused by accidental re-use 

304 # of a single instance of a schema generator 

305 self._used = False 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

306 

307 @property 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

308 def _config(self) -> _config.ConfigWrapper: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

309 return self._config_wrapper_stack.tail 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

310 

311 @property 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

312 def mode(self) -> JsonSchemaMode: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

313 if self._config.json_schema_mode_override is not None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

314 return self._config.json_schema_mode_override 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

315 else: 

316 return self._mode 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

317 

318 def build_schema_type_to_method( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

319 self, 

320 ) -> dict[CoreSchemaOrFieldType, Callable[[CoreSchemaOrField], JsonSchemaValue]]: 

321 """Builds a dictionary mapping fields to methods for generating JSON schemas. 

322 

323 Returns: 

324 A dictionary containing the mapping of `CoreSchemaOrFieldType` to a handler method. 

325 

326 Raises: 

327 TypeError: If no method has been defined for generating a JSON schema for a given pydantic core schema type. 

328 """ 

329 mapping: dict[CoreSchemaOrFieldType, Callable[[CoreSchemaOrField], JsonSchemaValue]] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

330 core_schema_types: list[CoreSchemaOrFieldType] = _typing_extra.all_literal_values( 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

331 CoreSchemaOrFieldType # type: ignore 

332 ) 

333 for key in core_schema_types: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

334 method_name = f"{key.replace('-', '_')}_schema" 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

335 try: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

336 mapping[key] = getattr(self, method_name) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

337 except AttributeError as e: # pragma: no cover 

338 raise TypeError( 

339 f'No method for generating JsonSchema for core_schema.type={key!r} ' 

340 f'(expected: {type(self).__name__}.{method_name})' 

341 ) from e 

342 return mapping 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

343 

344 def generate_definitions( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

345 self, inputs: Sequence[tuple[JsonSchemaKeyT, JsonSchemaMode, core_schema.CoreSchema]] 

346 ) -> tuple[dict[tuple[JsonSchemaKeyT, JsonSchemaMode], JsonSchemaValue], dict[DefsRef, JsonSchemaValue]]: 

347 """Generates JSON schema definitions from a list of core schemas, pairing the generated definitions with a 

348 mapping that links the input keys to the definition references. 

349 

350 Args: 

351 inputs: A sequence of tuples, where: 

352 

353 - The first element is a JSON schema key type. 

354 - The second element is the JSON mode: either 'validation' or 'serialization'. 

355 - The third element is a core schema. 

356 

357 Returns: 

358 A tuple where: 

359 

360 - The first element is a dictionary whose keys are tuples of JSON schema key type and JSON mode, and 

361 whose values are the JSON schema corresponding to that pair of inputs. (These schemas may have 

362 JsonRef references to definitions that are defined in the second returned element.) 

363 - The second element is a dictionary whose keys are definition references for the JSON schemas 

364 from the first returned element, and whose values are the actual JSON schema definitions. 

365 

366 Raises: 

367 PydanticUserError: Raised if the JSON schema generator has already been used to generate a JSON schema. 

368 """ 

369 if self._used: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

370 raise PydanticUserError( 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

371 'This JSON schema generator has already been used to generate a JSON schema. ' 

372 f'You must create a new instance of {type(self).__name__} to generate a new JSON schema.', 

373 code='json-schema-already-used', 

374 ) 

375 

376 for key, mode, schema in inputs: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

377 self._mode = mode 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

378 self.generate_inner(schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

379 

380 definitions_remapping = self._build_definitions_remapping() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

381 

382 json_schemas_map: dict[tuple[JsonSchemaKeyT, JsonSchemaMode], DefsRef] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

383 for key, mode, schema in inputs: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

384 self._mode = mode 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

385 json_schema = self.generate_inner(schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

386 json_schemas_map[(key, mode)] = definitions_remapping.remap_json_schema(json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

387 

388 json_schema = {'$defs': self.definitions} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

389 json_schema = definitions_remapping.remap_json_schema(json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

390 self._used = True 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

391 return json_schemas_map, _sort_json_schema(json_schema['$defs']) # type: ignore 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

392 

393 def generate(self, schema: CoreSchema, mode: JsonSchemaMode = 'validation') -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

394 """Generates a JSON schema for a specified schema in a specified mode. 

395 

396 Args: 

397 schema: A Pydantic model. 

398 mode: The mode in which to generate the schema. Defaults to 'validation'. 

399 

400 Returns: 

401 A JSON schema representing the specified schema. 

402 

403 Raises: 

404 PydanticUserError: If the JSON schema generator has already been used to generate a JSON schema. 

405 """ 

406 self._mode = mode 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

407 if self._used: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

408 raise PydanticUserError( 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

409 'This JSON schema generator has already been used to generate a JSON schema. ' 

410 f'You must create a new instance of {type(self).__name__} to generate a new JSON schema.', 

411 code='json-schema-already-used', 

412 ) 

413 

414 json_schema: JsonSchemaValue = self.generate_inner(schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

415 json_ref_counts = self.get_json_ref_counts(json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

416 

417 # Remove the top-level $ref if present; note that the _generate method already ensures there are no sibling keys 

418 ref = cast(JsonRef, json_schema.get('$ref')) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

419 while ref is not None: # may need to unpack multiple levels 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

420 ref_json_schema = self.get_schema_from_definitions(ref) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

421 if json_ref_counts[ref] > 1 or ref_json_schema is None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

422 # Keep the ref, but use an allOf to remove the top level $ref 

423 json_schema = {'allOf': [{'$ref': ref}]} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

424 else: 

425 # "Unpack" the ref since this is the only reference 

426 json_schema = ref_json_schema.copy() # copy to prevent recursive dict reference 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

427 json_ref_counts[ref] -= 1 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

428 ref = cast(JsonRef, json_schema.get('$ref')) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

429 

430 self._garbage_collect_definitions(json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

431 definitions_remapping = self._build_definitions_remapping() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

432 

433 if self.definitions: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

434 json_schema['$defs'] = self.definitions 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

435 

436 json_schema = definitions_remapping.remap_json_schema(json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

437 

438 # For now, we will not set the $schema key. However, if desired, this can be easily added by overriding 

439 # this method and adding the following line after a call to super().generate(schema): 

440 # json_schema['$schema'] = self.schema_dialect 

441 

442 self._used = True 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

443 return _sort_json_schema(json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

444 

445 def generate_inner(self, schema: CoreSchemaOrField) -> JsonSchemaValue: # noqa: C901 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

446 """Generates a JSON schema for a given core schema. 

447 

448 Args: 

449 schema: The given core schema. 

450 

451 Returns: 

452 The generated JSON schema. 

453 """ 

454 # If a schema with the same CoreRef has been handled, just return a reference to it 

455 # Note that this assumes that it will _never_ be the case that the same CoreRef is used 

456 # on types that should have different JSON schemas 

457 if 'ref' in schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

458 core_ref = CoreRef(schema['ref']) # type: ignore[typeddict-item] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

459 core_mode_ref = (core_ref, self.mode) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

460 if core_mode_ref in self.core_to_defs_refs and self.core_to_defs_refs[core_mode_ref] in self.definitions: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

461 return {'$ref': self.core_to_json_refs[core_mode_ref]} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

462 

463 # Generate the JSON schema, accounting for the json_schema_override and core_schema_override 

464 metadata_handler = _core_metadata.CoreMetadataHandler(schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

465 

466 def populate_defs(core_schema: CoreSchema, json_schema: JsonSchemaValue) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

467 if 'ref' in core_schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

468 core_ref = CoreRef(core_schema['ref']) # type: ignore[typeddict-item] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

469 defs_ref, ref_json_schema = self.get_cache_defs_ref_schema(core_ref) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

470 json_ref = JsonRef(ref_json_schema['$ref']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

471 self.json_to_defs_refs[json_ref] = defs_ref 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

472 # Replace the schema if it's not a reference to itself 

473 # What we want to avoid is having the def be just a ref to itself 

474 # which is what would happen if we blindly assigned any 

475 if json_schema.get('$ref', None) != json_ref: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

476 self.definitions[defs_ref] = json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

477 self._core_defs_invalid_for_json_schema.pop(defs_ref, None) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

478 json_schema = ref_json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

479 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

480 

481 def convert_to_all_of(json_schema: JsonSchemaValue) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

482 if '$ref' in json_schema and len(json_schema.keys()) > 1: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

483 # technically you can't have any other keys next to a "$ref" 

484 # but it's an easy mistake to make and not hard to correct automatically here 

485 json_schema = json_schema.copy() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

486 ref = json_schema.pop('$ref') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

487 json_schema = {'allOf': [{'$ref': ref}], **json_schema} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

488 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

489 

490 def handler_func(schema_or_field: CoreSchemaOrField) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

491 """Generate a JSON schema based on the input schema. 

492 

493 Args: 

494 schema_or_field: The core schema to generate a JSON schema from. 

495 

496 Returns: 

497 The generated JSON schema. 

498 

499 Raises: 

500 TypeError: If an unexpected schema type is encountered. 

501 """ 

502 # Generate the core-schema-type-specific bits of the schema generation: 

503 json_schema: JsonSchemaValue | None = None 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

504 if self.mode == 'serialization' and 'serialization' in schema_or_field: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

505 ser_schema = schema_or_field['serialization'] # type: ignore 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

506 json_schema = self.ser_schema(ser_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

507 if json_schema is None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

508 if _core_utils.is_core_schema(schema_or_field) or _core_utils.is_core_schema_field(schema_or_field): 508 ↛ 512line 508 didn't jump to line 512 because the condition on line 508 was always true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

509 generate_for_schema_type = self._schema_type_to_method[schema_or_field['type']] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

510 json_schema = generate_for_schema_type(schema_or_field) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

511 else: 

512 raise TypeError(f'Unexpected schema type: schema={schema_or_field}') 

513 if _core_utils.is_core_schema(schema_or_field): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

514 json_schema = populate_defs(schema_or_field, json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

515 json_schema = convert_to_all_of(json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

516 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

517 

518 current_handler = _schema_generation_shared.GenerateJsonSchemaHandler(self, handler_func) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

519 

520 for js_modify_function in metadata_handler.metadata.get('pydantic_js_functions', ()): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

521 

522 def new_handler_func( 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

523 schema_or_field: CoreSchemaOrField, 

524 current_handler: GetJsonSchemaHandler = current_handler, 

525 js_modify_function: GetJsonSchemaFunction = js_modify_function, 

526 ) -> JsonSchemaValue: 

527 json_schema = js_modify_function(schema_or_field, current_handler) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

528 if _core_utils.is_core_schema(schema_or_field): 528 ↛ 530line 528 didn't jump to line 530 because the condition on line 528 was always true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

529 json_schema = populate_defs(schema_or_field, json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

530 original_schema = current_handler.resolve_ref_schema(json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

531 ref = json_schema.pop('$ref', None) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

532 if ref and json_schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

533 original_schema.update(json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

534 return original_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

535 

536 current_handler = _schema_generation_shared.GenerateJsonSchemaHandler(self, new_handler_func) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

537 

538 for js_modify_function in metadata_handler.metadata.get('pydantic_js_annotation_functions', ()): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

539 

540 def new_handler_func( 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

541 schema_or_field: CoreSchemaOrField, 

542 current_handler: GetJsonSchemaHandler = current_handler, 

543 js_modify_function: GetJsonSchemaFunction = js_modify_function, 

544 ) -> JsonSchemaValue: 

545 json_schema = js_modify_function(schema_or_field, current_handler) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

546 if _core_utils.is_core_schema(schema_or_field): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

547 json_schema = populate_defs(schema_or_field, json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

548 json_schema = convert_to_all_of(json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

549 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

550 

551 current_handler = _schema_generation_shared.GenerateJsonSchemaHandler(self, new_handler_func) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

552 

553 json_schema = current_handler(schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

554 if _core_utils.is_core_schema(schema): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

555 json_schema = populate_defs(schema, json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

556 json_schema = convert_to_all_of(json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

557 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

558 

559 # ### Schema generation methods 

560 def any_schema(self, schema: core_schema.AnySchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

561 """Generates a JSON schema that matches any value. 

562 

563 Args: 

564 schema: The core schema. 

565 

566 Returns: 

567 The generated JSON schema. 

568 """ 

569 return {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

570 

571 def none_schema(self, schema: core_schema.NoneSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

572 """Generates a JSON schema that matches `None`. 

573 

574 Args: 

575 schema: The core schema. 

576 

577 Returns: 

578 The generated JSON schema. 

579 """ 

580 return {'type': 'null'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

581 

582 def bool_schema(self, schema: core_schema.BoolSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

583 """Generates a JSON schema that matches a bool value. 

584 

585 Args: 

586 schema: The core schema. 

587 

588 Returns: 

589 The generated JSON schema. 

590 """ 

591 return {'type': 'boolean'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

592 

593 def int_schema(self, schema: core_schema.IntSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

594 """Generates a JSON schema that matches an int value. 

595 

596 Args: 

597 schema: The core schema. 

598 

599 Returns: 

600 The generated JSON schema. 

601 """ 

602 json_schema: dict[str, Any] = {'type': 'integer'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

603 self.update_with_validations(json_schema, schema, self.ValidationsMapping.numeric) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

604 json_schema = {k: v for k, v in json_schema.items() if v not in {math.inf, -math.inf}} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

605 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

606 

607 def float_schema(self, schema: core_schema.FloatSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

608 """Generates a JSON schema that matches a float value. 

609 

610 Args: 

611 schema: The core schema. 

612 

613 Returns: 

614 The generated JSON schema. 

615 """ 

616 json_schema: dict[str, Any] = {'type': 'number'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

617 self.update_with_validations(json_schema, schema, self.ValidationsMapping.numeric) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

618 json_schema = {k: v for k, v in json_schema.items() if v not in {math.inf, -math.inf}} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

619 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

620 

621 def decimal_schema(self, schema: core_schema.DecimalSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

622 """Generates a JSON schema that matches a decimal value. 

623 

624 Args: 

625 schema: The core schema. 

626 

627 Returns: 

628 The generated JSON schema. 

629 """ 

630 json_schema = self.str_schema(core_schema.str_schema()) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

631 if self.mode == 'validation': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

632 multiple_of = schema.get('multiple_of') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

633 le = schema.get('le') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

634 ge = schema.get('ge') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

635 lt = schema.get('lt') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

636 gt = schema.get('gt') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

637 json_schema = { 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

638 'anyOf': [ 

639 self.float_schema( 

640 core_schema.float_schema( 

641 allow_inf_nan=schema.get('allow_inf_nan'), 

642 multiple_of=None if multiple_of is None else float(multiple_of), 

643 le=None if le is None else float(le), 

644 ge=None if ge is None else float(ge), 

645 lt=None if lt is None else float(lt), 

646 gt=None if gt is None else float(gt), 

647 ) 

648 ), 

649 json_schema, 

650 ], 

651 } 

652 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

653 

654 def str_schema(self, schema: core_schema.StringSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

655 """Generates a JSON schema that matches a string value. 

656 

657 Args: 

658 schema: The core schema. 

659 

660 Returns: 

661 The generated JSON schema. 

662 """ 

663 json_schema = {'type': 'string'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

664 self.update_with_validations(json_schema, schema, self.ValidationsMapping.string) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

665 if isinstance(json_schema.get('pattern'), Pattern): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

666 # TODO: should we add regex flags to the pattern? 

667 json_schema['pattern'] = json_schema.get('pattern').pattern # type: ignore 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

668 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

669 

670 def bytes_schema(self, schema: core_schema.BytesSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

671 """Generates a JSON schema that matches a bytes value. 

672 

673 Args: 

674 schema: The core schema. 

675 

676 Returns: 

677 The generated JSON schema. 

678 """ 

679 json_schema = {'type': 'string', 'format': 'base64url' if self._config.ser_json_bytes == 'base64' else 'binary'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

680 self.update_with_validations(json_schema, schema, self.ValidationsMapping.bytes) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

681 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

682 

683 def date_schema(self, schema: core_schema.DateSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

684 """Generates a JSON schema that matches a date value. 

685 

686 Args: 

687 schema: The core schema. 

688 

689 Returns: 

690 The generated JSON schema. 

691 """ 

692 json_schema = {'type': 'string', 'format': 'date'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

693 self.update_with_validations(json_schema, schema, self.ValidationsMapping.date) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

694 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

695 

696 def time_schema(self, schema: core_schema.TimeSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

697 """Generates a JSON schema that matches a time value. 

698 

699 Args: 

700 schema: The core schema. 

701 

702 Returns: 

703 The generated JSON schema. 

704 """ 

705 return {'type': 'string', 'format': 'time'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

706 

707 def datetime_schema(self, schema: core_schema.DatetimeSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

708 """Generates a JSON schema that matches a datetime value. 

709 

710 Args: 

711 schema: The core schema. 

712 

713 Returns: 

714 The generated JSON schema. 

715 """ 

716 return {'type': 'string', 'format': 'date-time'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

717 

718 def timedelta_schema(self, schema: core_schema.TimedeltaSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

719 """Generates a JSON schema that matches a timedelta value. 

720 

721 Args: 

722 schema: The core schema. 

723 

724 Returns: 

725 The generated JSON schema. 

726 """ 

727 if self._config.ser_json_timedelta == 'float': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

728 return {'type': 'number'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

729 return {'type': 'string', 'format': 'duration'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

730 

731 def literal_schema(self, schema: core_schema.LiteralSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

732 """Generates a JSON schema that matches a literal value. 

733 

734 Args: 

735 schema: The core schema. 

736 

737 Returns: 

738 The generated JSON schema. 

739 """ 

740 expected = [v.value if isinstance(v, Enum) else v for v in schema['expected']] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

741 # jsonify the expected values 

742 expected = [to_jsonable_python(v) for v in expected] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

743 

744 result: dict[str, Any] = {'enum': expected} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

745 if len(expected) == 1: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

746 result['const'] = expected[0] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

747 

748 types = {type(e) for e in expected} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

749 if types == {str}: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

750 result['type'] = 'string' 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

751 elif types == {int}: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

752 result['type'] = 'integer' 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

753 elif types == {float}: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

754 result['type'] = 'numeric' 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

755 elif types == {bool}: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

756 result['type'] = 'boolean' 1zBadejkpqrCbFGfglmstuvADchinowxy

757 elif types == {list}: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

758 result['type'] = 'array' 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

759 elif types == {type(None)}: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

760 result['type'] = 'null' 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

761 return result 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

762 

763 def enum_schema(self, schema: core_schema.EnumSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

764 """Generates a JSON schema that matches an Enum value. 

765 

766 Args: 

767 schema: The core schema. 

768 

769 Returns: 

770 The generated JSON schema. 

771 """ 

772 enum_type = schema['cls'] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

773 description = None if not enum_type.__doc__ else inspect.cleandoc(enum_type.__doc__) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

774 if ( 1EIzBCbHJAD

775 description == 'An enumeration.' 

776 ): # This is the default value provided by enum.EnumMeta.__new__; don't use it 

777 description = None 1EIzBadCbKLFGfgHJADch

778 result: dict[str, Any] = {'title': enum_type.__name__, 'description': description} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

779 result = {k: v for k, v in result.items() if v is not None} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

780 

781 expected = [to_jsonable_python(v.value) for v in schema['members']] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

782 

783 result['enum'] = expected 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

784 if len(expected) == 1: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

785 result['const'] = expected[0] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

786 

787 types = {type(e) for e in expected} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

788 if isinstance(enum_type, str) or types == {str}: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

789 result['type'] = 'string' 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

790 elif isinstance(enum_type, int) or types == {int}: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

791 result['type'] = 'integer' 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

792 elif isinstance(enum_type, float) or types == {float}: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

793 result['type'] = 'numeric' 1zBadejkpqrCbFGfglmstuvADchinowxy

794 elif types == {bool}: 794 ↛ 795line 794 didn't jump to line 795 because the condition on line 794 was never true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

795 result['type'] = 'boolean' 

796 elif types == {list}: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

797 result['type'] = 'array' 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

798 

799 return result 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

800 

801 def is_instance_schema(self, schema: core_schema.IsInstanceSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

802 """Handles JSON schema generation for a core schema that checks if a value is an instance of a class. 

803 

804 Unless overridden in a subclass, this raises an error. 

805 

806 Args: 

807 schema: The core schema. 

808 

809 Returns: 

810 The generated JSON schema. 

811 """ 

812 return self.handle_invalid_for_json_schema(schema, f'core_schema.IsInstanceSchema ({schema["cls"]})') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

813 

814 def is_subclass_schema(self, schema: core_schema.IsSubclassSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

815 """Handles JSON schema generation for a core schema that checks if a value is a subclass of a class. 

816 

817 For backwards compatibility with v1, this does not raise an error, but can be overridden to change this. 

818 

819 Args: 

820 schema: The core schema. 

821 

822 Returns: 

823 The generated JSON schema. 

824 """ 

825 # Note: This is for compatibility with V1; you can override if you want different behavior. 

826 return {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

827 

828 def callable_schema(self, schema: core_schema.CallableSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

829 """Generates a JSON schema that matches a callable value. 

830 

831 Unless overridden in a subclass, this raises an error. 

832 

833 Args: 

834 schema: The core schema. 

835 

836 Returns: 

837 The generated JSON schema. 

838 """ 

839 return self.handle_invalid_for_json_schema(schema, 'core_schema.CallableSchema') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

840 

841 def list_schema(self, schema: core_schema.ListSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

842 """Returns a schema that matches a list schema. 

843 

844 Args: 

845 schema: The core schema. 

846 

847 Returns: 

848 The generated JSON schema. 

849 """ 

850 items_schema = {} if 'items_schema' not in schema else self.generate_inner(schema['items_schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

851 json_schema = {'type': 'array', 'items': items_schema} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

852 self.update_with_validations(json_schema, schema, self.ValidationsMapping.array) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

853 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

854 

855 @deprecated('`tuple_positional_schema` is deprecated. Use `tuple_schema` instead.', category=None) 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

856 @final 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

857 def tuple_positional_schema(self, schema: core_schema.TupleSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

858 """Replaced by `tuple_schema`.""" 

859 warnings.warn( 

860 '`tuple_positional_schema` is deprecated. Use `tuple_schema` instead.', 

861 PydanticDeprecatedSince26, 

862 stacklevel=2, 

863 ) 

864 return self.tuple_schema(schema) 

865 

866 @deprecated('`tuple_variable_schema` is deprecated. Use `tuple_schema` instead.', category=None) 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

867 @final 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

868 def tuple_variable_schema(self, schema: core_schema.TupleSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

869 """Replaced by `tuple_schema`.""" 

870 warnings.warn( 

871 '`tuple_variable_schema` is deprecated. Use `tuple_schema` instead.', 

872 PydanticDeprecatedSince26, 

873 stacklevel=2, 

874 ) 

875 return self.tuple_schema(schema) 

876 

877 def tuple_schema(self, schema: core_schema.TupleSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

878 """Generates a JSON schema that matches a tuple schema e.g. `Tuple[int, 

879 str, bool]` or `Tuple[int, ...]`. 

880 

881 Args: 

882 schema: The core schema. 

883 

884 Returns: 

885 The generated JSON schema. 

886 """ 

887 json_schema: JsonSchemaValue = {'type': 'array'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

888 if 'variadic_item_index' in schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

889 variadic_item_index = schema['variadic_item_index'] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

890 if variadic_item_index > 0: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

891 json_schema['minItems'] = variadic_item_index 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

892 json_schema['prefixItems'] = [ 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

893 self.generate_inner(item) for item in schema['items_schema'][:variadic_item_index] 

894 ] 

895 if variadic_item_index + 1 == len(schema['items_schema']): 895 ↛ 902line 895 didn't jump to line 902 because the condition on line 895 was always true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

896 # if the variadic item is the last item, then represent it faithfully 

897 json_schema['items'] = self.generate_inner(schema['items_schema'][variadic_item_index]) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

898 else: 

899 # otherwise, 'items' represents the schema for the variadic 

900 # item plus the suffix, so just allow anything for simplicity 

901 # for now 

902 json_schema['items'] = True 

903 else: 

904 prefixItems = [self.generate_inner(item) for item in schema['items_schema']] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

905 if prefixItems: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

906 json_schema['prefixItems'] = prefixItems 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

907 json_schema['minItems'] = len(prefixItems) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

908 json_schema['maxItems'] = len(prefixItems) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

909 self.update_with_validations(json_schema, schema, self.ValidationsMapping.array) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

910 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

911 

912 def set_schema(self, schema: core_schema.SetSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

913 """Generates a JSON schema that matches a set schema. 

914 

915 Args: 

916 schema: The core schema. 

917 

918 Returns: 

919 The generated JSON schema. 

920 """ 

921 return self._common_set_schema(schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

922 

923 def frozenset_schema(self, schema: core_schema.FrozenSetSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

924 """Generates a JSON schema that matches a frozenset schema. 

925 

926 Args: 

927 schema: The core schema. 

928 

929 Returns: 

930 The generated JSON schema. 

931 """ 

932 return self._common_set_schema(schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

933 

934 def _common_set_schema(self, schema: core_schema.SetSchema | core_schema.FrozenSetSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

935 items_schema = {} if 'items_schema' not in schema else self.generate_inner(schema['items_schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

936 json_schema = {'type': 'array', 'uniqueItems': True, 'items': items_schema} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

937 self.update_with_validations(json_schema, schema, self.ValidationsMapping.array) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

938 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

939 

940 def generator_schema(self, schema: core_schema.GeneratorSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

941 """Returns a JSON schema that represents the provided GeneratorSchema. 

942 

943 Args: 

944 schema: The schema. 

945 

946 Returns: 

947 The generated JSON schema. 

948 """ 

949 items_schema = {} if 'items_schema' not in schema else self.generate_inner(schema['items_schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

950 json_schema = {'type': 'array', 'items': items_schema} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

951 self.update_with_validations(json_schema, schema, self.ValidationsMapping.array) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

952 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

953 

954 def dict_schema(self, schema: core_schema.DictSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

955 """Generates a JSON schema that matches a dict schema. 

956 

957 Args: 

958 schema: The core schema. 

959 

960 Returns: 

961 The generated JSON schema. 

962 """ 

963 json_schema: JsonSchemaValue = {'type': 'object'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

964 

965 keys_schema = self.generate_inner(schema['keys_schema']).copy() if 'keys_schema' in schema else {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

966 keys_pattern = keys_schema.pop('pattern', None) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

967 

968 values_schema = self.generate_inner(schema['values_schema']).copy() if 'values_schema' in schema else {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

969 values_schema.pop('title', None) # don't give a title to the additionalProperties 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

970 if values_schema or keys_pattern is not None: # don't add additionalProperties if it's empty 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

971 if keys_pattern is None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

972 json_schema['additionalProperties'] = values_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

973 else: 

974 json_schema['patternProperties'] = {keys_pattern: values_schema} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

975 

976 self.update_with_validations(json_schema, schema, self.ValidationsMapping.object) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

977 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

978 

979 def _function_schema( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

980 self, 

981 schema: _core_utils.AnyFunctionSchema, 

982 ) -> JsonSchemaValue: 

983 if _core_utils.is_function_with_inner_schema(schema): 983 ↛ 989line 983 didn't jump to line 989 because the condition on line 983 was always true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

984 # This could be wrong if the function's mode is 'before', but in practice will often be right, and when it 

985 # isn't, I think it would be hard to automatically infer what the desired schema should be. 

986 return self.generate_inner(schema['schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

987 

988 # function-plain 

989 return self.handle_invalid_for_json_schema( 

990 schema, f'core_schema.PlainValidatorFunctionSchema ({schema["function"]})' 

991 ) 

992 

993 def function_before_schema(self, schema: core_schema.BeforeValidatorFunctionSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

994 """Generates a JSON schema that matches a function-before schema. 

995 

996 Args: 

997 schema: The core schema. 

998 

999 Returns: 

1000 The generated JSON schema. 

1001 """ 

1002 return self._function_schema(schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1003 

1004 def function_after_schema(self, schema: core_schema.AfterValidatorFunctionSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1005 """Generates a JSON schema that matches a function-after schema. 

1006 

1007 Args: 

1008 schema: The core schema. 

1009 

1010 Returns: 

1011 The generated JSON schema. 

1012 """ 

1013 return self._function_schema(schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1014 

1015 def function_plain_schema(self, schema: core_schema.PlainValidatorFunctionSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1016 """Generates a JSON schema that matches a function-plain schema. 

1017 

1018 Args: 

1019 schema: The core schema. 

1020 

1021 Returns: 

1022 The generated JSON schema. 

1023 """ 

1024 return self._function_schema(schema) 

1025 

1026 def function_wrap_schema(self, schema: core_schema.WrapValidatorFunctionSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1027 """Generates a JSON schema that matches a function-wrap schema. 

1028 

1029 Args: 

1030 schema: The core schema. 

1031 

1032 Returns: 

1033 The generated JSON schema. 

1034 """ 

1035 return self._function_schema(schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1036 

1037 def default_schema(self, schema: core_schema.WithDefaultSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1038 """Generates a JSON schema that matches a schema with a default value. 

1039 

1040 Args: 

1041 schema: The core schema. 

1042 

1043 Returns: 

1044 The generated JSON schema. 

1045 """ 

1046 json_schema = self.generate_inner(schema['schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1047 

1048 if 'default' not in schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1049 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1050 default = schema['default'] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1051 # Note: if you want to include the value returned by the default_factory, 

1052 # override this method and replace the code above with: 

1053 # if 'default' in schema: 

1054 # default = schema['default'] 

1055 # elif 'default_factory' in schema: 

1056 # default = schema['default_factory']() 

1057 # else: 

1058 # return json_schema 

1059 

1060 # we reflect the application of custom plain, no-info serializers to defaults for 

1061 # json schemas viewed in serialization mode 

1062 # TODO: improvements along with https://github.com/pydantic/pydantic/issues/8208 

1063 # TODO: improve type safety here 

1064 if self.mode == 'serialization': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1065 if ( 1EIzBadejCbKLFGfglmHJADchin

1066 (ser_schema := schema['schema'].get('serialization', {})) 

1067 and (ser_func := ser_schema.get('function')) 

1068 and ser_schema.get('type') == 'function-plain' # type: ignore 

1069 and ser_schema.get('info_arg') is False # type: ignore 

1070 ): 

1071 default = ser_func(default) # type: ignore 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1072 

1073 try: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1074 encoded_default = self.encode_default(default) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1075 except pydantic_core.PydanticSerializationError: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1076 self.emit_warning( 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1077 'non-serializable-default', 

1078 f'Default value {default} is not JSON serializable; excluding default from JSON schema', 

1079 ) 

1080 # Return the inner schema, as though there was no default 

1081 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1082 

1083 if '$ref' in json_schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1084 # Since reference schemas do not support child keys, we wrap the reference schema in a single-case allOf: 

1085 return {'allOf': [json_schema], 'default': encoded_default} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1086 else: 

1087 json_schema['default'] = encoded_default 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1088 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1089 

1090 def nullable_schema(self, schema: core_schema.NullableSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1091 """Generates a JSON schema that matches a schema that allows null values. 

1092 

1093 Args: 

1094 schema: The core schema. 

1095 

1096 Returns: 

1097 The generated JSON schema. 

1098 """ 

1099 null_schema = {'type': 'null'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1100 inner_json_schema = self.generate_inner(schema['schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1101 

1102 if inner_json_schema == null_schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1103 return null_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1104 else: 

1105 # Thanks to the equality check against `null_schema` above, I think 'oneOf' would also be valid here; 

1106 # I'll use 'anyOf' for now, but it could be changed it if it would work better with some external tooling 

1107 return self.get_flattened_anyof([inner_json_schema, null_schema]) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1108 

1109 def union_schema(self, schema: core_schema.UnionSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1110 """Generates a JSON schema that matches a schema that allows values matching any of the given schemas. 

1111 

1112 Args: 

1113 schema: The core schema. 

1114 

1115 Returns: 

1116 The generated JSON schema. 

1117 """ 

1118 generated: list[JsonSchemaValue] = [] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1119 

1120 choices = schema['choices'] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1121 for choice in choices: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1122 # choice will be a tuple if an explicit label was provided 

1123 choice_schema = choice[0] if isinstance(choice, tuple) else choice 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1124 try: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1125 generated.append(self.generate_inner(choice_schema)) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1126 except PydanticOmit: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1127 continue 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1128 except PydanticInvalidForJsonSchema as exc: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1129 self.emit_warning('skipped-choice', exc.message) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1130 if len(generated) == 1: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1131 return generated[0] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1132 return self.get_flattened_anyof(generated) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1133 

1134 def tagged_union_schema(self, schema: core_schema.TaggedUnionSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1135 """Generates a JSON schema that matches a schema that allows values matching any of the given schemas, where 

1136 the schemas are tagged with a discriminator field that indicates which schema should be used to validate 

1137 the value. 

1138 

1139 Args: 

1140 schema: The core schema. 

1141 

1142 Returns: 

1143 The generated JSON schema. 

1144 """ 

1145 generated: dict[str, JsonSchemaValue] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1146 for k, v in schema['choices'].items(): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1147 if isinstance(k, Enum): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1148 k = k.value 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1149 try: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1150 # Use str(k) since keys must be strings for json; while not technically correct, 

1151 # it's the closest that can be represented in valid JSON 

1152 generated[str(k)] = self.generate_inner(v).copy() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1153 except PydanticOmit: 

1154 continue 

1155 except PydanticInvalidForJsonSchema as exc: 

1156 self.emit_warning('skipped-choice', exc.message) 

1157 

1158 one_of_choices = _deduplicate_schemas(generated.values()) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1159 json_schema: JsonSchemaValue = {'oneOf': one_of_choices} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1160 

1161 # This reflects the v1 behavior; TODO: we should make it possible to exclude OpenAPI stuff from the JSON schema 

1162 openapi_discriminator = self._extract_discriminator(schema, one_of_choices) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1163 if openapi_discriminator is not None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1164 json_schema['discriminator'] = { 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1165 'propertyName': openapi_discriminator, 

1166 'mapping': {k: v.get('$ref', v) for k, v in generated.items()}, 

1167 } 

1168 

1169 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1170 

1171 def _extract_discriminator( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1172 self, schema: core_schema.TaggedUnionSchema, one_of_choices: list[JsonDict] 

1173 ) -> str | None: 

1174 """Extract a compatible OpenAPI discriminator from the schema and one_of choices that end up in the final 

1175 schema.""" 

1176 openapi_discriminator: str | None = None 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1177 

1178 if isinstance(schema['discriminator'], str): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1179 return schema['discriminator'] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1180 

1181 if isinstance(schema['discriminator'], list): 1181 ↛ 1209line 1181 didn't jump to line 1209 because the condition on line 1181 was always true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1182 # If the discriminator is a single item list containing a string, that is equivalent to the string case 

1183 if len(schema['discriminator']) == 1 and isinstance(schema['discriminator'][0], str): 1183 ↛ 1184line 1183 didn't jump to line 1184 because the condition on line 1183 was never true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1184 return schema['discriminator'][0] 

1185 # When an alias is used that is different from the field name, the discriminator will be a list of single 

1186 # str lists, one for the attribute and one for the actual alias. The logic here will work even if there is 

1187 # more than one possible attribute, and looks for whether a single alias choice is present as a documented 

1188 # property on all choices. If so, that property will be used as the OpenAPI discriminator. 

1189 for alias_path in schema['discriminator']: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1190 if not isinstance(alias_path, list): 1190 ↛ 1191line 1190 didn't jump to line 1191 because the condition on line 1190 was never true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1191 break # this means that the discriminator is not a list of alias paths 

1192 if len(alias_path) != 1: 1192 ↛ 1193line 1192 didn't jump to line 1193 because the condition on line 1192 was never true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1193 continue # this means that the "alias" does not represent a single field 

1194 alias = alias_path[0] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1195 if not isinstance(alias, str): 1195 ↛ 1196line 1195 didn't jump to line 1196 because the condition on line 1195 was never true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1196 continue # this means that the "alias" does not represent a field 

1197 alias_is_present_on_all_choices = True 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1198 for choice in one_of_choices: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1199 while '$ref' in choice: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1200 assert isinstance(choice['$ref'], str) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1201 choice = self.get_schema_from_definitions(JsonRef(choice['$ref'])) or {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1202 properties = choice.get('properties', {}) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1203 if not isinstance(properties, dict) or alias not in properties: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1204 alias_is_present_on_all_choices = False 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1205 break 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1206 if alias_is_present_on_all_choices: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1207 openapi_discriminator = alias 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1208 break 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1209 return openapi_discriminator 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1210 

1211 def chain_schema(self, schema: core_schema.ChainSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1212 """Generates a JSON schema that matches a core_schema.ChainSchema. 

1213 

1214 When generating a schema for validation, we return the validation JSON schema for the first step in the chain. 

1215 For serialization, we return the serialization JSON schema for the last step in the chain. 

1216 

1217 Args: 

1218 schema: The core schema. 

1219 

1220 Returns: 

1221 The generated JSON schema. 

1222 """ 

1223 step_index = 0 if self.mode == 'validation' else -1 # use first step for validation, last for serialization 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1224 return self.generate_inner(schema['steps'][step_index]) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1225 

1226 def lax_or_strict_schema(self, schema: core_schema.LaxOrStrictSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1227 """Generates a JSON schema that matches a schema that allows values matching either the lax schema or the 

1228 strict schema. 

1229 

1230 Args: 

1231 schema: The core schema. 

1232 

1233 Returns: 

1234 The generated JSON schema. 

1235 """ 

1236 # TODO: Need to read the default value off of model config or whatever 

1237 use_strict = schema.get('strict', False) # TODO: replace this default False 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1238 # If your JSON schema fails to generate it is probably 

1239 # because one of the following two branches failed. 

1240 if use_strict: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1241 return self.generate_inner(schema['strict_schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1242 else: 

1243 return self.generate_inner(schema['lax_schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1244 

1245 def json_or_python_schema(self, schema: core_schema.JsonOrPythonSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1246 """Generates a JSON schema that matches a schema that allows values matching either the JSON schema or the 

1247 Python schema. 

1248 

1249 The JSON schema is used instead of the Python schema. If you want to use the Python schema, you should override 

1250 this method. 

1251 

1252 Args: 

1253 schema: The core schema. 

1254 

1255 Returns: 

1256 The generated JSON schema. 

1257 """ 

1258 return self.generate_inner(schema['json_schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1259 

1260 def typed_dict_schema(self, schema: core_schema.TypedDictSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1261 """Generates a JSON schema that matches a schema that defines a typed dict. 

1262 

1263 Args: 

1264 schema: The core schema. 

1265 

1266 Returns: 

1267 The generated JSON schema. 

1268 """ 

1269 total = schema.get('total', True) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1270 named_required_fields: list[tuple[str, bool, CoreSchemaField]] = [ 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1271 (name, self.field_is_required(field, total), field) 

1272 for name, field in schema['fields'].items() 

1273 if self.field_is_present(field) 

1274 ] 

1275 if self.mode == 'serialization': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1276 named_required_fields.extend(self._name_required_computed_fields(schema.get('computed_fields', []))) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1277 cls = _get_typed_dict_cls(schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1278 config = _get_typed_dict_config(cls) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1279 with self._config_wrapper_stack.push(config): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1280 json_schema = self._named_required_fields_schema(named_required_fields) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1281 

1282 json_schema_extra = config.get('json_schema_extra') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1283 extra = schema.get('extra_behavior') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1284 if extra is None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1285 extra = config.get('extra', 'ignore') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1286 

1287 if cls is not None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1288 title = config.get('title') or cls.__name__ 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1289 json_schema = self._update_class_schema(json_schema, title, extra, cls, json_schema_extra) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1290 else: 

1291 if extra == 'forbid': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1292 json_schema['additionalProperties'] = False 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1293 elif extra == 'allow': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1294 json_schema['additionalProperties'] = True 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1295 

1296 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1297 

1298 @staticmethod 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1299 def _name_required_computed_fields( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1300 computed_fields: list[ComputedField], 

1301 ) -> list[tuple[str, bool, core_schema.ComputedField]]: 

1302 return [(field['property_name'], True, field) for field in computed_fields] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1303 

1304 def _named_required_fields_schema( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1305 self, named_required_fields: Sequence[tuple[str, bool, CoreSchemaField]] 

1306 ) -> JsonSchemaValue: 

1307 properties: dict[str, JsonSchemaValue] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1308 required_fields: list[str] = [] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1309 for name, required, field in named_required_fields: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1310 if self.by_alias: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1311 name = self._get_alias_name(field, name) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1312 try: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1313 field_json_schema = self.generate_inner(field).copy() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1314 except PydanticOmit: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1315 continue 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1316 if 'title' not in field_json_schema and self.field_title_should_be_set(field): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1317 title = self.get_title_from_name(name) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1318 field_json_schema['title'] = title 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1319 field_json_schema = self.handle_ref_overrides(field_json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1320 properties[name] = field_json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1321 if required: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1322 required_fields.append(name) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1323 

1324 json_schema = {'type': 'object', 'properties': properties} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1325 if required_fields: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1326 json_schema['required'] = required_fields 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1327 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1328 

1329 def _get_alias_name(self, field: CoreSchemaField, name: str) -> str: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1330 if field['type'] == 'computed-field': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1331 alias: Any = field.get('alias', name) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1332 elif self.mode == 'validation': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1333 alias = field.get('validation_alias', name) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1334 else: 

1335 alias = field.get('serialization_alias', name) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1336 if isinstance(alias, str): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1337 name = alias 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1338 elif isinstance(alias, list): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1339 alias = cast('list[str] | str', alias) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1340 for path in alias: 1340 ↛ 1348line 1340 didn't jump to line 1348 because the loop on line 1340 didn't complete1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1341 if isinstance(path, list) and len(path) == 1 and isinstance(path[0], str): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1342 # Use the first valid single-item string path; the code that constructs the alias array 

1343 # should ensure the first such item is what belongs in the JSON schema 

1344 name = path[0] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1345 break 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1346 else: 

1347 assert_never(alias) 

1348 return name 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1349 

1350 def typed_dict_field_schema(self, schema: core_schema.TypedDictField) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1351 """Generates a JSON schema that matches a schema that defines a typed dict field. 

1352 

1353 Args: 

1354 schema: The core schema. 

1355 

1356 Returns: 

1357 The generated JSON schema. 

1358 """ 

1359 return self.generate_inner(schema['schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1360 

1361 def dataclass_field_schema(self, schema: core_schema.DataclassField) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1362 """Generates a JSON schema that matches a schema that defines a dataclass field. 

1363 

1364 Args: 

1365 schema: The core schema. 

1366 

1367 Returns: 

1368 The generated JSON schema. 

1369 """ 

1370 return self.generate_inner(schema['schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1371 

1372 def model_field_schema(self, schema: core_schema.ModelField) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1373 """Generates a JSON schema that matches a schema that defines a model field. 

1374 

1375 Args: 

1376 schema: The core schema. 

1377 

1378 Returns: 

1379 The generated JSON schema. 

1380 """ 

1381 return self.generate_inner(schema['schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1382 

1383 def computed_field_schema(self, schema: core_schema.ComputedField) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1384 """Generates a JSON schema that matches a schema that defines a computed field. 

1385 

1386 Args: 

1387 schema: The core schema. 

1388 

1389 Returns: 

1390 The generated JSON schema. 

1391 """ 

1392 return self.generate_inner(schema['return_schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1393 

1394 def model_schema(self, schema: core_schema.ModelSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1395 """Generates a JSON schema that matches a schema that defines a model. 

1396 

1397 Args: 

1398 schema: The core schema. 

1399 

1400 Returns: 

1401 The generated JSON schema. 

1402 """ 

1403 # We do not use schema['model'].model_json_schema() here 

1404 # because it could lead to inconsistent refs handling, etc. 

1405 cls = cast('type[BaseModel]', schema['cls']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1406 config = cls.model_config 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1407 title = config.get('title') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1408 

1409 with self._config_wrapper_stack.push(config): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1410 json_schema = self.generate_inner(schema['schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1411 

1412 json_schema_extra = config.get('json_schema_extra') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1413 if cls.__pydantic_root_model__: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1414 root_json_schema_extra = cls.model_fields['root'].json_schema_extra 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1415 if json_schema_extra and root_json_schema_extra: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1416 raise ValueError( 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1417 '"model_config[\'json_schema_extra\']" and "Field.json_schema_extra" on "RootModel.root"' 

1418 ' field must not be set simultaneously' 

1419 ) 

1420 if root_json_schema_extra: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1421 json_schema_extra = root_json_schema_extra 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1422 

1423 json_schema = self._update_class_schema(json_schema, title, config.get('extra', None), cls, json_schema_extra) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1424 

1425 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1426 

1427 def _update_class_schema( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1428 self, 

1429 json_schema: JsonSchemaValue, 

1430 title: str | None, 

1431 extra: Literal['allow', 'ignore', 'forbid'] | None, 

1432 cls: type[Any], 

1433 json_schema_extra: JsonDict | JsonSchemaExtraCallable | None, 

1434 ) -> JsonSchemaValue: 

1435 if '$ref' in json_schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1436 schema_to_update = self.get_schema_from_definitions(JsonRef(json_schema['$ref'])) or json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1437 else: 

1438 schema_to_update = json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1439 

1440 if title is not None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1441 # referenced_schema['title'] = title 

1442 schema_to_update.setdefault('title', title) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1443 

1444 if 'additionalProperties' not in schema_to_update: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1445 if extra == 'allow': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1446 schema_to_update['additionalProperties'] = True 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1447 elif extra == 'forbid': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1448 schema_to_update['additionalProperties'] = False 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1449 

1450 if isinstance(json_schema_extra, (staticmethod, classmethod)): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1451 # In older versions of python, this is necessary to ensure staticmethod/classmethods are callable 

1452 json_schema_extra = json_schema_extra.__get__(cls) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1453 

1454 if isinstance(json_schema_extra, dict): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1455 schema_to_update.update(json_schema_extra) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1456 elif callable(json_schema_extra): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1457 if len(inspect.signature(json_schema_extra).parameters) > 1: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1458 json_schema_extra(schema_to_update, cls) # type: ignore 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1459 else: 

1460 json_schema_extra(schema_to_update) # type: ignore 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1461 elif json_schema_extra is not None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1462 raise ValueError( 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1463 f"model_config['json_schema_extra']={json_schema_extra} should be a dict, callable, or None" 

1464 ) 

1465 

1466 if hasattr(cls, '__deprecated__'): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1467 json_schema['deprecated'] = True 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1468 

1469 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1470 

1471 def resolve_schema_to_update(self, json_schema: JsonSchemaValue) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1472 """Resolve a JsonSchemaValue to the non-ref schema if it is a $ref schema. 

1473 

1474 Args: 

1475 json_schema: The schema to resolve. 

1476 

1477 Returns: 

1478 The resolved schema. 

1479 """ 

1480 if '$ref' in json_schema: 1480 ↛ 1481line 1480 didn't jump to line 1481 because the condition on line 1480 was never true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1481 schema_to_update = self.get_schema_from_definitions(JsonRef(json_schema['$ref'])) 

1482 if schema_to_update is None: 

1483 raise RuntimeError(f'Cannot update undefined schema for $ref={json_schema["$ref"]}') 

1484 return self.resolve_schema_to_update(schema_to_update) 

1485 else: 

1486 schema_to_update = json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1487 return schema_to_update 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1488 

1489 def model_fields_schema(self, schema: core_schema.ModelFieldsSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1490 """Generates a JSON schema that matches a schema that defines a model's fields. 

1491 

1492 Args: 

1493 schema: The core schema. 

1494 

1495 Returns: 

1496 The generated JSON schema. 

1497 """ 

1498 named_required_fields: list[tuple[str, bool, CoreSchemaField]] = [ 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1499 (name, self.field_is_required(field, total=True), field) 

1500 for name, field in schema['fields'].items() 

1501 if self.field_is_present(field) 

1502 ] 

1503 if self.mode == 'serialization': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1504 named_required_fields.extend(self._name_required_computed_fields(schema.get('computed_fields', []))) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1505 json_schema = self._named_required_fields_schema(named_required_fields) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1506 extras_schema = schema.get('extras_schema', None) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1507 if extras_schema is not None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1508 schema_to_update = self.resolve_schema_to_update(json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1509 schema_to_update['additionalProperties'] = self.generate_inner(extras_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1510 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1511 

1512 def field_is_present(self, field: CoreSchemaField) -> bool: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1513 """Whether the field should be included in the generated JSON schema. 

1514 

1515 Args: 

1516 field: The schema for the field itself. 

1517 

1518 Returns: 

1519 `True` if the field should be included in the generated JSON schema, `False` otherwise. 

1520 """ 

1521 if self.mode == 'serialization': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1522 # If you still want to include the field in the generated JSON schema, 

1523 # override this method and return True 

1524 return not field.get('serialization_exclude') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1525 elif self.mode == 'validation': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1526 return True 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1527 else: 

1528 assert_never(self.mode) 

1529 

1530 def field_is_required( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1531 self, 

1532 field: core_schema.ModelField | core_schema.DataclassField | core_schema.TypedDictField, 

1533 total: bool, 

1534 ) -> bool: 

1535 """Whether the field should be marked as required in the generated JSON schema. 

1536 (Note that this is irrelevant if the field is not present in the JSON schema.). 

1537 

1538 Args: 

1539 field: The schema for the field itself. 

1540 total: Only applies to `TypedDictField`s. 

1541 Indicates if the `TypedDict` this field belongs to is total, in which case any fields that don't 

1542 explicitly specify `required=False` are required. 

1543 

1544 Returns: 

1545 `True` if the field should be marked as required in the generated JSON schema, `False` otherwise. 

1546 """ 

1547 if self.mode == 'serialization' and self._config.json_schema_serialization_defaults_required: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1548 return not field.get('serialization_exclude') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1549 else: 

1550 if field['type'] == 'typed-dict-field': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1551 return field.get('required', total) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1552 else: 

1553 return field['schema']['type'] != 'default' 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1554 

1555 def dataclass_args_schema(self, schema: core_schema.DataclassArgsSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1556 """Generates a JSON schema that matches a schema that defines a dataclass's constructor arguments. 

1557 

1558 Args: 

1559 schema: The core schema. 

1560 

1561 Returns: 

1562 The generated JSON schema. 

1563 """ 

1564 named_required_fields: list[tuple[str, bool, CoreSchemaField]] = [ 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1565 (field['name'], self.field_is_required(field, total=True), field) 

1566 for field in schema['fields'] 

1567 if self.field_is_present(field) 

1568 ] 

1569 if self.mode == 'serialization': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1570 named_required_fields.extend(self._name_required_computed_fields(schema.get('computed_fields', []))) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1571 return self._named_required_fields_schema(named_required_fields) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1572 

1573 def dataclass_schema(self, schema: core_schema.DataclassSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1574 """Generates a JSON schema that matches a schema that defines a dataclass. 

1575 

1576 Args: 

1577 schema: The core schema. 

1578 

1579 Returns: 

1580 The generated JSON schema. 

1581 """ 

1582 cls = schema['cls'] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1583 config: ConfigDict = getattr(cls, '__pydantic_config__', cast('ConfigDict', {})) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1584 title = config.get('title') or cls.__name__ 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1585 

1586 with self._config_wrapper_stack.push(config): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1587 json_schema = self.generate_inner(schema['schema']).copy() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1588 

1589 json_schema_extra = config.get('json_schema_extra') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1590 json_schema = self._update_class_schema(json_schema, title, config.get('extra', None), cls, json_schema_extra) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1591 

1592 # Dataclass-specific handling of description 

1593 if is_dataclass(cls) and not hasattr(cls, '__pydantic_validator__'): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1594 # vanilla dataclass; don't use cls.__doc__ as it will contain the class signature by default 

1595 description = None 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1596 else: 

1597 description = None if cls.__doc__ is None else inspect.cleandoc(cls.__doc__) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1598 if description: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1599 json_schema['description'] = description 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1600 

1601 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1602 

1603 def arguments_schema(self, schema: core_schema.ArgumentsSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1604 """Generates a JSON schema that matches a schema that defines a function's arguments. 

1605 

1606 Args: 

1607 schema: The core schema. 

1608 

1609 Returns: 

1610 The generated JSON schema. 

1611 """ 

1612 metadata = _core_metadata.CoreMetadataHandler(schema).metadata 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1613 prefer_positional = metadata.get('pydantic_js_prefer_positional_arguments') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1614 

1615 arguments = schema['arguments_schema'] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1616 kw_only_arguments = [a for a in arguments if a.get('mode') == 'keyword_only'] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1617 kw_or_p_arguments = [a for a in arguments if a.get('mode') in {'positional_or_keyword', None}] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1618 p_only_arguments = [a for a in arguments if a.get('mode') == 'positional_only'] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1619 var_args_schema = schema.get('var_args_schema') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1620 var_kwargs_schema = schema.get('var_kwargs_schema') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1621 

1622 if prefer_positional: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1623 positional_possible = not kw_only_arguments and not var_kwargs_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1624 if positional_possible: 1624 ↛ 1627line 1624 didn't jump to line 1627 because the condition on line 1624 was always true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1625 return self.p_arguments_schema(p_only_arguments + kw_or_p_arguments, var_args_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1626 

1627 keyword_possible = not p_only_arguments and not var_args_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1628 if keyword_possible: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1629 return self.kw_arguments_schema(kw_or_p_arguments + kw_only_arguments, var_kwargs_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1630 

1631 if not prefer_positional: 1631 ↛ 1636line 1631 didn't jump to line 1636 because the condition on line 1631 was always true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1632 positional_possible = not kw_only_arguments and not var_kwargs_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1633 if positional_possible: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1634 return self.p_arguments_schema(p_only_arguments + kw_or_p_arguments, var_args_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1635 

1636 raise PydanticInvalidForJsonSchema( 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1637 'Unable to generate JSON schema for arguments validator with positional-only and keyword-only arguments' 

1638 ) 

1639 

1640 def kw_arguments_schema( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1641 self, arguments: list[core_schema.ArgumentsParameter], var_kwargs_schema: CoreSchema | None 

1642 ) -> JsonSchemaValue: 

1643 """Generates a JSON schema that matches a schema that defines a function's keyword arguments. 

1644 

1645 Args: 

1646 arguments: The core schema. 

1647 

1648 Returns: 

1649 The generated JSON schema. 

1650 """ 

1651 properties: dict[str, JsonSchemaValue] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1652 required: list[str] = [] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1653 for argument in arguments: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1654 name = self.get_argument_name(argument) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1655 argument_schema = self.generate_inner(argument['schema']).copy() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1656 argument_schema['title'] = self.get_title_from_name(name) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1657 properties[name] = argument_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1658 

1659 if argument['schema']['type'] != 'default': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1660 # This assumes that if the argument has a default value, 

1661 # the inner schema must be of type WithDefaultSchema. 

1662 # I believe this is true, but I am not 100% sure 

1663 required.append(name) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1664 

1665 json_schema: JsonSchemaValue = {'type': 'object', 'properties': properties} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1666 if required: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1667 json_schema['required'] = required 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1668 

1669 if var_kwargs_schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1670 additional_properties_schema = self.generate_inner(var_kwargs_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1671 if additional_properties_schema: 1671 ↛ 1675line 1671 didn't jump to line 1675 because the condition on line 1671 was always true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1672 json_schema['additionalProperties'] = additional_properties_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1673 else: 

1674 json_schema['additionalProperties'] = False 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1675 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1676 

1677 def p_arguments_schema( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1678 self, arguments: list[core_schema.ArgumentsParameter], var_args_schema: CoreSchema | None 

1679 ) -> JsonSchemaValue: 

1680 """Generates a JSON schema that matches a schema that defines a function's positional arguments. 

1681 

1682 Args: 

1683 arguments: The core schema. 

1684 

1685 Returns: 

1686 The generated JSON schema. 

1687 """ 

1688 prefix_items: list[JsonSchemaValue] = [] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1689 min_items = 0 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1690 

1691 for argument in arguments: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1692 name = self.get_argument_name(argument) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1693 

1694 argument_schema = self.generate_inner(argument['schema']).copy() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1695 argument_schema['title'] = self.get_title_from_name(name) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1696 prefix_items.append(argument_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1697 

1698 if argument['schema']['type'] != 'default': 1698 ↛ 1691line 1698 didn't jump to line 1691 because the condition on line 1698 was always true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1699 # This assumes that if the argument has a default value, 

1700 # the inner schema must be of type WithDefaultSchema. 

1701 # I believe this is true, but I am not 100% sure 

1702 min_items += 1 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1703 

1704 json_schema: JsonSchemaValue = {'type': 'array', 'prefixItems': prefix_items} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1705 if min_items: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1706 json_schema['minItems'] = min_items 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1707 

1708 if var_args_schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1709 items_schema = self.generate_inner(var_args_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1710 if items_schema: 1710 ↛ 1715line 1710 didn't jump to line 1715 because the condition on line 1710 was always true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1711 json_schema['items'] = items_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1712 else: 

1713 json_schema['maxItems'] = len(prefix_items) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1714 

1715 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1716 

1717 def get_argument_name(self, argument: core_schema.ArgumentsParameter) -> str: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1718 """Retrieves the name of an argument. 

1719 

1720 Args: 

1721 argument: The core schema. 

1722 

1723 Returns: 

1724 The name of the argument. 

1725 """ 

1726 name = argument['name'] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1727 if self.by_alias: 1727 ↛ 1733line 1727 didn't jump to line 1733 because the condition on line 1727 was always true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1728 alias = argument.get('alias') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1729 if isinstance(alias, str): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1730 name = alias 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1731 else: 

1732 pass # might want to do something else? 1adejkpqrbfglmstuvchinowxy

1733 return name 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1734 

1735 def call_schema(self, schema: core_schema.CallSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1736 """Generates a JSON schema that matches a schema that defines a function call. 

1737 

1738 Args: 

1739 schema: The core schema. 

1740 

1741 Returns: 

1742 The generated JSON schema. 

1743 """ 

1744 return self.generate_inner(schema['arguments_schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1745 

1746 def custom_error_schema(self, schema: core_schema.CustomErrorSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1747 """Generates a JSON schema that matches a schema that defines a custom error. 

1748 

1749 Args: 

1750 schema: The core schema. 

1751 

1752 Returns: 

1753 The generated JSON schema. 

1754 """ 

1755 return self.generate_inner(schema['schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1756 

1757 def json_schema(self, schema: core_schema.JsonSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1758 """Generates a JSON schema that matches a schema that defines a JSON object. 

1759 

1760 Args: 

1761 schema: The core schema. 

1762 

1763 Returns: 

1764 The generated JSON schema. 

1765 """ 

1766 content_core_schema = schema.get('schema') or core_schema.any_schema() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1767 content_json_schema = self.generate_inner(content_core_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1768 if self.mode == 'validation': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1769 return {'type': 'string', 'contentMediaType': 'application/json', 'contentSchema': content_json_schema} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1770 else: 

1771 # self.mode == 'serialization' 

1772 return content_json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1773 

1774 def url_schema(self, schema: core_schema.UrlSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1775 """Generates a JSON schema that matches a schema that defines a URL. 

1776 

1777 Args: 

1778 schema: The core schema. 

1779 

1780 Returns: 

1781 The generated JSON schema. 

1782 """ 

1783 json_schema = {'type': 'string', 'format': 'uri', 'minLength': 1} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1784 self.update_with_validations(json_schema, schema, self.ValidationsMapping.string) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1785 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1786 

1787 def multi_host_url_schema(self, schema: core_schema.MultiHostUrlSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1788 """Generates a JSON schema that matches a schema that defines a URL that can be used with multiple hosts. 

1789 

1790 Args: 

1791 schema: The core schema. 

1792 

1793 Returns: 

1794 The generated JSON schema. 

1795 """ 

1796 # Note: 'multi-host-uri' is a custom/pydantic-specific format, not part of the JSON Schema spec 

1797 json_schema = {'type': 'string', 'format': 'multi-host-uri', 'minLength': 1} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1798 self.update_with_validations(json_schema, schema, self.ValidationsMapping.string) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1799 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1800 

1801 def uuid_schema(self, schema: core_schema.UuidSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1802 """Generates a JSON schema that matches a UUID. 

1803 

1804 Args: 

1805 schema: The core schema. 

1806 

1807 Returns: 

1808 The generated JSON schema. 

1809 """ 

1810 return {'type': 'string', 'format': 'uuid'} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1811 

1812 def definitions_schema(self, schema: core_schema.DefinitionsSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1813 """Generates a JSON schema that matches a schema that defines a JSON object with definitions. 

1814 

1815 Args: 

1816 schema: The core schema. 

1817 

1818 Returns: 

1819 The generated JSON schema. 

1820 """ 

1821 for definition in schema['definitions']: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1822 try: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1823 self.generate_inner(definition) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1824 except PydanticInvalidForJsonSchema as e: 

1825 core_ref: CoreRef = CoreRef(definition['ref']) # type: ignore 

1826 self._core_defs_invalid_for_json_schema[self.get_defs_ref((core_ref, self.mode))] = e 

1827 continue 

1828 return self.generate_inner(schema['schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1829 

1830 def definition_ref_schema(self, schema: core_schema.DefinitionReferenceSchema) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1831 """Generates a JSON schema that matches a schema that references a definition. 

1832 

1833 Args: 

1834 schema: The core schema. 

1835 

1836 Returns: 

1837 The generated JSON schema. 

1838 """ 

1839 core_ref = CoreRef(schema['schema_ref']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1840 _, ref_json_schema = self.get_cache_defs_ref_schema(core_ref) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1841 return ref_json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1842 

1843 def ser_schema( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1844 self, schema: core_schema.SerSchema | core_schema.IncExSeqSerSchema | core_schema.IncExDictSerSchema 

1845 ) -> JsonSchemaValue | None: 

1846 """Generates a JSON schema that matches a schema that defines a serialized object. 

1847 

1848 Args: 

1849 schema: The core schema. 

1850 

1851 Returns: 

1852 The generated JSON schema. 

1853 """ 

1854 schema_type = schema['type'] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1855 if schema_type == 'function-plain' or schema_type == 'function-wrap': 1855 ↛ 1860line 1855 didn't jump to line 1860 because the condition on line 1855 was always true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1856 # PlainSerializerFunctionSerSchema or WrapSerializerFunctionSerSchema 

1857 return_schema = schema.get('return_schema') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1858 if return_schema is not None: 1858 ↛ 1866line 1858 didn't jump to line 1866 because the condition on line 1858 was always true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1859 return self.generate_inner(return_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1860 elif schema_type == 'format' or schema_type == 'to-string': 

1861 # FormatSerSchema or ToStringSerSchema 

1862 return self.str_schema(core_schema.str_schema()) 

1863 elif schema['type'] == 'model': 

1864 # ModelSerSchema 

1865 return self.generate_inner(schema['schema']) 

1866 return None 

1867 

1868 # ### Utility methods 

1869 

1870 def get_title_from_name(self, name: str) -> str: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1871 """Retrieves a title from a name. 

1872 

1873 Args: 

1874 name: The name to retrieve a title from. 

1875 

1876 Returns: 

1877 The title. 

1878 """ 

1879 return name.title().replace('_', ' ') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1880 

1881 def field_title_should_be_set(self, schema: CoreSchemaOrField) -> bool: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1882 """Returns true if a field with the given schema should have a title set based on the field name. 

1883 

1884 Intuitively, we want this to return true for schemas that wouldn't otherwise provide their own title 

1885 (e.g., int, float, str), and false for those that would (e.g., BaseModel subclasses). 

1886 

1887 Args: 

1888 schema: The schema to check. 

1889 

1890 Returns: 

1891 `True` if the field should have a title set, `False` otherwise. 

1892 """ 

1893 if _core_utils.is_core_schema_field(schema): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1894 if schema['type'] == 'computed-field': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1895 field_schema = schema['return_schema'] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1896 else: 

1897 field_schema = schema['schema'] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1898 return self.field_title_should_be_set(field_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1899 

1900 elif _core_utils.is_core_schema(schema): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1901 if schema.get('ref'): # things with refs, such as models and enums, should not have titles set 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1902 return False 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1903 if schema['type'] in {'default', 'nullable', 'definitions'}: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1904 return self.field_title_should_be_set(schema['schema']) # type: ignore[typeddict-item] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1905 if _core_utils.is_function_with_inner_schema(schema): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1906 return self.field_title_should_be_set(schema['schema']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1907 if schema['type'] == 'definition-ref': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1908 # Referenced schemas should not have titles set for the same reason 

1909 # schemas with refs should not 

1910 return False 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1911 return True # anything else should have title set 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1912 

1913 else: 

1914 raise PydanticInvalidForJsonSchema(f'Unexpected schema type: schema={schema}') # pragma: no cover 

1915 

1916 def normalize_name(self, name: str) -> str: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1917 """Normalizes a name to be used as a key in a dictionary. 

1918 

1919 Args: 

1920 name: The name to normalize. 

1921 

1922 Returns: 

1923 The normalized name. 

1924 """ 

1925 return re.sub(r'[^a-zA-Z0-9.\-_]', '_', name).replace('.', '__') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1926 

1927 def get_defs_ref(self, core_mode_ref: CoreModeRef) -> DefsRef: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1928 """Override this method to change the way that definitions keys are generated from a core reference. 

1929 

1930 Args: 

1931 core_mode_ref: The core reference. 

1932 

1933 Returns: 

1934 The definitions key. 

1935 """ 

1936 # Split the core ref into "components"; generic origins and arguments are each separate components 

1937 core_ref, mode = core_mode_ref 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1938 components = re.split(r'([\][,])', core_ref) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1939 # Remove IDs from each component 

1940 components = [x.rsplit(':', 1)[0] for x in components] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1941 core_ref_no_id = ''.join(components) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1942 # Remove everything before the last period from each "component" 

1943 components = [re.sub(r'(?:[^.[\]]+\.)+((?:[^.[\]]+))', r'\1', x) for x in components] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1944 short_ref = ''.join(components) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1945 

1946 mode_title = _MODE_TITLE_MAPPING[mode] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1947 

1948 # It is important that the generated defs_ref values be such that at least one choice will not 

1949 # be generated for any other core_ref. Currently, this should be the case because we include 

1950 # the id of the source type in the core_ref 

1951 name = DefsRef(self.normalize_name(short_ref)) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1952 name_mode = DefsRef(self.normalize_name(short_ref) + f'-{mode_title}') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1953 module_qualname = DefsRef(self.normalize_name(core_ref_no_id)) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1954 module_qualname_mode = DefsRef(f'{module_qualname}-{mode_title}') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1955 module_qualname_id = DefsRef(self.normalize_name(core_ref)) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1956 occurrence_index = self._collision_index.get(module_qualname_id) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1957 if occurrence_index is None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1958 self._collision_counter[module_qualname] += 1 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1959 occurrence_index = self._collision_index[module_qualname_id] = self._collision_counter[module_qualname] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1960 

1961 module_qualname_occurrence = DefsRef(f'{module_qualname}__{occurrence_index}') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1962 module_qualname_occurrence_mode = DefsRef(f'{module_qualname_mode}__{occurrence_index}') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1963 

1964 self._prioritized_defsref_choices[module_qualname_occurrence_mode] = [ 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1965 name, 

1966 name_mode, 

1967 module_qualname, 

1968 module_qualname_mode, 

1969 module_qualname_occurrence, 

1970 module_qualname_occurrence_mode, 

1971 ] 

1972 

1973 return module_qualname_occurrence_mode 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1974 

1975 def get_cache_defs_ref_schema(self, core_ref: CoreRef) -> tuple[DefsRef, JsonSchemaValue]: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

1976 """This method wraps the get_defs_ref method with some cache-lookup/population logic, 

1977 and returns both the produced defs_ref and the JSON schema that will refer to the right definition. 

1978 

1979 Args: 

1980 core_ref: The core reference to get the definitions reference for. 

1981 

1982 Returns: 

1983 A tuple of the definitions reference and the JSON schema that will refer to it. 

1984 """ 

1985 core_mode_ref = (core_ref, self.mode) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1986 maybe_defs_ref = self.core_to_defs_refs.get(core_mode_ref) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1987 if maybe_defs_ref is not None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1988 json_ref = self.core_to_json_refs[core_mode_ref] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1989 return maybe_defs_ref, {'$ref': json_ref} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1990 

1991 defs_ref = self.get_defs_ref(core_mode_ref) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1992 

1993 # populate the ref translation mappings 

1994 self.core_to_defs_refs[core_mode_ref] = defs_ref 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1995 self.defs_to_core_refs[defs_ref] = core_mode_ref 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1996 

1997 json_ref = JsonRef(self.ref_template.format(model=defs_ref)) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1998 self.core_to_json_refs[core_mode_ref] = json_ref 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

1999 self.json_to_defs_refs[json_ref] = defs_ref 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2000 ref_json_schema = {'$ref': json_ref} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2001 return defs_ref, ref_json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2002 

2003 def handle_ref_overrides(self, json_schema: JsonSchemaValue) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2004 """It is not valid for a schema with a top-level $ref to have sibling keys. 

2005 

2006 During our own schema generation, we treat sibling keys as overrides to the referenced schema, 

2007 but this is not how the official JSON schema spec works. 

2008 

2009 Because of this, we first remove any sibling keys that are redundant with the referenced schema, then if 

2010 any remain, we transform the schema from a top-level '$ref' to use allOf to move the $ref out of the top level. 

2011 (See bottom of https://swagger.io/docs/specification/using-ref/ for a reference about this behavior) 

2012 """ 

2013 if '$ref' in json_schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2014 # prevent modifications to the input; this copy may be safe to drop if there is significant overhead 

2015 json_schema = json_schema.copy() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2016 

2017 referenced_json_schema = self.get_schema_from_definitions(JsonRef(json_schema['$ref'])) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2018 if referenced_json_schema is None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2019 # This can happen when building schemas for models with not-yet-defined references. 

2020 # It may be a good idea to do a recursive pass at the end of the generation to remove 

2021 # any redundant override keys. 

2022 if len(json_schema) > 1: 2022 ↛ 2024line 2022 didn't jump to line 2024 because the condition on line 2022 was never true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2023 # Make it an allOf to at least resolve the sibling keys issue 

2024 json_schema = json_schema.copy() 

2025 json_schema.setdefault('allOf', []) 

2026 json_schema['allOf'].append({'$ref': json_schema['$ref']}) 

2027 del json_schema['$ref'] 

2028 

2029 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2030 for k, v in list(json_schema.items()): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2031 if k == '$ref': 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2032 continue 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2033 if k in referenced_json_schema and referenced_json_schema[k] == v: 2033 ↛ 2034line 2033 didn't jump to line 2034 because the condition on line 2033 was never true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2034 del json_schema[k] # redundant key 

2035 if len(json_schema) > 1: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2036 # There is a remaining "override" key, so we need to move $ref out of the top level 

2037 json_ref = JsonRef(json_schema['$ref']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2038 del json_schema['$ref'] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2039 assert 'allOf' not in json_schema # this should never happen, but just in case 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2040 json_schema['allOf'] = [{'$ref': json_ref}] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2041 

2042 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2043 

2044 def get_schema_from_definitions(self, json_ref: JsonRef) -> JsonSchemaValue | None: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2045 def_ref = self.json_to_defs_refs[json_ref] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2046 if def_ref in self._core_defs_invalid_for_json_schema: 2046 ↛ 2047line 2046 didn't jump to line 2047 because the condition on line 2046 was never true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2047 raise self._core_defs_invalid_for_json_schema[def_ref] 

2048 return self.definitions.get(def_ref, None) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2049 

2050 def encode_default(self, dft: Any) -> Any: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2051 """Encode a default value to a JSON-serializable value. 

2052 

2053 This is used to encode default values for fields in the generated JSON schema. 

2054 

2055 Args: 

2056 dft: The default value to encode. 

2057 

2058 Returns: 

2059 The encoded default value. 

2060 """ 

2061 from .type_adapter import TypeAdapter, _type_has_config 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2062 

2063 config = self._config 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2064 try: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2065 default = ( 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2066 dft 

2067 if _type_has_config(type(dft)) 

2068 else TypeAdapter(type(dft), config=config.config_dict).dump_python(dft, mode='json') 

2069 ) 

2070 except PydanticSchemaGenerationError: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2071 raise pydantic_core.PydanticSerializationError(f'Unable to encode default value {dft}') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2072 

2073 return pydantic_core.to_jsonable_python( 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2074 default, 

2075 timedelta_mode=config.ser_json_timedelta, 

2076 bytes_mode=config.ser_json_bytes, 

2077 ) 

2078 

2079 def update_with_validations( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2080 self, json_schema: JsonSchemaValue, core_schema: CoreSchema, mapping: dict[str, str] 

2081 ) -> None: 

2082 """Update the json_schema with the corresponding validations specified in the core_schema, 

2083 using the provided mapping to translate keys in core_schema to the appropriate keys for a JSON schema. 

2084 

2085 Args: 

2086 json_schema: The JSON schema to update. 

2087 core_schema: The core schema to get the validations from. 

2088 mapping: A mapping from core_schema attribute names to the corresponding JSON schema attribute names. 

2089 """ 

2090 for core_key, json_schema_key in mapping.items(): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2091 if core_key in core_schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2092 json_schema[json_schema_key] = core_schema[core_key] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2093 

2094 class ValidationsMapping: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2095 """This class just contains mappings from core_schema attribute names to the corresponding 

2096 JSON schema attribute names. While I suspect it is unlikely to be necessary, you can in 

2097 principle override this class in a subclass of GenerateJsonSchema (by inheriting from 

2098 GenerateJsonSchema.ValidationsMapping) to change these mappings. 

2099 """ 

2100 

2101 numeric = { 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2102 'multiple_of': 'multipleOf', 

2103 'le': 'maximum', 

2104 'ge': 'minimum', 

2105 'lt': 'exclusiveMaximum', 

2106 'gt': 'exclusiveMinimum', 

2107 } 

2108 bytes = { 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2109 'min_length': 'minLength', 

2110 'max_length': 'maxLength', 

2111 } 

2112 string = { 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2113 'min_length': 'minLength', 

2114 'max_length': 'maxLength', 

2115 'pattern': 'pattern', 

2116 } 

2117 array = { 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2118 'min_length': 'minItems', 

2119 'max_length': 'maxItems', 

2120 } 

2121 object = { 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2122 'min_length': 'minProperties', 

2123 'max_length': 'maxProperties', 

2124 } 

2125 date = { 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2126 'le': 'maximum', 

2127 'ge': 'minimum', 

2128 'lt': 'exclusiveMaximum', 

2129 'gt': 'exclusiveMinimum', 

2130 } 

2131 

2132 def get_flattened_anyof(self, schemas: list[JsonSchemaValue]) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2133 members = [] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2134 for schema in schemas: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2135 if len(schema) == 1 and 'anyOf' in schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2136 members.extend(schema['anyOf']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2137 else: 

2138 members.append(schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2139 members = _deduplicate_schemas(members) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2140 if len(members) == 1: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2141 return members[0] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2142 return {'anyOf': members} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2143 

2144 def get_json_ref_counts(self, json_schema: JsonSchemaValue) -> dict[JsonRef, int]: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2145 """Get all values corresponding to the key '$ref' anywhere in the json_schema.""" 

2146 json_refs: dict[JsonRef, int] = Counter() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2147 

2148 def _add_json_refs(schema: Any) -> None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2149 if isinstance(schema, dict): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2150 if '$ref' in schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2151 json_ref = JsonRef(schema['$ref']) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2152 if not isinstance(json_ref, str): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2153 return # in this case, '$ref' might have been the name of a property 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2154 already_visited = json_ref in json_refs 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2155 json_refs[json_ref] += 1 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2156 if already_visited: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2157 return # prevent recursion on a definition that was already visited 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2158 defs_ref = self.json_to_defs_refs[json_ref] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2159 if defs_ref in self._core_defs_invalid_for_json_schema: 2159 ↛ 2160line 2159 didn't jump to line 2160 because the condition on line 2159 was never true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2160 raise self._core_defs_invalid_for_json_schema[defs_ref] 

2161 _add_json_refs(self.definitions[defs_ref]) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2162 

2163 for v in schema.values(): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2164 _add_json_refs(v) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2165 elif isinstance(schema, list): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2166 for v in schema: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2167 _add_json_refs(v) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2168 

2169 _add_json_refs(json_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2170 return json_refs 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2171 

2172 def handle_invalid_for_json_schema(self, schema: CoreSchemaOrField, error_info: str) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2173 raise PydanticInvalidForJsonSchema(f'Cannot generate a JsonSchema for {error_info}') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2174 

2175 def emit_warning(self, kind: JsonSchemaWarningKind, detail: str) -> None: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2176 """This method simply emits PydanticJsonSchemaWarnings based on handling in the `warning_message` method.""" 

2177 message = self.render_warning_message(kind, detail) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2178 if message is not None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2179 warnings.warn(message, PydanticJsonSchemaWarning) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2180 

2181 def render_warning_message(self, kind: JsonSchemaWarningKind, detail: str) -> str | None: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2182 """This method is responsible for ignoring warnings as desired, and for formatting the warning messages. 

2183 

2184 You can override the value of `ignored_warning_kinds` in a subclass of GenerateJsonSchema 

2185 to modify what warnings are generated. If you want more control, you can override this method; 

2186 just return None in situations where you don't want warnings to be emitted. 

2187 

2188 Args: 

2189 kind: The kind of warning to render. It can be one of the following: 

2190 

2191 - 'skipped-choice': A choice field was skipped because it had no valid choices. 

2192 - 'non-serializable-default': A default value was skipped because it was not JSON-serializable. 

2193 detail: A string with additional details about the warning. 

2194 

2195 Returns: 

2196 The formatted warning message, or `None` if no warning should be emitted. 

2197 """ 

2198 if kind in self.ignored_warning_kinds: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2199 return None 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2200 return f'{detail} [{kind}]' 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2201 

2202 def _build_definitions_remapping(self) -> _DefinitionsRemapping: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2203 defs_to_json: dict[DefsRef, JsonRef] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2204 for defs_refs in self._prioritized_defsref_choices.values(): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2205 for defs_ref in defs_refs: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2206 json_ref = JsonRef(self.ref_template.format(model=defs_ref)) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2207 defs_to_json[defs_ref] = json_ref 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2208 

2209 return _DefinitionsRemapping.from_prioritized_choices( 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2210 self._prioritized_defsref_choices, defs_to_json, self.definitions 

2211 ) 

2212 

2213 def _garbage_collect_definitions(self, schema: JsonSchemaValue) -> None: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2214 visited_defs_refs: set[DefsRef] = set() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2215 unvisited_json_refs = _get_all_json_refs(schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2216 while unvisited_json_refs: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2217 next_json_ref = unvisited_json_refs.pop() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2218 next_defs_ref = self.json_to_defs_refs[next_json_ref] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2219 if next_defs_ref in visited_defs_refs: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2220 continue 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2221 visited_defs_refs.add(next_defs_ref) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2222 unvisited_json_refs.update(_get_all_json_refs(self.definitions[next_defs_ref])) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2223 

2224 self.definitions = {k: v for k, v in self.definitions.items() if k in visited_defs_refs} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2225 

2226 

2227# ##### Start JSON Schema Generation Functions ##### 

2228 

2229 

2230def model_json_schema( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2231 cls: type[BaseModel] | type[PydanticDataclass], 

2232 by_alias: bool = True, 

2233 ref_template: str = DEFAULT_REF_TEMPLATE, 

2234 schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema, 

2235 mode: JsonSchemaMode = 'validation', 

2236) -> dict[str, Any]: 

2237 """Utility function to generate a JSON Schema for a model. 

2238 

2239 Args: 

2240 cls: The model class to generate a JSON Schema for. 

2241 by_alias: If `True` (the default), fields will be serialized according to their alias. 

2242 If `False`, fields will be serialized according to their attribute name. 

2243 ref_template: The template to use for generating JSON Schema references. 

2244 schema_generator: The class to use for generating the JSON Schema. 

2245 mode: The mode to use for generating the JSON Schema. It can be one of the following: 

2246 

2247 - 'validation': Generate a JSON Schema for validating data. 

2248 - 'serialization': Generate a JSON Schema for serializing data. 

2249 

2250 Returns: 

2251 The generated JSON Schema. 

2252 """ 

2253 from .main import BaseModel 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2254 

2255 schema_generator_instance = schema_generator(by_alias=by_alias, ref_template=ref_template) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2256 

2257 if isinstance(cls.__pydantic_core_schema__, _mock_val_ser.MockCoreSchema): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2258 cls.__pydantic_core_schema__.rebuild() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2259 

2260 if cls is BaseModel: 2260 ↛ 2261line 2260 didn't jump to line 2261 because the condition on line 2260 was never true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2261 raise AttributeError('model_json_schema() must be called on a subclass of BaseModel, not BaseModel itself.') 

2262 

2263 assert not isinstance(cls.__pydantic_core_schema__, _mock_val_ser.MockCoreSchema), 'this is a bug! please report it' 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2264 return schema_generator_instance.generate(cls.__pydantic_core_schema__, mode=mode) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2265 

2266 

2267def models_json_schema( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2268 models: Sequence[tuple[type[BaseModel] | type[PydanticDataclass], JsonSchemaMode]], 

2269 *, 

2270 by_alias: bool = True, 

2271 title: str | None = None, 

2272 description: str | None = None, 

2273 ref_template: str = DEFAULT_REF_TEMPLATE, 

2274 schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema, 

2275) -> tuple[dict[tuple[type[BaseModel] | type[PydanticDataclass], JsonSchemaMode], JsonSchemaValue], JsonSchemaValue]: 

2276 """Utility function to generate a JSON Schema for multiple models. 

2277 

2278 Args: 

2279 models: A sequence of tuples of the form (model, mode). 

2280 by_alias: Whether field aliases should be used as keys in the generated JSON Schema. 

2281 title: The title of the generated JSON Schema. 

2282 description: The description of the generated JSON Schema. 

2283 ref_template: The reference template to use for generating JSON Schema references. 

2284 schema_generator: The schema generator to use for generating the JSON Schema. 

2285 

2286 Returns: 

2287 A tuple where: 

2288 - The first element is a dictionary whose keys are tuples of JSON schema key type and JSON mode, and 

2289 whose values are the JSON schema corresponding to that pair of inputs. (These schemas may have 

2290 JsonRef references to definitions that are defined in the second returned element.) 

2291 - The second element is a JSON schema containing all definitions referenced in the first returned 

2292 element, along with the optional title and description keys. 

2293 """ 

2294 for cls, _ in models: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2295 if isinstance(cls.__pydantic_core_schema__, _mock_val_ser.MockCoreSchema): 2295 ↛ 2296line 2295 didn't jump to line 2296 because the condition on line 2295 was never true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2296 cls.__pydantic_core_schema__.rebuild() 

2297 

2298 instance = schema_generator(by_alias=by_alias, ref_template=ref_template) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2299 inputs: list[tuple[type[BaseModel] | type[PydanticDataclass], JsonSchemaMode, CoreSchema]] = [ 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2300 (m, mode, m.__pydantic_core_schema__) for m, mode in models 

2301 ] 

2302 json_schemas_map, definitions = instance.generate_definitions(inputs) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2303 

2304 json_schema: dict[str, Any] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2305 if definitions: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2306 json_schema['$defs'] = definitions 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2307 if title: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2308 json_schema['title'] = title 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2309 if description: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2310 json_schema['description'] = description 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2311 

2312 return json_schemas_map, json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2313 

2314 

2315# ##### End JSON Schema Generation Functions ##### 

2316 

2317 

2318_HashableJsonValue: TypeAlias = Union[ 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2319 int, float, str, bool, None, Tuple['_HashableJsonValue', ...], Tuple[Tuple[str, '_HashableJsonValue'], ...] 

2320] 

2321 

2322 

2323def _deduplicate_schemas(schemas: Iterable[JsonDict]) -> list[JsonDict]: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2324 return list({_make_json_hashable(schema): schema for schema in schemas}.values()) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2325 

2326 

2327def _make_json_hashable(value: JsonValue) -> _HashableJsonValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2328 if isinstance(value, dict): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2329 return tuple(sorted((k, _make_json_hashable(v)) for k, v in value.items())) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2330 elif isinstance(value, list): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2331 return tuple(_make_json_hashable(v) for v in value) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2332 else: 

2333 return value 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2334 

2335 

2336def _sort_json_schema(value: JsonSchemaValue, parent_key: str | None = None) -> JsonSchemaValue: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2337 if isinstance(value, dict): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2338 sorted_dict: dict[str, JsonSchemaValue] = {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2339 keys = value.keys() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2340 if (parent_key != 'properties') and (parent_key != 'default'): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2341 keys = sorted(keys) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2342 for key in keys: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2343 sorted_dict[key] = _sort_json_schema(value[key], parent_key=key) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2344 return sorted_dict 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2345 elif isinstance(value, list): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2346 sorted_list: list[JsonSchemaValue] = [] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2347 for item in value: # type: ignore 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2348 sorted_list.append(_sort_json_schema(item, parent_key)) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2349 return sorted_list # type: ignore 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2350 else: 

2351 return value 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2352 

2353 

2354@dataclasses.dataclass(**_internal_dataclass.slots_true) 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2355class WithJsonSchema: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2356 """Usage docs: https://docs.pydantic.dev/2.8/concepts/json_schema/#withjsonschema-annotation 

2357 

2358 Add this as an annotation on a field to override the (base) JSON schema that would be generated for that field. 

2359 This provides a way to set a JSON schema for types that would otherwise raise errors when producing a JSON schema, 

2360 such as Callable, or types that have an is-instance core schema, without needing to go so far as creating a 

2361 custom subclass of pydantic.json_schema.GenerateJsonSchema. 

2362 Note that any _modifications_ to the schema that would normally be made (such as setting the title for model fields) 

2363 will still be performed. 

2364 

2365 If `mode` is set this will only apply to that schema generation mode, allowing you 

2366 to set different json schemas for validation and serialization. 

2367 """ 

2368 

2369 json_schema: JsonSchemaValue | None 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2370 mode: Literal['validation', 'serialization'] | None = None 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2371 

2372 def __get_pydantic_json_schema__( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2373 self, core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler 

2374 ) -> JsonSchemaValue: 

2375 mode = self.mode or handler.mode 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2376 if mode != handler.mode: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2377 return handler(core_schema) 1EzaekHAcio

2378 if self.json_schema is None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2379 # This exception is handled in pydantic.json_schema.GenerateJsonSchema._named_required_fields_schema 

2380 raise PydanticOmit 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2381 else: 

2382 return self.json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2383 

2384 def __hash__(self) -> int: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2385 return hash(type(self.mode)) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2386 

2387 

2388@dataclasses.dataclass(**_internal_dataclass.slots_true) 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2389class Examples: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2390 """Add examples to a JSON schema. 

2391 

2392 Examples should be a map of example names (strings) 

2393 to example values (any valid JSON). 

2394 

2395 If `mode` is set this will only apply to that schema generation mode, 

2396 allowing you to add different examples for validation and serialization. 

2397 """ 

2398 

2399 examples: dict[str, Any] 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2400 mode: Literal['validation', 'serialization'] | None = None 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2401 

2402 def __get_pydantic_json_schema__( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2403 self, core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler 

2404 ) -> JsonSchemaValue: 

2405 mode = self.mode or handler.mode 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2406 json_schema = handler(core_schema) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2407 if mode != handler.mode: 2407 ↛ 2408line 2407 didn't jump to line 2408 because the condition on line 2407 was never true1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2408 return json_schema 

2409 examples = json_schema.get('examples', {}) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2410 examples.update(to_jsonable_python(self.examples)) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2411 json_schema['examples'] = examples 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2412 return json_schema 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2413 

2414 def __hash__(self) -> int: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2415 return hash(type(self.mode)) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2416 

2417 

2418def _get_all_json_refs(item: Any) -> set[JsonRef]: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2419 """Get all the definitions references from a JSON schema.""" 

2420 refs: set[JsonRef] = set() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2421 stack = [item] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2422 

2423 while stack: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2424 current = stack.pop() 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2425 if isinstance(current, dict): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2426 for key, value in current.items(): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2427 if key == '$ref' and isinstance(value, str): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2428 refs.add(JsonRef(value)) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2429 elif isinstance(value, dict): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2430 stack.append(value) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2431 elif isinstance(value, list): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2432 stack.extend(value) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2433 elif isinstance(current, list): 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2434 stack.extend(current) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2435 

2436 return refs 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2437 

2438 

2439AnyType = TypeVar('AnyType') 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2440 

2441if TYPE_CHECKING: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2442 SkipJsonSchema = Annotated[AnyType, ...] 

2443else: 

2444 

2445 @dataclasses.dataclass(**_internal_dataclass.slots_true) 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2446 class SkipJsonSchema: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2447 """Usage docs: https://docs.pydantic.dev/2.8/concepts/json_schema/#skipjsonschema-annotation 

2448 

2449 Add this as an annotation on a field to skip generating a JSON schema for that field. 

2450 

2451 Example: 

2452 ```py 

2453 from typing import Union 

2454 

2455 from pydantic import BaseModel 

2456 from pydantic.json_schema import SkipJsonSchema 

2457 

2458 from pprint import pprint 

2459 

2460 

2461 class Model(BaseModel): 

2462 a: Union[int, None] = None # (1)! 

2463 b: Union[int, SkipJsonSchema[None]] = None # (2)! 

2464 c: SkipJsonSchema[Union[int, None]] = None # (3)! 

2465 

2466 

2467 pprint(Model.model_json_schema()) 

2468 ''' 

2469 { 

2470 'properties': { 

2471 'a': { 

2472 'anyOf': [ 

2473 {'type': 'integer'}, 

2474 {'type': 'null'} 

2475 ], 

2476 'default': None, 

2477 'title': 'A' 

2478 }, 

2479 'b': { 

2480 'default': None, 

2481 'title': 'B', 

2482 'type': 'integer' 

2483 } 

2484 }, 

2485 'title': 'Model', 

2486 'type': 'object' 

2487 } 

2488 ''' 

2489 ``` 

2490 

2491 1. The integer and null types are both included in the schema for `a`. 

2492 2. The integer type is the only type included in the schema for `b`. 

2493 3. The entirety of the `c` field is omitted from the schema. 

2494 """ 

2495 

2496 def __class_getitem__(cls, item: AnyType) -> AnyType: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2497 return Annotated[item, cls()] 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2498 

2499 def __get_pydantic_json_schema__( 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2500 self, core_schema: CoreSchema, handler: GetJsonSchemaHandler 

2501 ) -> JsonSchemaValue: 

2502 raise PydanticOmit 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2503 

2504 def __hash__(self) -> int: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2505 return hash(type(self)) 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2506 

2507 

2508def _get_typed_dict_cls(schema: core_schema.TypedDictSchema) -> type[Any] | None: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2509 metadata = _core_metadata.CoreMetadataHandler(schema).metadata 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2510 cls = metadata.get('pydantic_typed_dict_cls') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2511 return cls 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2512 

2513 

2514def _get_typed_dict_config(cls: type[Any] | None) -> ConfigDict: 1EIzBadejkpqrCbKLFGfglmstuvUVMNOPQRSTHJADchinowxy

2515 if cls is not None: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2516 try: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2517 return _decorators.get_attribute_from_bases(cls, '__pydantic_config__') 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2518 except AttributeError: 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2519 pass 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy

2520 return {} 1EIzBadejkpqrCbKLFGfglmstuvHJADchinowxy