35
35
)
36
36
37
37
import pydantic_core
38
- from pydantic_core import CoreConfig , CoreSchema , PydanticOmit , core_schema , to_jsonable_python
38
+ from pydantic_core import CoreSchema , PydanticOmit , core_schema , to_jsonable_python
39
39
from pydantic_core .core_schema import ComputedField
40
40
from typing_extensions import Annotated , Literal , assert_never
41
41
42
- from pydantic ._internal import _annotated_handlers , _internal_dataclass
43
-
44
- from ._internal import _core_metadata , _core_utils , _mock_val_ser , _schema_generation_shared , _typing_extra
42
+ from ._internal import (
43
+ _annotated_handlers ,
44
+ _config ,
45
+ _core_metadata ,
46
+ _core_utils ,
47
+ _decorators ,
48
+ _internal_dataclass ,
49
+ _mock_val_ser ,
50
+ _schema_generation_shared ,
51
+ _typing_extra ,
52
+ )
45
53
from .config import JsonSchemaExtraCallable
46
54
from .errors import PydanticInvalidForJsonSchema , PydanticUserError
47
55
@@ -266,6 +274,7 @@ def __init__(self, by_alias: bool = True, ref_template: str = DEFAULT_REF_TEMPLA
266
274
self .json_to_defs_refs : dict [JsonRef , DefsRef ] = {}
267
275
268
276
self .definitions : dict [DefsRef , JsonSchemaValue ] = {}
277
+ self ._config_wrapper_stack = _config .ConfigWrapperStack (_config .ConfigWrapper ({}))
269
278
270
279
self .mode : JsonSchemaMode = 'validation'
271
280
@@ -291,6 +300,10 @@ def __init__(self, by_alias: bool = True, ref_template: str = DEFAULT_REF_TEMPLA
291
300
# of a single instance of a schema generator
292
301
self ._used = False
293
302
303
+ @property
304
+ def _config (self ) -> _config .ConfigWrapper :
305
+ return self ._config_wrapper_stack .tail
306
+
294
307
def build_schema_type_to_method (
295
308
self ,
296
309
) -> dict [CoreSchemaOrFieldType , Callable [[CoreSchemaOrField ], JsonSchemaValue ]]:
@@ -649,7 +662,7 @@ def bytes_schema(self, schema: core_schema.BytesSchema) -> JsonSchemaValue:
649
662
Returns:
650
663
The generated JSON schema.
651
664
"""
652
- json_schema = {'type' : 'string' , 'format' : 'binary' }
665
+ json_schema = {'type' : 'string' , 'format' : 'base64url' if self . _config . ser_json_bytes == 'base64' else ' binary' }
653
666
self .update_with_validations (json_schema , schema , self .ValidationsMapping .bytes )
654
667
return json_schema
655
668
@@ -697,6 +710,8 @@ def timedelta_schema(self, schema: core_schema.TimedeltaSchema) -> JsonSchemaVal
697
710
Returns:
698
711
The generated JSON schema.
699
712
"""
713
+ if self ._config .ser_json_timedelta == 'float' :
714
+ return {'type' : 'number' }
700
715
return {'type' : 'string' , 'format' : 'duration' }
701
716
702
717
def literal_schema (self , schema : core_schema .LiteralSchema ) -> JsonSchemaValue :
@@ -1168,10 +1183,12 @@ def typed_dict_schema(self, schema: core_schema.TypedDictSchema) -> JsonSchemaVa
1168
1183
]
1169
1184
if self .mode == 'serialization' :
1170
1185
named_required_fields .extend (self ._name_required_computed_fields (schema .get ('computed_fields' , [])))
1171
- json_schema = self ._named_required_fields_schema (named_required_fields )
1172
- config : CoreConfig | None = schema .get ('config' , None )
1173
1186
1174
- extra = (config or {}).get ('extra_fields_behavior' , 'ignore' )
1187
+ config = _get_typed_dict_config (schema )
1188
+ with self ._config_wrapper_stack .push (config ):
1189
+ json_schema = self ._named_required_fields_schema (named_required_fields )
1190
+
1191
+ extra = config .get ('extra' , 'ignore' )
1175
1192
if extra == 'forbid' :
1176
1193
json_schema ['additionalProperties' ] = False
1177
1194
elif extra == 'allow' :
@@ -1286,12 +1303,13 @@ def model_schema(self, schema: core_schema.ModelSchema) -> JsonSchemaValue:
1286
1303
"""
1287
1304
# We do not use schema['model'].model_json_schema() here
1288
1305
# because it could lead to inconsistent refs handling, etc.
1289
- json_schema = self .generate_inner (schema ['schema' ])
1290
-
1291
1306
cls = cast ('type[BaseModel]' , schema ['cls' ])
1292
1307
config = cls .model_config
1293
1308
title = config .get ('title' )
1294
1309
1310
+ with self ._config_wrapper_stack .push (config ):
1311
+ json_schema = self .generate_inner (schema ['schema' ])
1312
+
1295
1313
json_schema_extra = config .get ('json_schema_extra' )
1296
1314
if cls .__pydantic_root_model__ :
1297
1315
root_json_schema_extra = cls .model_fields ['root' ].json_schema_extra
@@ -1461,13 +1479,13 @@ def dataclass_schema(self, schema: core_schema.DataclassSchema) -> JsonSchemaVal
1461
1479
Returns:
1462
1480
The generated JSON schema.
1463
1481
"""
1464
- json_schema = self .generate_inner (schema ['schema' ]).copy ()
1465
-
1466
1482
cls = schema ['cls' ]
1467
1483
config : ConfigDict = getattr (cls , '__pydantic_config__' , cast ('ConfigDict' , {}))
1468
-
1469
1484
title = config .get ('title' ) or cls .__name__
1470
1485
1486
+ with self ._config_wrapper_stack .push (config ):
1487
+ json_schema = self .generate_inner (schema ['schema' ]).copy ()
1488
+
1471
1489
json_schema_extra = config .get ('json_schema_extra' )
1472
1490
json_schema = self ._update_class_schema (json_schema , title , config .get ('extra' , None ), cls , json_schema_extra )
1473
1491
@@ -1942,7 +1960,12 @@ def encode_default(self, dft: Any) -> Any:
1942
1960
Returns:
1943
1961
The encoded default value.
1944
1962
"""
1945
- return pydantic_core .to_jsonable_python (dft )
1963
+ config = self ._config
1964
+ return pydantic_core .to_jsonable_python (
1965
+ dft ,
1966
+ timedelta_mode = config .ser_json_timedelta ,
1967
+ bytes_mode = config .ser_json_bytes ,
1968
+ )
1946
1969
1947
1970
def update_with_validations (
1948
1971
self , json_schema : JsonSchemaValue , core_schema : CoreSchema , mapping : dict [str , str ]
@@ -2321,3 +2344,14 @@ def __get_pydantic_json_schema__(
2321
2344
2322
2345
def __hash__ (self ) -> int :
2323
2346
return hash (type (self ))
2347
+
2348
+
2349
+ def _get_typed_dict_config (schema : core_schema .TypedDictSchema ) -> ConfigDict :
2350
+ metadata = _core_metadata .CoreMetadataHandler (schema ).metadata
2351
+ cls = metadata .get ('pydantic_typed_dict_cls' )
2352
+ if cls is not None :
2353
+ try :
2354
+ return _decorators .get_attribute_from_bases (cls , '__pydantic_config__' )
2355
+ except AttributeError :
2356
+ pass
2357
+ return {}
0 commit comments