Skip to content

Commit 9693919

Browse files
authored
Error changes (#307)
* rename kind -> type * renaming message -> msg * rename context -> ctx * rename input_value -> input * make "loc" a tuple, not a list
1 parent 8f2daf6 commit 9693919

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+1457
-1505
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ except ValidationError as e:
6464
1 validation error for model
6565
age
6666
Input should be greater than or equal to 18
67-
[kind=greater_than_equal, context={ge: 18}, input_value=11, input_type=int]
67+
[type=greater_than_equal, context={ge: 18}, input_value=11, input_type=int]
6868
"""
6969
```
7070

pydantic_core/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from ._pydantic_core import (
22
PydanticCustomError,
3-
PydanticKindError,
3+
PydanticKnownError,
44
PydanticOmit,
55
SchemaError,
66
SchemaValidator,
@@ -17,6 +17,6 @@
1717
'SchemaError',
1818
'ValidationError',
1919
'PydanticCustomError',
20-
'PydanticKindError',
20+
'PydanticKnownError',
2121
'PydanticOmit',
2222
)

pydantic_core/_pydantic_core.pyi

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import decimal
22
import sys
33
from typing import Any, TypedDict
44

5-
from pydantic_core.core_schema import CoreConfig, CoreSchema, ErrorKind
5+
from pydantic_core.core_schema import CoreConfig, CoreSchema, ErrorType
66

77
if sys.version_info < (3, 11):
88
from typing_extensions import NotRequired
@@ -16,7 +16,7 @@ __all__ = (
1616
'SchemaError',
1717
'ValidationError',
1818
'PydanticCustomError',
19-
'PydanticKindError',
19+
'PydanticKnownError',
2020
'PydanticOmit',
2121
'list_all_errors',
2222
)
@@ -42,7 +42,7 @@ class SchemaError(Exception):
4242
pass
4343

4444
class ErrorDetails(TypedDict):
45-
kind: str
45+
type: str
4646
loc: 'list[int | str]'
4747
message: str
4848
input_value: Any
@@ -55,33 +55,33 @@ class ValidationError(ValueError):
5555
def errors(self, include_context: bool = True) -> 'list[ErrorDetails]': ...
5656

5757
class PydanticCustomError(ValueError):
58-
kind: str
58+
type: str
5959
message_template: str
6060
context: 'dict[str, Any] | None'
6161

62-
def __init__(self, kind: str, message_template: str, context: 'dict[str, Any] | None' = None) -> None: ...
62+
def __init__(self, error_type: str, message_template: str, context: 'dict[str, Any] | None' = None) -> None: ...
6363
def message(self) -> str: ...
6464

65-
class PydanticKindError(ValueError):
66-
kind: ErrorKind
65+
class PydanticKnownError(ValueError):
66+
type: ErrorType
6767
message_template: str
6868
context: 'dict[str, str | int | float] | None'
6969

7070
def __init__(
71-
self, kind: ErrorKind, context: 'dict[str, str | int | float | decimal.Decimal] | None' = None
71+
self, error_type: ErrorType, context: 'dict[str, str | int | float | decimal.Decimal] | None' = None
7272
) -> None: ...
7373
def message(self) -> str: ...
7474

7575
class PydanticOmit(Exception):
7676
def __init__(self) -> None: ...
7777

78-
class ErrorKindInfo(TypedDict):
79-
kind: ErrorKind
78+
class ErrorTypeInfo(TypedDict):
79+
type: ErrorType
8080
message_template: str
8181
example_message: str
8282
example_context: 'dict[str, str | int | float] | None'
8383

84-
def list_all_errors() -> 'list[ErrorKindInfo]':
84+
def list_all_errors() -> 'list[ErrorTypeInfo]':
8585
"""
8686
Get information about all built-in errors.
8787
"""

pydantic_core/core_schema.py

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -736,16 +736,10 @@ def nullable_schema(
736736
return dict_not_none(type='nullable', schema=schema, strict=strict, ref=ref, extra=extra)
737737

738738

739-
class CustomError(TypedDict, total=False):
740-
kind: Required[str]
741-
message: str
742-
context: Dict[str, Union[str, int]]
743-
744-
745739
class UnionSchema(TypedDict, total=False):
746740
type: Required[Literal['union']]
747741
choices: Required[List[CoreSchema]]
748-
custom_error_kind: str
742+
custom_error_type: str
749743
custom_error_message: str
750744
custom_error_context: Dict[str, Union[str, int, float]]
751745
strict: bool
@@ -755,7 +749,7 @@ class UnionSchema(TypedDict, total=False):
755749

756750
def union_schema(
757751
*choices: CoreSchema,
758-
custom_error_kind: str | None = None,
752+
custom_error_type: str | None = None,
759753
custom_error_message: str | None = None,
760754
custom_error_context: dict[str, str | int] | None = None,
761755
strict: bool | None = None,
@@ -765,7 +759,7 @@ def union_schema(
765759
return dict_not_none(
766760
type='union',
767761
choices=choices,
768-
custom_error_kind=custom_error_kind,
762+
custom_error_type=custom_error_type,
769763
custom_error_message=custom_error_message,
770764
custom_error_context=custom_error_context,
771765
strict=strict,
@@ -780,7 +774,7 @@ class TaggedUnionSchema(TypedDict, total=False):
780774
discriminator: Required[
781775
Union[str, List[Union[str, int]], List[List[Union[str, int]]], Callable[[Any], Optional[str]]]
782776
]
783-
custom_error_kind: str
777+
custom_error_type: str
784778
custom_error_message: str
785779
custom_error_context: Dict[str, Union[str, int, float]]
786780
strict: bool
@@ -792,7 +786,7 @@ def tagged_union_schema(
792786
choices: Dict[str, CoreSchema],
793787
discriminator: str | list[str | int] | list[list[str | int]] | Callable[[Any], str | None],
794788
*,
795-
custom_error_kind: str | None = None,
789+
custom_error_type: str | None = None,
796790
custom_error_message: str | None = None,
797791
custom_error_context: dict[str, int | str | float] | None = None,
798792
strict: bool | None = None,
@@ -803,7 +797,7 @@ def tagged_union_schema(
803797
type='tagged-union',
804798
choices=choices,
805799
discriminator=discriminator,
806-
custom_error_kind=custom_error_kind,
800+
custom_error_type=custom_error_type,
807801
custom_error_message=custom_error_message,
808802
custom_error_context=custom_error_context,
809803
strict=strict,
@@ -989,7 +983,7 @@ def recursive_reference_schema(schema_ref: str) -> RecursiveReferenceSchema:
989983
class CustomErrorSchema(TypedDict, total=False):
990984
type: Required[Literal['custom_error']]
991985
schema: Required[CoreSchema]
992-
custom_error_kind: Required[str]
986+
custom_error_type: Required[str]
993987
custom_error_message: str
994988
custom_error_context: Dict[str, Union[str, int, float]]
995989
ref: str
@@ -998,7 +992,7 @@ class CustomErrorSchema(TypedDict, total=False):
998992

999993
def custom_error_schema(
1000994
schema: CoreSchema,
1001-
custom_error_kind: str,
995+
custom_error_type: str,
1002996
*,
1003997
custom_error_message: str | None = None,
1004998
custom_error_context: dict[str, str | int | float] | None = None,
@@ -1008,7 +1002,7 @@ def custom_error_schema(
10081002
return dict_not_none(
10091003
type='custom_error',
10101004
schema=schema,
1011-
custom_error_kind=custom_error_kind,
1005+
custom_error_type=custom_error_type,
10121006
custom_error_message=custom_error_message,
10131007
custom_error_context=custom_error_context,
10141008
ref=ref,
@@ -1067,9 +1061,9 @@ def json_schema(schema: CoreSchema | None = None, *, ref: str | None = None, ext
10671061
JsonSchema,
10681062
]
10691063

1070-
# used in _pydantic_core.pyi::PydanticKindError
1064+
# used in _pydantic_core.pyi::PydanticKnownError
10711065
# to update this, call `pytest -k test_all_errors` and copy the output
1072-
ErrorKind = Literal[
1066+
ErrorType = Literal[
10731067
'json_invalid',
10741068
'json_type',
10751069
'recursion_loop',

src/errors/line_error.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use pyo3::PyDowncastError;
44

55
use crate::input::{Input, JsonInput};
66

7-
use super::kinds::ErrorKind;
87
use super::location::{LocItem, Location};
8+
use super::types::ErrorType;
99
use super::validation_exception::{pretty_py_line_errors, PyLineError};
1010

1111
pub type ValResult<'a, T> = Result<T, ValError<'a>>;
@@ -36,16 +36,16 @@ impl<'a> From<Vec<ValLineError<'a>>> for ValError<'a> {
3636
}
3737

3838
impl<'a> ValError<'a> {
39-
pub fn new(kind: ErrorKind, input: &'a impl Input<'a>) -> ValError<'a> {
40-
Self::LineErrors(vec![ValLineError::new(kind, input)])
39+
pub fn new(error_type: ErrorType, input: &'a impl Input<'a>) -> ValError<'a> {
40+
Self::LineErrors(vec![ValLineError::new(error_type, input)])
4141
}
4242

43-
pub fn new_with_loc(kind: ErrorKind, input: &'a impl Input<'a>, loc: impl Into<LocItem>) -> ValError<'a> {
44-
Self::LineErrors(vec![ValLineError::new_with_loc(kind, input, loc)])
43+
pub fn new_with_loc(error_type: ErrorType, input: &'a impl Input<'a>, loc: impl Into<LocItem>) -> ValError<'a> {
44+
Self::LineErrors(vec![ValLineError::new_with_loc(error_type, input, loc)])
4545
}
4646

47-
pub fn new_custom_input(kind: ErrorKind, input_value: InputValue<'a>) -> ValError<'a> {
48-
Self::LineErrors(vec![ValLineError::new_custom_input(kind, input_value)])
47+
pub fn new_custom_input(error_type: ErrorType, input_value: InputValue<'a>) -> ValError<'a> {
48+
Self::LineErrors(vec![ValLineError::new_custom_input(error_type, input_value)])
4949
}
5050

5151
/// helper function to call with_outer on line items if applicable
@@ -81,32 +81,32 @@ pub fn pretty_line_errors(py: Python, line_errors: Vec<ValLineError>) -> String
8181
/// I don't like the name `ValLineError`, but it's the best I could come up with (for now).
8282
#[cfg_attr(debug_assertions, derive(Debug))]
8383
pub struct ValLineError<'a> {
84-
pub kind: ErrorKind,
84+
pub error_type: ErrorType,
8585
// location is reversed so that adding an "outer" location item is pushing, it's reversed before showing to the user
8686
pub location: Location,
8787
pub input_value: InputValue<'a>,
8888
}
8989

9090
impl<'a> ValLineError<'a> {
91-
pub fn new(kind: ErrorKind, input: &'a impl Input<'a>) -> ValLineError<'a> {
91+
pub fn new(error_type: ErrorType, input: &'a impl Input<'a>) -> ValLineError<'a> {
9292
Self {
93-
kind,
93+
error_type,
9494
input_value: input.as_error_value(),
9595
location: Location::default(),
9696
}
9797
}
9898

99-
pub fn new_with_loc(kind: ErrorKind, input: &'a impl Input<'a>, loc: impl Into<LocItem>) -> ValLineError<'a> {
99+
pub fn new_with_loc(error_type: ErrorType, input: &'a impl Input<'a>, loc: impl Into<LocItem>) -> ValLineError<'a> {
100100
Self {
101-
kind,
101+
error_type,
102102
input_value: input.as_error_value(),
103103
location: Location::new_some(loc.into()),
104104
}
105105
}
106106

107-
pub fn new_custom_input(kind: ErrorKind, input_value: InputValue<'a>) -> ValLineError<'a> {
107+
pub fn new_custom_input(error_type: ErrorType, input_value: InputValue<'a>) -> ValLineError<'a> {
108108
Self {
109-
kind,
109+
error_type,
110110
input_value,
111111
location: Location::default(),
112112
}
@@ -119,16 +119,16 @@ impl<'a> ValLineError<'a> {
119119
self
120120
}
121121

122-
// change the kind on a error in place
123-
pub fn with_kind(mut self, kind: ErrorKind) -> Self {
124-
self.kind = kind;
122+
// change the error_type on a error in place
123+
pub fn with_type(mut self, error_type: ErrorType) -> Self {
124+
self.error_type = error_type;
125125
self
126126
}
127127

128128
/// a bit like clone but change the lifetime to match py, used by ValError.duplicate above
129129
pub fn duplicate<'py>(&'a self, py: Python<'py>) -> ValLineError<'py> {
130130
ValLineError {
131-
kind: self.kind.clone(),
131+
error_type: self.error_type.clone(),
132132
input_value: InputValue::<'py>::from(self.input_value.to_object(py)),
133133
location: self.location.clone(),
134134
}

src/errors/location.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
use pyo3::once_cell::GILOnceCell;
12
use std::fmt;
23

34
use pyo3::prelude::*;
4-
use pyo3::types::PyList;
5+
use pyo3::types::PyTuple;
56

67
/// Used to store individual items of the error location, e.g. a string for key/field names
78
/// or a number for array indices.
@@ -85,11 +86,15 @@ impl Default for Location {
8586
}
8687
}
8788

89+
static EMPTY_TUPLE: GILOnceCell<PyObject> = GILOnceCell::new();
90+
8891
impl ToPyObject for Location {
8992
fn to_object(&self, py: Python<'_>) -> PyObject {
9093
match self {
91-
Self::List(loc) => loc.iter().rev().collect::<Vec<_>>().to_object(py),
92-
Self::Empty => PyList::empty(py).to_object(py),
94+
Self::List(loc) => PyTuple::new(py, loc.iter().rev()).to_object(py),
95+
Self::Empty => EMPTY_TUPLE
96+
.get_or_init(py, || PyTuple::empty(py).to_object(py))
97+
.clone_ref(py),
9398
}
9499
}
95100
}

src/errors/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
use pyo3::prelude::*;
22

3-
mod kinds;
43
mod line_error;
54
mod location;
5+
mod types;
66
mod validation_exception;
77
mod value_exception;
88

9-
pub use self::kinds::{list_all_errors, ErrorKind};
109
pub use self::line_error::{pretty_line_errors, InputValue, ValError, ValLineError, ValResult};
1110
pub use self::location::LocItem;
11+
pub use self::types::{list_all_errors, ErrorType};
1212
pub use self::validation_exception::ValidationError;
13-
pub use self::value_exception::{PydanticCustomError, PydanticKindError, PydanticOmit};
13+
pub use self::value_exception::{PydanticCustomError, PydanticKnownError, PydanticOmit};
1414

1515
pub fn py_err_string(py: Python, err: PyErr) -> String {
1616
let value = err.value(py);

0 commit comments

Comments
 (0)