11use std:: borrow:: Cow ;
2- use std:: str:: from_utf8;
32
43use pyo3:: exceptions:: PyTypeError ;
54use pyo3:: intern;
65use pyo3:: prelude:: * ;
76use pyo3:: types:: {
8- PyByteArray , PyBytes , PyDate , PyDateTime , PyDelta , PyDict , PyFrozenSet , PyList , PySet , PyString , PyTime , PyTuple ,
7+ PyByteArray , PyBytes , PyDate , PyDateTime , PyDelta , PyDict , PyFrozenSet , PyIterator , PyList , PySet , PyString ,
8+ PyTime , PyTuple ,
99} ;
1010
1111use serde:: ser:: { Serialize , SerializeMap , SerializeSeq , Serializer } ;
1212
1313use crate :: build_tools:: { py_err, safe_repr} ;
14+ use crate :: serializers:: filter:: SchemaFilter ;
1415use crate :: url:: { PyMultiHostUrl , PyUrl } ;
1516
16- use super :: config:: utf8_py_error;
1717use super :: errors:: { py_err_se_err, PydanticSerializationError } ;
1818use super :: extra:: { Extra , SerMode } ;
1919use super :: filter:: AnyFilter ;
@@ -97,21 +97,23 @@ pub(crate) fn infer_to_python_known(
9797 // have to do this to make sure subclasses of for example str are upcast to `str`
9898 ObType :: IntSubclass => value. extract :: < i64 > ( ) ?. into_py ( py) ,
9999 ObType :: FloatSubclass => value. extract :: < f64 > ( ) ?. into_py ( py) ,
100+ ObType :: Decimal => value. to_string ( ) . into_py ( py) ,
100101 ObType :: StrSubclass => value. extract :: < & str > ( ) ?. into_py ( py) ,
101102 ObType :: Bytes => extra
102103 . config
103104 . bytes_mode
104- . bytes_to_string ( value. downcast ( ) ?)
105+ . bytes_to_string ( py , value. downcast :: < PyBytes > ( ) ?. as_bytes ( ) )
105106 . map ( |s| s. into_py ( py) ) ?,
106107 ObType :: Bytearray => {
107108 let py_byte_array: & PyByteArray = value. downcast ( ) ?;
108109 // see https://docs.rs/pyo3/latest/pyo3/types/struct.PyByteArray.html#method.as_bytes
109110 // for why this is marked unsafe
110111 let bytes = unsafe { py_byte_array. as_bytes ( ) } ;
111- match from_utf8 ( bytes) {
112- Ok ( s) => s. into_py ( py) ,
113- Err ( err) => return Err ( utf8_py_error ( py, err, bytes) ) ,
114- }
112+ extra
113+ . config
114+ . bytes_mode
115+ . bytes_to_string ( py, bytes)
116+ . map ( |s| s. into_py ( py) ) ?
115117 }
116118 ObType :: Tuple => {
117119 let elements = serialize_seq_filter ! ( PyTuple ) ;
@@ -163,6 +165,20 @@ pub(crate) fn infer_to_python_known(
163165 let v = value. getattr ( intern ! ( py, "value" ) ) ?;
164166 infer_to_python ( v, include, exclude, extra) ?. into_py ( py)
165167 }
168+ ObType :: Generator => {
169+ let py_seq: & PyIterator = value. downcast ( ) ?;
170+ let mut items = Vec :: new ( ) ;
171+ let filter = AnyFilter :: new ( ) ;
172+
173+ for ( index, r) in py_seq. iter ( ) ?. enumerate ( ) {
174+ let element = r?;
175+ let op_next = filter. value_filter ( index, include, exclude) ?;
176+ if let Some ( ( next_include, next_exclude) ) = op_next {
177+ items. push ( infer_to_python ( element, next_include, next_exclude, extra) ?) ;
178+ }
179+ }
180+ PyList :: new ( py, items) . into_py ( py)
181+ }
166182 ObType :: Unknown => return Err ( unknown_type_error ( value) ) ,
167183 } ,
168184 _ => match ob_type {
@@ -199,6 +215,17 @@ pub(crate) fn infer_to_python_known(
199215 }
200216 ObType :: Dataclass => serialize_dict ( object_to_dict ( value, false , extra) ?) ?,
201217 ObType :: PydanticModel => serialize_dict ( object_to_dict ( value, true , extra) ?) ?,
218+ ObType :: Generator => {
219+ let iter = super :: type_serializers:: generator:: SerializationIterator :: new (
220+ value. downcast ( ) ?,
221+ super :: type_serializers:: any:: AnySerializer :: default ( ) . into ( ) ,
222+ SchemaFilter :: default ( ) ,
223+ include,
224+ exclude,
225+ extra,
226+ ) ;
227+ iter. into_py ( py)
228+ }
202229 _ => value. into_py ( py) ,
203230 } ,
204231 } ;
@@ -321,21 +348,19 @@ pub(crate) fn infer_serialize_known<S: Serializer>(
321348 ObType :: Int | ObType :: IntSubclass => serialize ! ( i64 ) ,
322349 ObType :: Bool => serialize ! ( bool ) ,
323350 ObType :: Float | ObType :: FloatSubclass => serialize ! ( f64 ) ,
351+ ObType :: Decimal => value. to_string ( ) . serialize ( serializer) ,
324352 ObType :: Str | ObType :: StrSubclass => {
325353 let py_str: & PyString = value. downcast ( ) . map_err ( py_err_se_err) ?;
326354 super :: type_serializers:: string:: serialize_py_str ( py_str, serializer)
327355 }
328356 ObType :: Bytes => {
329357 let py_bytes: & PyBytes = value. downcast ( ) . map_err ( py_err_se_err) ?;
330- extra. config . bytes_mode . serialize_bytes ( py_bytes, serializer)
358+ extra. config . bytes_mode . serialize_bytes ( py_bytes. as_bytes ( ) , serializer)
331359 }
332360 ObType :: Bytearray => {
333361 let py_byte_array: & PyByteArray = value. downcast ( ) . map_err ( py_err_se_err) ?;
334362 let bytes = unsafe { py_byte_array. as_bytes ( ) } ;
335- match from_utf8 ( bytes) {
336- Ok ( s) => serializer. serialize_str ( s) ,
337- Err ( e) => Err ( py_err_se_err ( e) ) ,
338- }
363+ extra. config . bytes_mode . serialize_bytes ( bytes, serializer)
339364 }
340365 ObType :: Dict => serialize_dict ! ( value. downcast:: <PyDict >( ) . map_err( py_err_se_err) ?) ,
341366 ObType :: List => serialize_seq_filter ! ( PyList ) ,
@@ -378,6 +403,20 @@ pub(crate) fn infer_serialize_known<S: Serializer>(
378403 let v = value. getattr ( intern ! ( value. py( ) , "value" ) ) . map_err ( py_err_se_err) ?;
379404 infer_serialize ( v, serializer, include, exclude, extra)
380405 }
406+ ObType :: Generator => {
407+ let py_seq: & PyIterator = value. downcast ( ) . map_err ( py_err_se_err) ?;
408+ let mut seq = serializer. serialize_seq ( None ) ?;
409+ let filter = AnyFilter :: new ( ) ;
410+ for ( index, r) in py_seq. iter ( ) . map_err ( py_err_se_err) ?. enumerate ( ) {
411+ let element = r. map_err ( py_err_se_err) ?;
412+ let op_next = filter. value_filter ( index, include, exclude) . map_err ( py_err_se_err) ?;
413+ if let Some ( ( next_include, next_exclude) ) = op_next {
414+ let item_serializer = SerializeInfer :: new ( element, next_include, next_exclude, extra) ;
415+ seq. serialize_element ( & item_serializer) ?
416+ }
417+ }
418+ seq. end ( )
419+ }
381420 ObType :: Unknown => return Err ( py_err_se_err ( unknown_type_error ( value) ) ) ,
382421 } ;
383422 extra. rec_guard . pop ( value_id) ;
@@ -399,19 +438,20 @@ pub(crate) fn infer_json_key_known<'py>(ob_type: &ObType, key: &'py PyAny, extra
399438 ObType :: Int | ObType :: IntSubclass | ObType :: Float | ObType :: FloatSubclass => {
400439 super :: type_serializers:: simple:: to_str_json_key ( key)
401440 }
441+ ObType :: Decimal => Ok ( Cow :: Owned ( key. to_string ( ) ) ) ,
402442 ObType :: Bool => super :: type_serializers:: simple:: bool_json_key ( key) ,
403443 ObType :: Str | ObType :: StrSubclass => {
404444 let py_str: & PyString = key. downcast ( ) ?;
405445 Ok ( Cow :: Borrowed ( py_str. to_str ( ) ?) )
406446 }
407- ObType :: Bytes => extra. config . bytes_mode . bytes_to_string ( key. downcast ( ) ?) ,
447+ ObType :: Bytes => extra
448+ . config
449+ . bytes_mode
450+ . bytes_to_string ( key. py ( ) , key. downcast :: < PyBytes > ( ) ?. as_bytes ( ) ) ,
408451 ObType :: Bytearray => {
409452 let py_byte_array: & PyByteArray = key. downcast ( ) ?;
410453 let bytes = unsafe { py_byte_array. as_bytes ( ) } ;
411- match from_utf8 ( bytes) {
412- Ok ( s) => Ok ( Cow :: Borrowed ( s) ) ,
413- Err ( err) => Err ( utf8_py_error ( key. py ( ) , err, bytes) ) ,
414- }
454+ extra. config . bytes_mode . bytes_to_string ( key. py ( ) , bytes)
415455 }
416456 ObType :: Datetime => {
417457 let py_dt: & PyDateTime = key. downcast ( ) ?;
@@ -447,7 +487,7 @@ pub(crate) fn infer_json_key_known<'py>(ob_type: &ObType, key: &'py PyAny, extra
447487 }
448488 Ok ( Cow :: Owned ( key_build. finish ( ) ) )
449489 }
450- ObType :: List | ObType :: Set | ObType :: Frozenset | ObType :: Dict => {
490+ ObType :: List | ObType :: Set | ObType :: Frozenset | ObType :: Dict | ObType :: Generator => {
451491 py_err ! ( PyTypeError ; "`{}` not valid as object key" , ob_type)
452492 }
453493 ObType :: Dataclass | ObType :: PydanticModel => {
0 commit comments