@@ -171,6 +171,7 @@ impl GeneralFieldsSerializer {
171171 pub ( crate ) fn main_to_python < ' py > (
172172 & self ,
173173 py : Python < ' py > ,
174+ model : & Bound < ' py , PyAny > ,
174175 main_iter : impl Iterator < Item = PyResult < ( Bound < ' py , PyAny > , Bound < ' py , PyAny > ) > > ,
175176 state : & mut SerializationState < ' _ , ' py > ,
176177 ) -> PyResult < Bound < ' py , PyDict > > {
@@ -218,7 +219,7 @@ impl GeneralFieldsSerializer {
218219 return Err ( PydanticSerializationUnexpectedValue :: new (
219220 Some ( format ! ( "Unexpected field `{key}`" ) ) ,
220221 Some ( key_str. to_string ( ) ) ,
221- state . model_type_name ( ) . map ( |bound| bound . to_string ( ) ) ,
222+ model_type_name ( model ) ,
222223 None ,
223224 )
224225 . to_py_err ( ) ) ;
@@ -244,8 +245,8 @@ impl GeneralFieldsSerializer {
244245 Err ( PydanticSerializationUnexpectedValue :: new (
245246 Some ( format ! ( "Expected {required_fields} fields but got {used_req_fields}" ) . to_string ( ) ) ,
246247 state. field_name . as_ref ( ) . map ( ToString :: to_string) ,
247- state . model_type_name ( ) . map ( |bound| bound . to_string ( ) ) ,
248- state . model . clone ( ) . map ( Bound :: unbind) ,
248+ model_type_name ( model ) ,
249+ Some ( model. clone ( ) . unbind ( ) ) ,
249250 )
250251 . to_py_err ( ) )
251252 } else {
@@ -353,7 +354,6 @@ impl GeneralFieldsSerializer {
353354 state : & mut SerializationState < ' _ , ' py > ,
354355 ) -> PyResult < ( ) > {
355356 if let Some ( ref computed_fields) = self . computed_fields {
356- let state = & mut state. scoped_set ( |s| & mut s. model , Some ( model. clone ( ) ) ) ;
357357 computed_fields. to_python ( model, output_dict, & self . filter , state) ?;
358358 }
359359 Ok ( ( ) )
@@ -366,7 +366,6 @@ impl GeneralFieldsSerializer {
366366 state : & mut SerializationState < ' _ , ' py > ,
367367 ) -> Result < ( ) , S :: Error > {
368368 if let Some ( ref computed_fields) = self . computed_fields {
369- // FIXME: need to match state.model setting above in `add_computed_fields_python`??
370369 computed_fields. serde_serialize :: < S > ( model, map, & self . filter , state) ?;
371370 }
372371 Ok ( ( ) )
@@ -390,21 +389,14 @@ impl TypeSerializer for GeneralFieldsSerializer {
390389 ) -> PyResult < Py < PyAny > > {
391390 let py = value. py ( ) ;
392391 let missing_sentinel = get_missing_sentinel_object ( py) ;
393- // If there is already a model registered (from a dataclass, BaseModel)
394- // then do not touch it
395- // If there is no model, we (a TypedDict) are the model
396- let model = state. model . clone ( ) . unwrap_or_else ( || value. clone ( ) ) ;
392+
393+ let model = get_model ( state) ?;
397394
398395 let Some ( ( main_dict, extra_dict) ) = self . extract_dicts ( value) else {
399396 state. warn_fallback_py ( self . get_name ( ) , value) ?;
400397 return infer_to_python ( value, state) ;
401398 } ;
402- let output_dict = self . main_to_python (
403- py,
404- dict_items ( & main_dict) ,
405- // FIXME: should also set model for extra serialization?
406- & mut state. scoped_set ( |s| & mut s. model , Some ( model. clone ( ) ) ) ,
407- ) ?;
399+ let output_dict = self . main_to_python ( py, & model, dict_items ( & main_dict) , state) ?;
408400
409401 // this is used to include `__pydantic_extra__` in serialization on models
410402 if let Some ( extra_dict) = extra_dict {
@@ -448,24 +440,15 @@ impl TypeSerializer for GeneralFieldsSerializer {
448440 return infer_serialize ( value, serializer, state) ;
449441 } ;
450442 let missing_sentinel = get_missing_sentinel_object ( value. py ( ) ) ;
451- // If there is already a model registered (from a dataclass, BaseModel)
452- // then do not touch it
453- // If there is no model, we (a TypedDict) are the model
454- let model = state. model . clone ( ) . unwrap_or_else ( || value. clone ( ) ) ;
443+ let model = get_model ( state) . map_err ( py_err_se_err) ?;
455444
456445 let expected_len = match self . mode {
457446 FieldsMode :: TypedDictAllow => main_dict. len ( ) + self . computed_field_count ( ) ,
458447 _ => self . fields . len ( ) + option_length ! ( extra_dict) + self . computed_field_count ( ) ,
459448 } ;
460449 // NOTE! As above, we maintain the order of the input dict assuming that's right
461450 // we don't both with `used_req_fields` here because on unions, `to_python(..., mode='json')` is used
462- let mut map = self . main_serde_serialize (
463- dict_items ( & main_dict) ,
464- expected_len,
465- serializer,
466- // FIXME: should also set model for extra serialization?
467- & mut state. scoped_set ( |s| & mut s. model , Some ( model. clone ( ) ) ) ,
468- ) ?;
451+ let mut map = self . main_serde_serialize ( dict_items ( & main_dict) , expected_len, serializer, state) ?;
469452
470453 // this is used to include `__pydantic_extra__` in serialization on models
471454 if let Some ( extra_dict) = extra_dict {
@@ -507,3 +490,19 @@ fn dict_items<'py>(
507490 let main_items: SmallVec < [ _ ; 16 ] > = main_dict. iter ( ) . collect ( ) ;
508491 main_items. into_iter ( ) . map ( Ok )
509492}
493+
494+ fn get_model < ' py > ( state : & mut SerializationState < ' _ , ' py > ) -> PyResult < Bound < ' py , PyAny > > {
495+ state. model . clone ( ) . ok_or_else ( || {
496+ PydanticSerializationUnexpectedValue :: new (
497+ Some ( "No model found for fields serialization" . to_string ( ) ) ,
498+ None ,
499+ None ,
500+ None ,
501+ )
502+ . to_py_err ( )
503+ } )
504+ }
505+
506+ fn model_type_name ( model : & Bound < ' _ , PyAny > ) -> Option < String > {
507+ model. get_type ( ) . name ( ) . ok ( ) . map ( |s| s. to_string ( ) )
508+ }
0 commit comments