Skip to content

Commit

Permalink
uuid test - broken
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Aug 21, 2023
1 parent 63cee1d commit 91da3b7
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 7 deletions.
14 changes: 12 additions & 2 deletions src/input/input_json.rs
Expand Up @@ -83,13 +83,23 @@ impl<'a> Input<'a> for JsonInput {
}
}

fn validate_str(&'a self, _strict: bool) -> ValResult<ValidationMatch<EitherString<'a>>> {
fn exact_str(&'a self) -> ValResult<EitherString<'a>> {
match self {
JsonInput::String(s) => Ok(ValidationMatch::exact(s.as_str().into())),
// Justification for `strict` instead of `exact` is that in JSON strings can also
// represent other datatypes such as UUID and date more exactly, so string is a
// converting input
JsonInput::String(s) => Ok(s.as_str().into()),
_ => Err(ValError::new(ErrorTypeDefaults::StringType, self)),
}
}

fn validate_str(&'a self, _strict: bool) -> ValResult<ValidationMatch<EitherString<'a>>> {
// Justification for `strict` instead of `exact` is that in JSON strings can also
// represent other datatypes such as UUID and date more exactly, so string is a
// converting input
self.exact_str().map(ValidationMatch::strict)
}

fn validate_bytes(&'a self, _strict: bool) -> ValResult<EitherBytes<'a>> {
match self {
JsonInput::String(s) => Ok(s.as_bytes().into()),
Expand Down
10 changes: 5 additions & 5 deletions src/validators/uuid.rs
Expand Up @@ -114,11 +114,11 @@ impl Validator for UuidValidator {
input,
))
} else {
state.set_exactness_ceiling(if input.is_python() {
Exactness::Lax
} else {
Exactness::Strict
});
// In python mode this is a coercion, in JSON mode we treat a UUID string as an
// exact match
if input.is_python() {
state.set_exactness_ceiling(Exactness::Lax);
}
let uuid = self.get_uuid(input)?;
self.create_py_uuid(py, class, &uuid)
}
Expand Down
25 changes: 25 additions & 0 deletions tests/validators/test_union.py
@@ -1,8 +1,11 @@
from datetime import date
from enum import Enum
from typing import Type, TypeVar
from uuid import UUID

import pytest
from dirty_equals import IsFloat, IsInt
from pydantic.type_adapter import TypeAdapter

from pydantic_core import SchemaError, SchemaValidator, ValidationError, core_schema

Expand Down Expand Up @@ -511,3 +514,25 @@ def remove_prefix(v: str):
'12345678-1234-5678-1234-567812345678'
)
assert validator_called_count == 1


T = TypeVar('T')


@pytest.mark.parametrize(
('ty', 'input_value', 'expected_value'),
(
(UUID, '12345678-1234-5678-1234-567812345678', UUID('12345678-1234-5678-1234-567812345678')),
(date, '2020-01-01', date(2020, 1, 1)),
),
)
def test_smart_union_json_string_types(ty: Type[T], input_value: str, expected_value: T):
# Many types have to be represented in strings as JSON, we make sure that
# when parsing in JSON mode these types are preferred
assert TypeAdapter(ty | str).validate_json(f'"{input_value}"') == expected_value
# in Python mode the string will be preferred
assert TypeAdapter(ty | str).validate_python(input_value) == input_value

# Repeat with reversed order
assert TypeAdapter(str | ty).validate_json(f'"{input_value}"') == expected_value
assert TypeAdapter(str | ty).validate_python(input_value) == input_value

0 comments on commit 91da3b7

Please sign in to comment.