Skip to content

Commit 424a2f8

Browse files
authored
Allow proper subclasses of strings (#706)
1 parent 29de2c9 commit 424a2f8

File tree

4 files changed

+20
-22
lines changed

4 files changed

+20
-22
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pydantic-core"
3-
version = "0.41.0"
3+
version = "0.42.0"
44
edition = "2021"
55
license = "MIT"
66
homepage = "https://github.com/pydantic/pydantic-core"

src/input/input_python.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,15 +186,21 @@ impl<'a> Input<'a> for PyAny {
186186
}
187187

188188
fn strict_str(&'a self) -> ValResult<EitherString<'a>> {
189-
if let Ok(py_str) = <PyString as PyTryFrom>::try_from_exact(self) {
189+
if let Ok(py_str) = <PyString as PyTryFrom>::try_from(self) {
190190
Ok(py_str.into())
191-
} else if PyString::is_type_of(self) {
192-
Err(ValError::new(ErrorType::StringSubType, self))
193191
} else {
194192
Err(ValError::new(ErrorType::StringType, self))
195193
}
196194
}
197195

196+
fn exact_str(&'a self) -> ValResult<EitherString<'a>> {
197+
if let Ok(py_str) = <PyString as PyTryFrom>::try_from_exact(self) {
198+
Ok(EitherString::Py(py_str))
199+
} else {
200+
Err(ValError::new(ErrorType::IntType, self))
201+
}
202+
}
203+
198204
fn exact_int(&'a self) -> ValResult<EitherInt<'a>> {
199205
if PyInt::is_exact_type_of(self) {
200206
Ok(EitherInt::Py(self))

tests/validators/test_string.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -199,23 +199,15 @@ class FruitEnum(str, Enum):
199199
return FruitEnum
200200

201201

202-
@pytest.mark.parametrize('kwargs', [{}, {'to_lower': True}], ids=repr)
203-
def test_strict_subclass(FruitEnum, kwargs):
204-
v = SchemaValidator(core_schema.str_schema(strict=True, **kwargs))
205-
assert v.validate_python('foobar') == 'foobar'
206-
with pytest.raises(ValidationError, match='type=string_type,'):
207-
v.validate_python(b'foobar')
208-
with pytest.raises(ValidationError, match='type=string_sub_type,') as exc_info:
209-
v.validate_python(FruitEnum.pear)
210-
# insert_assert(exc_info.value.errors(include_url=False))
211-
assert exc_info.value.errors(include_url=False) == [
212-
{
213-
'type': 'string_sub_type',
214-
'loc': (),
215-
'msg': 'Input should be a string, not an instance of a subclass of str',
216-
'input': FruitEnum.pear,
217-
}
218-
]
202+
@pytest.mark.parametrize('to_lower', [False, True], ids=repr)
203+
def test_strict_subclass(to_lower: bool):
204+
v = SchemaValidator(core_schema.str_schema(strict=True, to_lower=to_lower))
205+
206+
class StrSubclass(str):
207+
pass
208+
209+
res = v.validate_python(StrSubclass('ABC'))
210+
assert res == 'abc' if to_lower else 'ABC'
219211

220212

221213
@pytest.mark.parametrize('kwargs', [{}, {'to_lower': True}], ids=repr)

0 commit comments

Comments
 (0)