Skip to content

Commit dfe5027

Browse files
authored
Implement pickling for ValidationError (#1119)
1 parent a5b3906 commit dfe5027

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

src/errors/validation_exception.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,20 @@ impl ValidationError {
341341
fn __str__(&self, py: Python) -> String {
342342
self.__repr__(py)
343343
}
344+
345+
fn __reduce__(slf: &PyCell<Self>) -> PyResult<(&PyAny, PyObject)> {
346+
let py = slf.py();
347+
let callable = slf.getattr("from_exception_data")?;
348+
let borrow = slf.try_borrow()?;
349+
let args = (
350+
borrow.title.as_ref(py),
351+
borrow.errors(py, include_url_env(py), true, true)?,
352+
borrow.input_type.into_py(py),
353+
borrow.hide_input,
354+
)
355+
.into_py(slf.py());
356+
Ok((callable, args))
357+
}
344358
}
345359

346360
// TODO: is_utf8_char_boundary, floor_char_boundary and ceil_char_boundary

tests/test_errors.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import enum
2+
import pickle
23
import re
34
import sys
45
from decimal import Decimal
@@ -1074,3 +1075,17 @@ def test_hide_input_in_json() -> None:
10741075

10751076
for error in exc_info.value.errors(include_input=False):
10761077
assert 'input' not in error
1078+
1079+
1080+
@pytest.mark.skipif(
1081+
sys.version_info < (3, 9) and sys.implementation.name == 'pypy',
1082+
reason='PyPy before 3.9 cannot pickle this correctly',
1083+
)
1084+
def test_validation_error_pickle() -> None:
1085+
s = SchemaValidator({'type': 'int'})
1086+
with pytest.raises(ValidationError) as exc_info:
1087+
s.validate_python('definitely not an int')
1088+
1089+
original = exc_info.value
1090+
roundtripped = pickle.loads(pickle.dumps(original))
1091+
assert original.errors() == roundtripped.errors()

0 commit comments

Comments
 (0)