Skip to content

Commit b818f74

Browse files
committed
use get_slice to copy lists
1 parent 250cafa commit b818f74

File tree

4 files changed

+51
-39
lines changed

4 files changed

+51
-39
lines changed

src/input/return_enums.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@ use pyo3::types::PyFunction;
1212
use pyo3::PyTypeInfo;
1313

1414
use crate::errors::{py_err_string, ErrorType, InputValue, ValError, ValLineError, ValResult};
15-
use crate::input::py_error_on_minusone;
1615
use crate::recursion_guard::RecursionGuard;
1716
use crate::validators::{CombinedValidator, Extra, Validator};
1817

1918
use super::parse_json::{JsonArray, JsonInput, JsonObject};
20-
use super::Input;
19+
use super::{py_error_on_minusone, Input};
2120

2221
/// Container for all the collections (sized iterable containers) types, which
2322
/// can mostly be converted to each other in lax mode.

src/validators/dict.rs

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::input::{
1010
use crate::recursion_guard::RecursionGuard;
1111

1212
use super::any::AnyValidator;
13+
use super::list::length_check;
1314
use super::{build_validator, BuildValidator, CombinedValidator, Definitions, DefinitionsBuilder, Extra, Validator};
1415

1516
#[derive(Debug, Clone)]
@@ -104,40 +105,6 @@ impl Validator for DictValidator {
104105
}
105106
}
106107

107-
macro_rules! length_check {
108-
($input:ident, $field_type:literal, $min_length:expr, $max_length:expr, $obj:ident) => {{
109-
let mut op_actual_length: Option<usize> = None;
110-
if let Some(min_length) = $min_length {
111-
let actual_length = $obj.len();
112-
if actual_length < min_length {
113-
return Err(crate::errors::ValError::new(
114-
crate::errors::ErrorType::TooShort {
115-
field_type: $field_type.to_string(),
116-
min_length,
117-
actual_length,
118-
},
119-
$input,
120-
));
121-
}
122-
op_actual_length = Some(actual_length);
123-
}
124-
if let Some(max_length) = $max_length {
125-
let actual_length = op_actual_length.unwrap_or_else(|| $obj.len());
126-
if actual_length > max_length {
127-
return Err(crate::errors::ValError::new(
128-
crate::errors::ErrorType::TooLong {
129-
field_type: $field_type.to_string(),
130-
max_length,
131-
actual_length,
132-
},
133-
$input,
134-
));
135-
}
136-
}
137-
}};
138-
}
139-
pub(crate) use length_check;
140-
141108
macro_rules! build_validate {
142109
($name:ident, $dict_type:ty, $iter:ty) => {
143110
fn $name<'s, 'data>(

src/validators/list.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use pyo3::types::PyDict;
33

44
use crate::build_tools::SchemaDict;
55
use crate::errors::ValResult;
6-
use crate::input::Input;
6+
use crate::input::{GenericCollection, Input};
77
use crate::recursion_guard::RecursionGuard;
88

99
use super::{build_validator, BuildValidator, CombinedValidator, Definitions, DefinitionsBuilder, Extra, Validator};
@@ -35,6 +35,40 @@ pub fn get_items_schema(
3535
}
3636
}
3737

38+
macro_rules! length_check {
39+
($input:ident, $field_type:literal, $min_length:expr, $max_length:expr, $obj:ident) => {{
40+
let mut op_actual_length: Option<usize> = None;
41+
if let Some(min_length) = $min_length {
42+
let actual_length = $obj.len();
43+
if actual_length < min_length {
44+
return Err(crate::errors::ValError::new(
45+
crate::errors::ErrorType::TooShort {
46+
field_type: $field_type.to_string(),
47+
min_length,
48+
actual_length,
49+
},
50+
$input,
51+
));
52+
}
53+
op_actual_length = Some(actual_length);
54+
}
55+
if let Some(max_length) = $max_length {
56+
let actual_length = op_actual_length.unwrap_or_else(|| $obj.len());
57+
if actual_length > max_length {
58+
return Err(crate::errors::ValError::new(
59+
crate::errors::ErrorType::TooLong {
60+
field_type: $field_type.to_string(),
61+
max_length,
62+
actual_length,
63+
},
64+
$input,
65+
));
66+
}
67+
}
68+
}};
69+
}
70+
pub(crate) use length_check;
71+
3872
macro_rules! min_length_check {
3973
($input:ident, $field_type:literal, $min_length:expr, $obj:ident) => {{
4074
if let Some(min_length) = $min_length {
@@ -100,7 +134,14 @@ impl Validator for ListValidator {
100134
definitions,
101135
recursion_guard,
102136
)?,
103-
None => seq.to_vec(py, input, "List", self.max_length)?,
137+
None => match seq {
138+
GenericCollection::List(list) => {
139+
length_check!(input, "List", self.min_length, self.max_length, list);
140+
let list_copy = list.get_slice(0, usize::MAX);
141+
return Ok(list_copy.into_py(py));
142+
}
143+
_ => seq.to_vec(py, input, "List", self.max_length)?,
144+
},
104145
};
105146
min_length_check!(input, "List", self.min_length, output);
106147
Ok(output.into_py(py))

tests/validators/test_list.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ def test_list_strict():
4040
]
4141

4242

43+
def test_list_no_copy():
44+
v = SchemaValidator({'type': 'list'})
45+
assert v.validate_python([1, 2, 3]) is not [1, 2, 3]
46+
47+
4348
def gen_ints():
4449
yield 1
4550
yield 2
@@ -148,7 +153,7 @@ def test_list_error(input_value, index):
148153
(
149154
{'max_length': 3},
150155
[1, 2, 3, 4, 5, 6, 7],
151-
Err('List should have at most 3 items after validation, not 4 [type=too_long,'),
156+
Err('List should have at most 3 items after validation, not 7 [type=too_long,'),
152157
),
153158
({'max_length': 1}, [1, 2], Err('List should have at most 1 item after validation, not 2 [type=too_long,')),
154159
(

0 commit comments

Comments
 (0)