Skip to content

Commit b503f51

Browse files
committed
add full type to validation error
1 parent 91c3541 commit b503f51

File tree

7 files changed

+28
-12
lines changed

7 files changed

+28
-12
lines changed

src/errors/validation_exception.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::errors::LocItem;
1818
use crate::get_pydantic_version;
1919
use crate::input::InputType;
2020
use crate::serializers::{DuckTypingSerMode, Extra, SerMode, SerializationState};
21-
use crate::tools::{safe_repr, SchemaDict};
21+
use crate::tools::{get_type_name, safe_repr, SchemaDict};
2222

2323
use super::line_error::ValLineError;
2424
use super::location::Location;
@@ -572,7 +572,7 @@ impl PyLineError {
572572
let input_str = safe_repr(input_value);
573573
truncate_input_value!(output, &input_str.to_cow());
574574

575-
if let Ok(type_) = input_value.get_type().qualname() {
575+
if let Ok(type_) = get_type_name(input_value.get_type()) {
576576
write!(output, ", input_type={type_}")?;
577577
}
578578
}

src/tools.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::borrow::Cow;
22

33
use pyo3::exceptions::PyKeyError;
44
use pyo3::prelude::*;
5-
use pyo3::types::{PyDict, PyString};
5+
use pyo3::types::{PyDict, PyString, PyType};
66
use pyo3::{ffi, intern, FromPyObject};
77

88
use jiter::{cached_py_string, pystring_fast_new, StringCacheMode};
@@ -114,6 +114,18 @@ impl std::fmt::Display for ReprOutput<'_> {
114114
}
115115
}
116116

117+
pub fn get_type_name(t: Bound<'_, PyType>) -> Result<String, ()> {
118+
if let Ok(repr) = t.repr() {
119+
let repr = repr.to_string();
120+
if repr.starts_with("<class '") {
121+
return Ok(repr[8..repr.len() - 2].to_owned());
122+
}
123+
// For example repr(typing.Literal) is 'typing.Literal'
124+
return Ok(repr);
125+
}
126+
Err(())
127+
}
128+
117129
pub fn safe_repr<'py>(v: &Bound<'py, PyAny>) -> ReprOutput<'py> {
118130
if let Ok(s) = v.repr() {
119131
ReprOutput::Python(s)

tests/test_errors.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ def test_error_on_repr(pydantic_version):
730730
assert str(exc_info.value) == (
731731
'1 validation error for int\n'
732732
' Input should be a valid integer '
733-
'[type=int_type, input_value=<unprintable BadRepr object>, input_type=BadRepr]\n'
733+
'[type=int_type, input_value=<unprintable BadRepr object>, input_type=tests.test_errors.BadRepr]\n'
734734
f' For further information visit https://errors.pydantic.dev/{pydantic_version}/v/int_type'
735735
)
736736
assert exc_info.value.errors(include_url=False) == [

tests/validators/test_arguments.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,7 @@ def test_error_display(pydantic_version):
10181018
'1 validation error for arguments\n'
10191019
'b\n'
10201020
' Missing required argument [type=missing_argument, '
1021-
"input_value=ArgsKwargs((), {'a': 1}), input_type=ArgsKwargs]\n"
1021+
"input_value=ArgsKwargs((), {'a': 1}), input_type=pydantic_core._pydantic_core.ArgsKwargs]\n"
10221022
f' For further information visit https://errors.pydantic.dev/{pydantic_version}/v/missing_argument'
10231023
)
10241024
# insert_assert(exc_info.value.json(include_url=False))

tests/validators/test_decimal.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,9 @@ def test_non_finite_json_values(py_and_json: PyAndJson, input_value, allow_inf_n
358358
(
359359
Decimal('nan'),
360360
False,
361-
Err("Input should be a finite number [type=finite_number, input_value=Decimal('NaN'), input_type=Decimal]"),
361+
Err(
362+
"Input should be a finite number [type=finite_number, input_value=Decimal('NaN'), input_type=decimal.Decimal]"
363+
),
362364
),
363365
],
364366
)
@@ -379,21 +381,21 @@ def test_non_finite_decimal_values(strict, input_value, allow_inf_nan, expected)
379381
Decimal('+inf'),
380382
False,
381383
Err(
382-
"Input should be a finite number [type=finite_number, input_value=Decimal('Infinity'), input_type=Decimal]"
384+
"Input should be a finite number [type=finite_number, input_value=Decimal('Infinity'), input_type=decimal.Decimal]"
383385
),
384386
),
385387
(
386388
Decimal('-inf'),
387389
True,
388390
Err(
389-
"Input should be greater than 0 [type=greater_than, input_value=Decimal('-Infinity'), input_type=Decimal]"
391+
"Input should be greater than 0 [type=greater_than, input_value=Decimal('-Infinity'), input_type=decimal.Decimal]"
390392
),
391393
),
392394
(
393395
Decimal('-inf'),
394396
False,
395397
Err(
396-
"Input should be a finite number [type=finite_number, input_value=Decimal('-Infinity'), input_type=Decimal]"
398+
"Input should be a finite number [type=finite_number, input_value=Decimal('-Infinity'), input_type=decimal.Decimal]"
397399
),
398400
),
399401
],

tests/validators/test_int.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def test_int_py_and_json(py_and_json: PyAndJson, input_value, expected):
119119
Decimal('1.001'),
120120
Err(
121121
'Input should be a valid integer, got a number with a fractional part '
122-
"[type=int_from_float, input_value=Decimal('1.001'), input_type=Decimal]"
122+
"[type=int_from_float, input_value=Decimal('1.001'), input_type=decimal.Decimal]"
123123
),
124124
id='decimal-remainder',
125125
),
@@ -166,7 +166,7 @@ def test_int(input_value, expected):
166166
Decimal('1.001'),
167167
Err(
168168
'Input should be a valid integer, got a number with a fractional part '
169-
"[type=int_from_float, input_value=Decimal('1.001'), input_type=Decimal]"
169+
"[type=int_from_float, input_value=Decimal('1.001'), input_type=decimal.Decimal]"
170170
),
171171
id='decimal-remainder',
172172
),

tests/validators/test_string.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ def test_str(py_and_json: PyAndJson, input_value, expected):
5050
(123, Err('Input should be a valid string [type=string_type, input_value=123, input_type=int]')),
5151
(
5252
Decimal('123'),
53-
Err("Input should be a valid string [type=string_type, input_value=Decimal('123'), input_type=Decimal]"),
53+
Err(
54+
"Input should be a valid string [type=string_type, input_value=Decimal('123'), input_type=decimal.Decimal]"
55+
),
5456
),
5557
],
5658
)

0 commit comments

Comments
 (0)