Skip to content

Commit 75daffc

Browse files
ligsamuelcolvin
andauthored
🐛 Fix max_length for unicode strings (#758)
Co-authored-by: Samuel Colvin <[email protected]>
1 parent 1a17d42 commit 75daffc

File tree

2 files changed

+32
-10
lines changed

2 files changed

+32
-10
lines changed

src/validators/string.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,23 @@ impl Validator for StrConstrainedValidator {
9393
if self.strip_whitespace {
9494
str = str.trim();
9595
}
96+
97+
let str_len: Option<usize> = if self.min_length.is_some() | self.max_length.is_some() {
98+
Some(str.chars().count())
99+
} else {
100+
None
101+
};
96102
if let Some(min_length) = self.min_length {
97-
if str.len() < min_length {
98-
// return py_schema_err!("{} is shorter than {}", str, min_length);
103+
if str_len.unwrap() < min_length {
99104
return Err(ValError::new(ErrorType::StringTooShort { min_length }, input));
100105
}
101106
}
102107
if let Some(max_length) = self.max_length {
103-
if str.len() > max_length {
108+
if str_len.unwrap() > max_length {
104109
return Err(ValError::new(ErrorType::StringTooLong { max_length }, input));
105110
}
106111
}
112+
107113
if let Some(pattern) = &self.pattern {
108114
if !pattern.is_match(str) {
109115
return Err(ValError::new(

tests/validators/test_string.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import re
22
from decimal import Decimal
3-
from typing import Any, Dict
3+
from typing import Any, Dict, Union
44

55
import pytest
66

@@ -134,12 +134,28 @@ def test_unicode_error():
134134
]
135135

136136

137-
def test_str_constrained():
138-
v = SchemaValidator({'type': 'str', 'max_length': 5})
139-
assert v.validate_python('test') == 'test'
140-
141-
with pytest.raises(ValidationError, match='String should have at most 5 characters'):
142-
v.validate_python('test long')
137+
@pytest.mark.parametrize(
138+
('data', 'max_length', 'error'),
139+
[
140+
pytest.param('test', 5, None, id='short string'),
141+
pytest.param('test long', 5, 'String should have at most 5 characters', id='long string'),
142+
pytest.param('␛⯋℃▤', 5, None, id='short string with unicode characters'),
143+
pytest.param(
144+
'␛⯋℃▤⩥⠫⳼⣪⨺✒⧐♳⩚⏭⏣⍥┙⧃Ⰴ┽⏏♜',
145+
5,
146+
'String should have at most 5 characters',
147+
id='long string with unicode characters',
148+
),
149+
pytest.param('а' * 25, 32, None, id='a lot of `а`s'),
150+
],
151+
)
152+
def test_str_constrained(data: str, max_length: int, error: Union[re.Pattern, None]):
153+
v = SchemaValidator({'type': 'str', 'max_length': max_length})
154+
if error is None:
155+
assert v.validate_python(data) == data
156+
else:
157+
with pytest.raises(ValidationError, match=error):
158+
v.validate_python(data)
143159

144160

145161
def test_str_constrained_config():

0 commit comments

Comments
 (0)