Coverage for pydantic/json_schema.py: 94.57%

1020 statements  

« prev     ^ index     » next       coverage.py v7.5.3, created at 2024-06-21 17:00 +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 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

13 

14import dataclasses 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

15import inspect 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

16import math 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

17import re 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

18import warnings 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

19from collections import defaultdict 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

20from copy import deepcopy 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

21from dataclasses import is_dataclass 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

22from enum import Enum 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

23from typing import ( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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

42from pydantic_core.core_schema import ComputedField 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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

44 

45from pydantic.warnings import PydanticDeprecatedSince26 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

46 

47from ._internal import ( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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

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

60 

61if TYPE_CHECKING: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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] 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

70""" 1adejkpbfglmqrGHIJKLMchinos

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] 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

77""" 1adejkpbfglmqrGHIJKLMchinos

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'] 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

82""" 1adejkpbfglmqrGHIJKLMchinos

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'} 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

92 

93 

94@deprecated( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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'] 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

115""" 1adejkpbfglmqrGHIJKLMchinos

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): 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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}' 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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

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) 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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) 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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) 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

146 

147CoreModeRef = Tuple[CoreRef, JsonSchemaMode] 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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

149 

150 

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

152class _DefinitionsRemapping: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

153 defs_remapping: dict[DefsRef, DefsRef] 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

154 json_remapping: dict[JsonRef, JsonRef] 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

155 

156 @staticmethod 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

157 def from_prioritized_choices( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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 complete1yCtvadejkpwbEFzAfglmqrBDuxchinos

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

175 for defs_ref in copied_definitions: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

176 alternatives = prioritized_choices[defs_ref] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

177 for alternative in alternatives: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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(): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

184 

185 # Build the remapping 

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

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

188 for original_defs_ref in definitions: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

189 alternatives = prioritized_choices[original_defs_ref] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 1911yCtvadejkpwbEFzAfglmqrBDuxchinos

192 defs_remapping[original_defs_ref] = remapped_defs_ref 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

194 remapping = _DefinitionsRemapping(defs_remapping, json_remapping) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

196 if definitions_schema == new_definitions_schema: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

197 # We've reached the fixed point 

198 return remapping 1yCtvadejkpwbEFzAfglmqrBDuxchinos

199 definitions_schema = new_definitions_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

200 

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

202 

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

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

205 

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

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

208 

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

210 """ 

211 Recursively update the JSON schema replacing all $refs 

212 """ 

213 if isinstance(schema, str): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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)) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

216 elif isinstance(schema, list): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

218 elif isinstance(schema, dict): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

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

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

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

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

229 return schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

230 

231 

232class GenerateJsonSchema: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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' 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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'} 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

270 

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

272 self.by_alias = by_alias 1yCtvadejkpwbEFzAfglmqrBDuxchinos

273 self.ref_template = ref_template 1yCtvadejkpwbEFzAfglmqrBDuxchinos

274 

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

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

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

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

279 

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

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

282 

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

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]] = {} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

292 

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

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] = {} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

306 

307 @property 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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

309 return self._config_wrapper_stack.tail 1yCtvadejkpwbEFzAfglmqrBDuxchinos

310 

311 @property 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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

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

314 return self._config.json_schema_mode_override 1yCtvadejkpwbEFzAfglmqrBDuxchinos

315 else: 

316 return self._mode 1yCtvadejkpwbEFzAfglmqrBDuxchinos

317 

318 def build_schema_type_to_method( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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]] = {} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

331 CoreSchemaOrFieldType # type: ignore 

332 ) 

333 for key in core_schema_types: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

335 try: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

343 

344 def generate_definitions( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

370 raise PydanticUserError( 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

377 self._mode = mode 1yCtvadejkpwbEFzAfglmqrBDuxchinos

378 self.generate_inner(schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

379 

380 definitions_remapping = self._build_definitions_remapping() 1yCtvadejkpwbEFzAfglmqrBDuxchinos

381 

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

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

384 self._mode = mode 1yCtvadejkpwbEFzAfglmqrBDuxchinos

385 json_schema = self.generate_inner(schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

387 

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

389 json_schema = definitions_remapping.remap_json_schema(json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

390 self._used = True 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

392 

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

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

407 if self._used: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

408 raise PydanticUserError( 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

415 json_ref_counts = self.get_json_ref_counts(json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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')) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

420 ref_json_schema = self.get_schema_from_definitions(ref) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

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

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

427 json_ref_counts[ref] -= 1 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

429 

430 self._garbage_collect_definitions(json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

431 definitions_remapping = self._build_definitions_remapping() 1yCtvadejkpwbEFzAfglmqrBDuxchinos

432 

433 if self.definitions: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

435 

436 json_schema = definitions_remapping.remap_json_schema(json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

443 return _sort_json_schema(json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

444 

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

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: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

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

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

462 

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

464 metadata_handler = _core_metadata.CoreMetadataHandler(schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

465 

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

467 if 'ref' in core_schema: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

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

471 self.json_to_defs_refs[json_ref] = defs_ref 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

476 self.definitions[defs_ref] = json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

478 json_schema = ref_json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

479 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

480 

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

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

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() 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

488 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

489 

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

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

506 json_schema = self.ser_schema(ser_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

507 if json_schema is None: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 true1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

510 json_schema = generate_for_schema_type(schema_or_field) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

511 else: 

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

513 if _core_utils.is_core_schema(schema_or_field): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

514 json_schema = populate_defs(schema_or_field, json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

515 json_schema = convert_to_all_of(json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

516 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

517 

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

519 

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

521 

522 def new_handler_func( 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 true1yCtvadejkpwbEFzAfglmqrBDuxchinos

529 json_schema = populate_defs(schema_or_field, json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

530 original_schema = current_handler.resolve_ref_schema(json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

532 if ref and json_schema: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

533 original_schema.update(json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

534 return original_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

535 

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

537 

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

539 

540 def new_handler_func( 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

546 if _core_utils.is_core_schema(schema_or_field): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

547 json_schema = populate_defs(schema_or_field, json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

548 json_schema = convert_to_all_of(json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

549 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

550 

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

552 

553 json_schema = current_handler(schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

554 if _core_utils.is_core_schema(schema): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

555 json_schema = populate_defs(schema, json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

556 json_schema = convert_to_all_of(json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

557 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

558 

559 # ### Schema generation methods 

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

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 {} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

570 

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

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'} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

581 

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

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'} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

592 

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

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'} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

605 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

606 

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

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'} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

619 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

620 

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

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()) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

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

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

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

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

637 json_schema = { 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

653 

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

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'} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

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

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

668 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

669 

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

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'} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

681 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

682 

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

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'} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

694 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

695 

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

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'} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

706 

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

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'} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

717 

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

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': 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

730 

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

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']] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

741 # jsonify the expected values 

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

743 

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

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

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

747 

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

749 if types == {str}: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

751 elif types == {int}: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

753 elif types == {float}: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

755 elif types == {bool}: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

757 elif types == {list}: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

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

761 return result 1yCtvadejkpwbEFzAfglmqrBDuxchinos

762 

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

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'] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

774 if ( 1yCtvwbBDux

775 description == 'An enumeration.' 

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

777 description = None 1yCtvadwbEFzAfgBDuxch

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

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

780 

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

782 

783 result['enum'] = expected 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

786 

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

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

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

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

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

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

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

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

795 result['type'] = 'boolean' 

796 elif types == {list}: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

798 

799 return result 1yCtvadejkpwbEFzAfglmqrBDuxchinos

800 

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

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"]})') 1yCtvadejkpwbEFzAfglmqrBDuxchinos

813 

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

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 {} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

827 

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

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') 1yCtvadejkpwbEFzAfglmqrBDuxchinos

840 

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

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

853 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

854 

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

856 @final 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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

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) 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

867 @final 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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

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: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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'} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

888 if 'variadic_item_index' in schema: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

889 variadic_item_index = schema['variadic_item_index'] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

890 if variadic_item_index > 0: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

891 json_schema['minItems'] = variadic_item_index 1yCtvadejkpwbEFzAfglmqrBDuxchinos

892 json_schema['prefixItems'] = [ 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 true1yCtvadejkpwbEFzAfglmqrBDuxchinos

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]) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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']] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

905 if prefixItems: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

906 json_schema['prefixItems'] = prefixItems 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

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

910 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

911 

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

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

922 

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

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

933 

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

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

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

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

938 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

939 

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

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

952 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

953 

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

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'} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

964 

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

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

967 

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

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

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

971 if keys_pattern is None: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

972 json_schema['additionalProperties'] = values_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

973 else: 

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

975 

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

977 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

978 

979 def _function_schema( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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 true1yCtvadejkpwbEFzAfglmqrBDuxchinos

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1003 

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

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1014 

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

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: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1036 

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

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1047 

1048 if 'default' not in schema: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1049 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1050 default = schema['default'] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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': 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1065 if ( 1yCtvadejwbEFzAfglmBDuxchin

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1072 

1073 try: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1074 encoded_default = self.encode_default(default) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1075 except pydantic_core.PydanticSerializationError: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1076 self.emit_warning( 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1082 

1083 if '$ref' in json_schema: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1086 else: 

1087 json_schema['default'] = encoded_default 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1088 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1089 

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

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'} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1101 

1102 if inner_json_schema == null_schema: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1103 return null_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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]) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1108 

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

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] = [] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1119 

1120 choices = schema['choices'] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1121 for choice in choices: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

1124 try: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1126 except PydanticOmit: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1127 continue 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1128 except PydanticInvalidForJsonSchema as exc: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

1131 return generated[0] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1132 return self.get_flattened_anyof(generated) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1133 

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

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] = {} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1147 if isinstance(k, Enum): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1148 k = k.value 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1149 try: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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() 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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()) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1163 if openapi_discriminator is not None: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1164 json_schema['discriminator'] = { 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1165 'propertyName': openapi_discriminator, 

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

1167 } 

1168 

1169 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1170 

1171 def _extract_discriminator( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1177 

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

1179 return schema['discriminator'] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1180 

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

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 true1yCtvadejkpwbEFzAfglmqrBDuxchinos

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']: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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 true1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1194 alias = alias_path[0] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

1197 alias_is_present_on_all_choices = True 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1198 for choice in one_of_choices: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1199 while '$ref' in choice: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

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

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

1204 alias_is_present_on_all_choices = False 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1205 break 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1206 if alias_is_present_on_all_choices: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1207 openapi_discriminator = alias 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1208 break 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1209 return openapi_discriminator 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1210 

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

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1225 

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

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1239 # because one of the following two branches failed. 

1240 if use_strict: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1242 else: 

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

1244 

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

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1259 

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

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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': 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1277 cls = _get_typed_dict_cls(schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1278 config = _get_typed_dict_config(cls) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1280 json_schema = self._named_required_fields_schema(named_required_fields) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1281 

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

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

1284 if extra is None: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1286 

1287 if cls is not None: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

1290 else: 

1291 if extra == 'forbid': 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1292 json_schema['additionalProperties'] = False 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1293 elif extra == 'allow': 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1294 json_schema['additionalProperties'] = True 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1295 

1296 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1297 

1298 @staticmethod 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

1299 def _name_required_computed_fields( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1303 

1304 def _named_required_fields_schema( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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

1306 ) -> JsonSchemaValue: 

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

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

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

1310 if self.by_alias: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1312 try: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1314 except PydanticOmit: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1315 continue 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1317 title = self.get_title_from_name(name) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1318 field_json_schema['title'] = title 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1319 field_json_schema = self.handle_ref_overrides(field_json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1320 properties[name] = field_json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1321 if required: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1322 required_fields.append(name) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1323 

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

1325 if required_fields: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1326 json_schema['required'] = required_fields 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1327 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1328 

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

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

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

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

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

1334 else: 

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

1336 if isinstance(alias, str): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1337 name = alias 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1338 elif isinstance(alias, list): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

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

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] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1345 break 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1346 else: 

1347 assert_never(alias) 

1348 return name 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1349 

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

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1360 

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

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1371 

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

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1382 

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

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1393 

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

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1406 config = cls.model_config 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1408 

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

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

1411 

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

1413 if cls.__pydantic_root_model__: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1415 if json_schema_extra and root_json_schema_extra: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1416 raise ValueError( 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1421 json_schema_extra = root_json_schema_extra 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1422 

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

1424 

1425 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1426 

1427 def _update_class_schema( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1437 else: 

1438 schema_to_update = json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1439 

1440 if title is not None: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1441 # referenced_schema['title'] = title 

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

1443 

1444 if 'additionalProperties' not in schema_to_update: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1445 if extra == 'allow': 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1446 schema_to_update['additionalProperties'] = True 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1447 elif extra == 'forbid': 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1448 schema_to_update['additionalProperties'] = False 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1449 

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

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

1452 json_schema_extra = json_schema_extra.__get__(cls) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1453 

1454 if isinstance(json_schema_extra, dict): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1455 schema_to_update.update(json_schema_extra) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1456 elif callable(json_schema_extra): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

1459 else: 

1460 json_schema_extra(schema_to_update) # type: ignore 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1461 elif json_schema_extra is not None: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1462 raise ValueError( 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1464 ) 

1465 

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

1467 json_schema['deprecated'] = True 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1468 

1469 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1470 

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

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 true1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1487 return schema_to_update 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1488 

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

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]] = [ 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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': 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1505 json_schema = self._named_required_fields_schema(named_required_fields) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1507 if extras_schema is not None: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1508 schema_to_update = self.resolve_schema_to_update(json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1510 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1511 

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

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': 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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') 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1526 return True 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1527 else: 

1528 assert_never(self.mode) 

1529 

1530 def field_is_required( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1549 else: 

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

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

1552 else: 

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

1554 

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

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]] = [ 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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': 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1571 return self._named_required_fields_schema(named_required_fields) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1572 

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

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'] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

1585 

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

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

1588 

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

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

1591 

1592 # Dataclass-specific handling of description 

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

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

1595 description = None 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1596 else: 

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

1598 if description: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1599 json_schema['description'] = description 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1600 

1601 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1602 

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

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1614 

1615 arguments = schema['arguments_schema'] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

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

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

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

1621 

1622 if prefer_positional: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1623 positional_possible = not kw_only_arguments and not var_kwargs_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

1626 

1627 keyword_possible = not p_only_arguments and not var_args_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1628 if keyword_possible: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1630 

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

1632 positional_possible = not kw_only_arguments and not var_kwargs_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1633 if positional_possible: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1635 

1636 raise PydanticInvalidForJsonSchema( 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1638 ) 

1639 

1640 def kw_arguments_schema( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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] = {} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1653 for argument in arguments: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1654 name = self.get_argument_name(argument) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

1657 properties[name] = argument_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1658 

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

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1664 

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

1666 if required: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1667 json_schema['required'] = required 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1668 

1669 if var_kwargs_schema: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1670 additional_properties_schema = self.generate_inner(var_kwargs_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1672 json_schema['additionalProperties'] = additional_properties_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1673 else: 

1674 json_schema['additionalProperties'] = False 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1675 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1676 

1677 def p_arguments_schema( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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] = [] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1689 min_items = 0 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1690 

1691 for argument in arguments: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1692 name = self.get_argument_name(argument) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1693 

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

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

1696 prefix_items.append(argument_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1697 

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

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1703 

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

1705 if min_items: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1706 json_schema['minItems'] = min_items 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1707 

1708 if var_args_schema: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1709 items_schema = self.generate_inner(var_args_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1711 json_schema['items'] = items_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1712 else: 

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

1714 

1715 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1716 

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

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'] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

1729 if isinstance(alias, str): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1730 name = alias 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1731 else: 

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

1733 return name 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1734 

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

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1745 

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

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1756 

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

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() 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1767 content_json_schema = self.generate_inner(content_core_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

1770 else: 

1771 # self.mode == 'serialization' 

1772 return content_json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1773 

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

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} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1785 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1786 

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

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} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1799 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1800 

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

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'} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1811 

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

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']: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1822 try: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1823 self.generate_inner(definition) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1829 

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

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1841 return ref_json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1842 

1843 def ser_schema( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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'] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 true1yCtvadejkpwbEFzAfglmqrBDuxchinos

1856 # PlainSerializerFunctionSerSchema or WrapSerializerFunctionSerSchema 

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

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

1859 return self.generate_inner(return_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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('_', ' ') 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1880 

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

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): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1895 field_schema = schema['return_schema'] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1896 else: 

1897 field_schema = schema['schema'] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1898 return self.field_title_should_be_set(field_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1899 

1900 elif _core_utils.is_core_schema(schema): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1902 return False 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

1905 if _core_utils.is_function_with_inner_schema(schema): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

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

1909 # schemas with refs should not 

1910 return False 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1912 

1913 else: 

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

1915 

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

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('.', '__') 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1926 

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

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1939 # Remove IDs from each component 

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

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

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

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

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

1945 

1946 mode_title = _MODE_TITLE_MAPPING[mode] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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)) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

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

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

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

1957 if occurrence_index is None: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

1960 

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

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

1963 

1964 self._prioritized_defsref_choices[module_qualname_occurrence_mode] = [ 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1974 

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

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) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1987 if maybe_defs_ref is not None: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1988 json_ref = self.core_to_json_refs[core_mode_ref] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

1990 

1991 defs_ref = self.get_defs_ref(core_mode_ref) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1992 

1993 # populate the ref translation mappings 

1994 self.core_to_defs_refs[core_mode_ref] = defs_ref 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1995 self.defs_to_core_refs[defs_ref] = core_mode_ref 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1996 

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

1998 self.core_to_json_refs[core_mode_ref] = json_ref 1yCtvadejkpwbEFzAfglmqrBDuxchinos

1999 self.json_to_defs_refs[json_ref] = defs_ref 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

2001 return defs_ref, ref_json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2002 

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

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: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

2015 json_schema = json_schema.copy() 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2016 

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

2018 if referenced_json_schema is None: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 true1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

2032 continue 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 true1yCtvadejkpwbEFzAfglmqrBDuxchinos

2034 del json_schema[k] # redundant key 

2035 if len(json_schema) > 1: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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']) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2038 del json_schema['$ref'] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

2041 

2042 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2043 

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

2045 def_ref = self.json_to_defs_refs[json_ref] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 true1yCtvadejkpwbEFzAfglmqrBDuxchinos

2047 raise self._core_defs_invalid_for_json_schema[def_ref] 

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

2049 

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

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2062 

2063 config = self._config 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2064 try: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2065 default = ( 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

2072 

2073 return pydantic_core.to_jsonable_python( 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2074 default, 

2075 timedelta_mode=config.ser_json_timedelta, 

2076 bytes_mode=config.ser_json_bytes, 

2077 ) 

2078 

2079 def update_with_validations( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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(): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2091 if core_key in core_schema: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

2093 

2094 class ValidationsMapping: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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 = { 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2102 'multiple_of': 'multipleOf', 

2103 'le': 'maximum', 

2104 'ge': 'minimum', 

2105 'lt': 'exclusiveMaximum', 

2106 'gt': 'exclusiveMinimum', 

2107 } 

2108 bytes = { 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2109 'min_length': 'minLength', 

2110 'max_length': 'maxLength', 

2111 } 

2112 string = { 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2113 'min_length': 'minLength', 

2114 'max_length': 'maxLength', 

2115 'pattern': 'pattern', 

2116 } 

2117 array = { 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2118 'min_length': 'minItems', 

2119 'max_length': 'maxItems', 

2120 } 

2121 object = { 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2122 'min_length': 'minProperties', 

2123 'max_length': 'maxProperties', 

2124 } 

2125 date = { 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2126 'le': 'maximum', 

2127 'ge': 'minimum', 

2128 'lt': 'exclusiveMaximum', 

2129 'gt': 'exclusiveMinimum', 

2130 } 

2131 

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

2133 members = [] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2134 for schema in schemas: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

2137 else: 

2138 members.append(schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2139 members = _deduplicate_schemas(members) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

2141 return members[0] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2142 return {'anyOf': members} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2143 

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

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

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

2147 

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

2149 if isinstance(schema, dict): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2150 if '$ref' in schema: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

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

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

2154 already_visited = json_ref in json_refs 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2155 json_refs[json_ref] += 1 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2156 if already_visited: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

2158 defs_ref = self.json_to_defs_refs[json_ref] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 true1yCtvadejkpwbEFzAfglmqrBDuxchinos

2160 raise self._core_defs_invalid_for_json_schema[defs_ref] 

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

2162 

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

2164 _add_json_refs(v) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2165 elif isinstance(schema, list): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2166 for v in schema: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2167 _add_json_refs(v) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2168 

2169 _add_json_refs(json_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2170 return json_refs 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2171 

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

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

2174 

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

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

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

2178 if message is not None: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2179 warnings.warn(message, PydanticJsonSchemaWarning) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2180 

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

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: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2199 return None 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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

2201 

2202 def _build_definitions_remapping(self) -> _DefinitionsRemapping: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2203 defs_to_json: dict[DefsRef, JsonRef] = {} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2204 for defs_refs in self._prioritized_defsref_choices.values(): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2205 for defs_ref in defs_refs: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2206 json_ref = JsonRef(self.ref_template.format(model=defs_ref)) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2207 defs_to_json[defs_ref] = json_ref 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2208 

2209 return _DefinitionsRemapping.from_prioritized_choices( 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2210 self._prioritized_defsref_choices, defs_to_json, self.definitions 

2211 ) 

2212 

2213 def _garbage_collect_definitions(self, schema: JsonSchemaValue) -> None: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2214 visited_defs_refs: set[DefsRef] = set() 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2215 unvisited_json_refs = _get_all_json_refs(schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2216 while unvisited_json_refs: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2217 next_json_ref = unvisited_json_refs.pop() 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2218 next_defs_ref = self.json_to_defs_refs[next_json_ref] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2219 if next_defs_ref in visited_defs_refs: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2220 continue 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2221 visited_defs_refs.add(next_defs_ref) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2222 unvisited_json_refs.update(_get_all_json_refs(self.definitions[next_defs_ref])) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2223 

2224 self.definitions = {k: v for k, v in self.definitions.items() if k in visited_defs_refs} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2225 

2226 

2227# ##### Start JSON Schema Generation Functions ##### 

2228 

2229 

2230def model_json_schema( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2254 

2255 schema_generator_instance = schema_generator(by_alias=by_alias, ref_template=ref_template) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2256 

2257 if isinstance(cls.__pydantic_core_schema__, _mock_val_ser.MockCoreSchema): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2258 cls.__pydantic_core_schema__.rebuild() 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2259 

2260 if cls is BaseModel: 2260 ↛ 2261line 2260 didn't jump to line 2261, because the condition on line 2260 was never true1yCtvadejkpwbEFzAfglmqrBDuxchinos

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' 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2264 return schema_generator_instance.generate(cls.__pydantic_core_schema__, mode=mode) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2265 

2266 

2267def models_json_schema( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

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 true1yCtvadejkpwbEFzAfglmqrBDuxchinos

2296 cls.__pydantic_core_schema__.rebuild() 

2297 

2298 instance = schema_generator(by_alias=by_alias, ref_template=ref_template) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2299 inputs: list[tuple[type[BaseModel] | type[PydanticDataclass], JsonSchemaMode, CoreSchema]] = [ 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2300 (m, mode, m.__pydantic_core_schema__) for m, mode in models 

2301 ] 

2302 json_schemas_map, definitions = instance.generate_definitions(inputs) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2303 

2304 json_schema: dict[str, Any] = {} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2305 if definitions: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2306 json_schema['$defs'] = definitions 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2307 if title: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2308 json_schema['title'] = title 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2309 if description: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2310 json_schema['description'] = description 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2311 

2312 return json_schemas_map, json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2313 

2314 

2315# ##### End JSON Schema Generation Functions ##### 

2316 

2317 

2318_HashableJsonValue: TypeAlias = Union[ 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2319 int, float, str, bool, None, Tuple['_HashableJsonValue', ...], Tuple[Tuple[str, '_HashableJsonValue'], ...] 

2320] 

2321 

2322 

2323def _deduplicate_schemas(schemas: Iterable[JsonDict]) -> list[JsonDict]: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2324 return list({_make_json_hashable(schema): schema for schema in schemas}.values()) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2325 

2326 

2327def _make_json_hashable(value: JsonValue) -> _HashableJsonValue: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2328 if isinstance(value, dict): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2329 return tuple(sorted((k, _make_json_hashable(v)) for k, v in value.items())) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2330 elif isinstance(value, list): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2331 return tuple(_make_json_hashable(v) for v in value) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2332 else: 

2333 return value 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2334 

2335 

2336def _sort_json_schema(value: JsonSchemaValue, parent_key: str | None = None) -> JsonSchemaValue: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2337 if isinstance(value, dict): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2338 sorted_dict: dict[str, JsonSchemaValue] = {} 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2339 keys = value.keys() 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2340 if (parent_key != 'properties') and (parent_key != 'default'): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2341 keys = sorted(keys) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2342 for key in keys: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2343 sorted_dict[key] = _sort_json_schema(value[key], parent_key=key) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2344 return sorted_dict 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2345 elif isinstance(value, list): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2346 sorted_list: list[JsonSchemaValue] = [] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2347 for item in value: # type: ignore 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2348 sorted_list.append(_sort_json_schema(item, parent_key)) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2349 return sorted_list # type: ignore 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2350 else: 

2351 return value 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2352 

2353 

2354@dataclasses.dataclass(**_internal_dataclass.slots_true) 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2355class WithJsonSchema: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2370 mode: Literal['validation', 'serialization'] | None = None 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2371 

2372 def __get_pydantic_json_schema__( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2373 self, core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler 

2374 ) -> JsonSchemaValue: 

2375 mode = self.mode or handler.mode 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2376 if mode != handler.mode: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2377 return handler(core_schema) 1ytaekBucio

2378 if self.json_schema is None: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2379 # This exception is handled in pydantic.json_schema.GenerateJsonSchema._named_required_fields_schema 

2380 raise PydanticOmit 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2381 else: 

2382 return self.json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2383 

2384 def __hash__(self) -> int: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2385 return hash(type(self.mode)) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2386 

2387 

2388@dataclasses.dataclass(**_internal_dataclass.slots_true) 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2389class Examples: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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] 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2400 mode: Literal['validation', 'serialization'] | None = None 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2401 

2402 def __get_pydantic_json_schema__( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2403 self, core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler 

2404 ) -> JsonSchemaValue: 

2405 mode = self.mode or handler.mode 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2406 json_schema = handler(core_schema) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2407 if mode != handler.mode: 2407 ↛ 2408line 2407 didn't jump to line 2408, because the condition on line 2407 was never true1yCtvadejkpwbEFzAfglmqrBDuxchinos

2408 return json_schema 

2409 examples = json_schema.get('examples', {}) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2410 examples.update(to_jsonable_python(self.examples)) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2411 json_schema['examples'] = examples 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2412 return json_schema 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2413 

2414 def __hash__(self) -> int: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2415 return hash(type(self.mode)) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2416 

2417 

2418def _get_all_json_refs(item: Any) -> set[JsonRef]: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2419 """Get all the definitions references from a JSON schema.""" 

2420 refs: set[JsonRef] = set() 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2421 stack = [item] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2422 

2423 while stack: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2424 current = stack.pop() 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2425 if isinstance(current, dict): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2426 for key, value in current.items(): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2427 if key == '$ref' and isinstance(value, str): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2428 refs.add(JsonRef(value)) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2429 elif isinstance(value, dict): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2430 stack.append(value) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2431 elif isinstance(value, list): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2432 stack.extend(value) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2433 elif isinstance(current, list): 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2434 stack.extend(current) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2435 

2436 return refs 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2437 

2438 

2439AnyType = TypeVar('AnyType') 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2440 

2441if TYPE_CHECKING: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2442 SkipJsonSchema = Annotated[AnyType, ...] 

2443else: 

2444 

2445 @dataclasses.dataclass(**_internal_dataclass.slots_true) 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2446 class SkipJsonSchema: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

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: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2497 return Annotated[item, cls()] 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2498 

2499 def __get_pydantic_json_schema__( 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2500 self, core_schema: CoreSchema, handler: GetJsonSchemaHandler 

2501 ) -> JsonSchemaValue: 

2502 raise PydanticOmit 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2503 

2504 def __hash__(self) -> int: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2505 return hash(type(self)) 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2506 

2507 

2508def _get_typed_dict_cls(schema: core_schema.TypedDictSchema) -> type[Any] | None: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2509 metadata = _core_metadata.CoreMetadataHandler(schema).metadata 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2510 cls = metadata.get('pydantic_typed_dict_cls') 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2511 return cls 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2512 

2513 

2514def _get_typed_dict_config(cls: type[Any] | None) -> ConfigDict: 1yCtvadejkpwbEFzAfglmqrNOGHIJKLMBDuxchinos

2515 if cls is not None: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2516 try: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2517 return _decorators.get_attribute_from_bases(cls, '__pydantic_config__') 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2518 except AttributeError: 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2519 pass 1yCtvadejkpwbEFzAfglmqrBDuxchinos

2520 return {} 1yCtvadejkpwbEFzAfglmqrBDuxchinos