1
1
use pyo3:: intern;
2
2
use pyo3:: prelude:: * ;
3
3
use pyo3:: types:: { PyDict , PyList , PyTuple } ;
4
+ use smallvec:: SmallVec ;
4
5
use std:: borrow:: Cow ;
5
6
6
7
use crate :: build_tools:: py_schema_err;
7
8
use crate :: definitions:: DefinitionsBuilder ;
8
- use crate :: tools:: SchemaDict ;
9
+ use crate :: tools:: { SchemaDict , UNION_ERR_SMALLVEC_CAPACITY } ;
9
10
use crate :: PydanticSerializationUnexpectedValue ;
10
11
11
12
use super :: {
12
- infer_json_key, infer_serialize, infer_to_python, py_err_se_err , BuildSerializer , CombinedSerializer , Extra ,
13
- SerCheck , TypeSerializer ,
13
+ infer_json_key, infer_serialize, infer_to_python, BuildSerializer , CombinedSerializer , Extra , SerCheck ,
14
+ TypeSerializer ,
14
15
} ;
15
16
16
17
#[ derive( Debug , Clone ) ]
@@ -78,13 +79,14 @@ impl TypeSerializer for UnionSerializer {
78
79
// try the serializers in left to right order with error_on fallback=true
79
80
let mut new_extra = extra. clone ( ) ;
80
81
new_extra. check = SerCheck :: Strict ;
82
+ let mut errors: SmallVec < [ PyErr ; UNION_ERR_SMALLVEC_CAPACITY ] > = SmallVec :: new ( ) ;
81
83
82
84
for comb_serializer in & self . choices {
83
85
match comb_serializer. to_python ( value, include, exclude, & new_extra) {
84
86
Ok ( v) => return Ok ( v) ,
85
87
Err ( err) => match err. is_instance_of :: < PydanticSerializationUnexpectedValue > ( value. py ( ) ) {
86
88
true => ( ) ,
87
- false => return Err ( err) ,
89
+ false => errors . push ( err) ,
88
90
} ,
89
91
}
90
92
}
@@ -95,25 +97,31 @@ impl TypeSerializer for UnionSerializer {
95
97
Ok ( v) => return Ok ( v) ,
96
98
Err ( err) => match err. is_instance_of :: < PydanticSerializationUnexpectedValue > ( value. py ( ) ) {
97
99
true => ( ) ,
98
- false => return Err ( err) ,
100
+ false => errors . push ( err) ,
99
101
} ,
100
102
}
101
103
}
102
104
}
103
105
106
+ for err in & errors {
107
+ extra. warnings . custom_warning ( err. to_string ( ) ) ;
108
+ }
109
+
104
110
extra. warnings . on_fallback_py ( self . get_name ( ) , value, extra) ?;
105
111
infer_to_python ( value, include, exclude, extra)
106
112
}
107
113
108
114
fn json_key < ' a > ( & self , key : & ' a Bound < ' _ , PyAny > , extra : & Extra ) -> PyResult < Cow < ' a , str > > {
109
115
let mut new_extra = extra. clone ( ) ;
110
116
new_extra. check = SerCheck :: Strict ;
117
+ let mut errors: SmallVec < [ PyErr ; UNION_ERR_SMALLVEC_CAPACITY ] > = SmallVec :: new ( ) ;
118
+
111
119
for comb_serializer in & self . choices {
112
120
match comb_serializer. json_key ( key, & new_extra) {
113
121
Ok ( v) => return Ok ( v) ,
114
122
Err ( err) => match err. is_instance_of :: < PydanticSerializationUnexpectedValue > ( key. py ( ) ) {
115
123
true => ( ) ,
116
- false => return Err ( err) ,
124
+ false => errors . push ( err) ,
117
125
} ,
118
126
}
119
127
}
@@ -124,12 +132,16 @@ impl TypeSerializer for UnionSerializer {
124
132
Ok ( v) => return Ok ( v) ,
125
133
Err ( err) => match err. is_instance_of :: < PydanticSerializationUnexpectedValue > ( key. py ( ) ) {
126
134
true => ( ) ,
127
- false => return Err ( err) ,
135
+ false => errors . push ( err) ,
128
136
} ,
129
137
}
130
138
}
131
139
}
132
140
141
+ for err in & errors {
142
+ extra. warnings . custom_warning ( err. to_string ( ) ) ;
143
+ }
144
+
133
145
extra. warnings . on_fallback_py ( self . get_name ( ) , key, extra) ?;
134
146
infer_json_key ( key, extra)
135
147
}
@@ -145,12 +157,14 @@ impl TypeSerializer for UnionSerializer {
145
157
let py = value. py ( ) ;
146
158
let mut new_extra = extra. clone ( ) ;
147
159
new_extra. check = SerCheck :: Strict ;
160
+ let mut errors: SmallVec < [ PyErr ; UNION_ERR_SMALLVEC_CAPACITY ] > = SmallVec :: new ( ) ;
161
+
148
162
for comb_serializer in & self . choices {
149
163
match comb_serializer. to_python ( value, include, exclude, & new_extra) {
150
164
Ok ( v) => return infer_serialize ( v. bind ( py) , serializer, None , None , extra) ,
151
- Err ( err) => match err. is_instance_of :: < PydanticSerializationUnexpectedValue > ( py ) {
165
+ Err ( err) => match err. is_instance_of :: < PydanticSerializationUnexpectedValue > ( value . py ( ) ) {
152
166
true => ( ) ,
153
- false => return Err ( py_err_se_err ( err) ) ,
167
+ false => errors . push ( err) ,
154
168
} ,
155
169
}
156
170
}
@@ -159,14 +173,18 @@ impl TypeSerializer for UnionSerializer {
159
173
for comb_serializer in & self . choices {
160
174
match comb_serializer. to_python ( value, include, exclude, & new_extra) {
161
175
Ok ( v) => return infer_serialize ( v. bind ( py) , serializer, None , None , extra) ,
162
- Err ( err) => match err. is_instance_of :: < PydanticSerializationUnexpectedValue > ( py ) {
176
+ Err ( err) => match err. is_instance_of :: < PydanticSerializationUnexpectedValue > ( value . py ( ) ) {
163
177
true => ( ) ,
164
- false => return Err ( py_err_se_err ( err) ) ,
178
+ false => errors . push ( err) ,
165
179
} ,
166
180
}
167
181
}
168
182
}
169
183
184
+ for err in & errors {
185
+ extra. warnings . custom_warning ( err. to_string ( ) ) ;
186
+ }
187
+
170
188
extra. warnings . on_fallback_ser :: < S > ( self . get_name ( ) , value, extra) ?;
171
189
infer_serialize ( value, serializer, include, exclude, extra)
172
190
}
0 commit comments