@@ -17,8 +17,7 @@ use pyo3::types::{PyBytes, PyComplex, PyFloat, PyFrozenSet, PyIterator, PyMappin
17
17
use serde:: { ser:: Error , Serialize , Serializer } ;
18
18
19
19
use crate :: errors:: {
20
- py_err_string, sequence_valid_as_partial, ErrorType , ErrorTypeDefaults , InputValue , ToErrorValue , ValError ,
21
- ValLineError , ValResult ,
20
+ py_err_string, ErrorType , ErrorTypeDefaults , InputValue , LocItem , ToErrorValue , ValError , ValLineError , ValResult ,
22
21
} ;
23
22
use crate :: py_gc:: PyGcTraverse ;
24
23
use crate :: tools:: { extract_i64, extract_int, new_py_string, py_err} ;
@@ -131,7 +130,6 @@ pub(crate) fn validate_iter_to_vec<'py>(
131
130
let mut errors: Vec < ValLineError > = Vec :: new ( ) ;
132
131
let mut index = 0 ;
133
132
for item_result in iter {
134
- index += 1 ;
135
133
let item = item_result. map_err ( |e| any_next_error ! ( py, e, max_length_check. input, index) ) ?;
136
134
match validator. validate ( py, item. borrow_input ( ) , state) {
137
135
Ok ( item) => {
@@ -148,6 +146,7 @@ pub(crate) fn validate_iter_to_vec<'py>(
148
146
Err ( ValError :: Omit ) => ( ) ,
149
147
Err ( err) => return Err ( err) ,
150
148
}
149
+ index += 1 ;
151
150
}
152
151
153
152
if errors. is_empty ( ) || sequence_valid_as_partial ( state, index, & errors) {
@@ -157,6 +156,23 @@ pub(crate) fn validate_iter_to_vec<'py>(
157
156
}
158
157
}
159
158
159
+ /// If we're in `allow_partial` mode, whether all errors occurred in the last element of the input.
160
+ pub fn sequence_valid_as_partial ( state : & ValidationState , input_length : usize , errors : & [ ValLineError ] ) -> bool {
161
+ if !state. extra ( ) . allow_partial {
162
+ false
163
+ } else {
164
+ // for the error to be in the last element, the index of all errors must be `input_length - 1`
165
+ let last_index = ( input_length - 1 ) as i64 ;
166
+ errors. iter ( ) . all ( |error| {
167
+ if let Some ( LocItem :: I ( loc_index) ) = error. first_loc_item ( ) {
168
+ * loc_index == last_index
169
+ } else {
170
+ false
171
+ }
172
+ } )
173
+ }
174
+ }
175
+
160
176
pub trait BuildSet {
161
177
fn build_add ( & self , item : PyObject ) -> PyResult < ( ) > ;
162
178
@@ -202,7 +218,6 @@ pub(crate) fn validate_iter_to_set<'py>(
202
218
let mut errors: Vec < ValLineError > = Vec :: new ( ) ;
203
219
let mut index = 0 ;
204
220
for item_result in iter {
205
- index += 1 ;
206
221
let item = item_result. map_err ( |e| any_next_error ! ( py, e, input, index) ) ?;
207
222
match validator. validate ( py, item. borrow_input ( ) , state) {
208
223
Ok ( item) => {
@@ -233,6 +248,7 @@ pub(crate) fn validate_iter_to_set<'py>(
233
248
if fail_fast && !errors. is_empty ( ) {
234
249
return Err ( ValError :: LineErrors ( errors) ) ;
235
250
}
251
+ index += 1 ;
236
252
}
237
253
238
254
if errors. is_empty ( ) || sequence_valid_as_partial ( state, index, & errors) {
0 commit comments