Skip to content

Commit 14c2971

Browse files
authored
Fix bug with UUID validation from json with a wrap validator (#1080)
1 parent 223aa27 commit 14c2971

File tree

5 files changed

+43
-6
lines changed

5 files changed

+43
-6
lines changed

src/input/input_abstract.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use super::datetime::{EitherDate, EitherDateTime, EitherTime, EitherTimedelta};
1414
use super::return_enums::{EitherBytes, EitherInt, EitherString};
1515
use super::{EitherFloat, GenericArguments, GenericIterable, GenericIterator, GenericMapping, ValidationMatch};
1616

17-
#[derive(Debug, Clone, Copy)]
17+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1818
pub enum InputType {
1919
Python,
2020
Json,

src/validators/dataclass.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use ahash::AHashSet;
88
use crate::build_tools::py_schema_err;
99
use crate::build_tools::{is_strict, schema_or_config_same, ExtraBehavior};
1010
use crate::errors::{AsLocItem, ErrorType, ErrorTypeDefaults, ValError, ValLineError, ValResult};
11+
use crate::input::InputType;
1112
use crate::input::{BorrowInput, GenericArguments, Input, ValidationMatch};
1213
use crate::lookup_key::LookupKey;
1314
use crate::tools::SchemaDict;
@@ -535,7 +536,7 @@ impl Validator for DataclassValidator {
535536
} else {
536537
Ok(input.to_object(py))
537538
}
538-
} else if state.strict_or(self.strict) && input.is_python() {
539+
} else if state.strict_or(self.strict) && state.extra().input_type == InputType::Python {
539540
Err(ValError::new(
540541
ErrorType::DataclassExactType {
541542
class_name: self.get_name().to_string(),

src/validators/uuid.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use uuid::Uuid;
99
use crate::build_tools::is_strict;
1010
use crate::errors::{ErrorType, ErrorTypeDefaults, ValError, ValResult};
1111
use crate::input::Input;
12+
use crate::input::InputType;
1213
use crate::tools::SchemaDict;
1314

1415
use super::model::create_class;
@@ -108,7 +109,7 @@ impl Validator for UuidValidator {
108109
}
109110
}
110111
Ok(py_input.to_object(py))
111-
} else if state.strict_or(self.strict) && input.is_python() {
112+
} else if state.strict_or(self.strict) && state.extra().input_type == InputType::Python {
112113
Err(ValError::new(
113114
ErrorType::IsInstanceOf {
114115
class: class.name().unwrap_or("UUID").to_string(),
@@ -118,8 +119,9 @@ impl Validator for UuidValidator {
118119
))
119120
} else {
120121
// In python mode this is a coercion, in JSON mode we treat a UUID string as an
121-
// exact match
122-
if input.is_python() {
122+
// exact match.
123+
// TODO V3: we might want to remove the JSON special case
124+
if state.extra().input_type == InputType::Python {
123125
state.floor_exactness(Exactness::Lax);
124126
}
125127
let uuid = self.get_uuid(input)?;

tests/validators/test_dataclasses.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,6 +1510,27 @@ def test_dataclass_json():
15101510
]
15111511

15121512

1513+
def test_dataclass_wrap_json():
1514+
# https://github.com/pydantic/pydantic/issues/8147
1515+
schema = core_schema.no_info_wrap_validator_function(
1516+
lambda v, handler: handler(v),
1517+
core_schema.dataclass_schema(
1518+
FooDataclass,
1519+
core_schema.dataclass_args_schema(
1520+
'FooDataclass',
1521+
[
1522+
core_schema.dataclass_field(name='a', schema=core_schema.str_schema()),
1523+
core_schema.dataclass_field(name='b', schema=core_schema.bool_schema()),
1524+
],
1525+
),
1526+
['a', 'b'],
1527+
),
1528+
)
1529+
v = SchemaValidator(schema)
1530+
assert v.validate_json('{"a": "hello", "b": true}') == FooDataclass(a='hello', b=True)
1531+
assert v.validate_json('{"a": "hello", "b": true}', strict=True) == FooDataclass(a='hello', b=True)
1532+
1533+
15131534
@pytest.mark.xfail(
15141535
condition=platform.python_implementation() == 'PyPy', reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
15151536
)

tests/validators/test_uuid.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import pytest
66

7-
from pydantic_core import SchemaValidator, ValidationError
7+
from pydantic_core import SchemaValidator, ValidationError, core_schema
88

99
from ..conftest import Err, PyAndJson
1010

@@ -197,3 +197,16 @@ def test_uuid_copy():
197197
assert repr(output) == "UUID('a6cc5730-2261-11ee-9c43-2eb5a363657c')"
198198
assert c == output
199199
assert isinstance(output, UUID)
200+
201+
202+
def test_uuid_wrap_json():
203+
# https://github.com/pydantic/pydantic/issues/8147
204+
schema = core_schema.no_info_wrap_validator_function(lambda v, handler: handler(v), core_schema.uuid_schema())
205+
v = SchemaValidator(schema)
206+
207+
assert v.validate_python(UUID('a6cc5730-2261-11ee-9c43-2eb5a363657c'), strict=True) == UUID(
208+
'a6cc5730-2261-11ee-9c43-2eb5a363657c'
209+
)
210+
assert v.validate_json('"a6cc5730-2261-11ee-9c43-2eb5a363657c"', strict=True) == UUID(
211+
'a6cc5730-2261-11ee-9c43-2eb5a363657c'
212+
)

0 commit comments

Comments
 (0)