Loading django/core/exceptions.py +9 −1 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ Global Django exception and warning classes. from functools import reduce import operator from django.utils import six from django.utils.encoding import force_text Loading Loading @@ -84,10 +85,17 @@ class ValidationError(Exception): list or dictionary can be an actual `list` or `dict` or an instance of ValidationError with its `error_list` or `error_dict` attribute set. """ # PY2 can't pickle naive exception: http://bugs.python.org/issue1692335. super(ValidationError, self).__init__(message, code, params) if isinstance(message, ValidationError): if hasattr(message, 'error_dict'): message = message.error_dict elif not hasattr(message, 'message'): # PY2 has a `message` property which is always there so we can't # duck-type on it. It was introduced in Python 2.5 and already # deprecated in Python 2.6. elif not hasattr(message, 'message' if six.PY3 else 'code'): message = message.error_list else: message, code, params = message.message, message.code, message.params Loading tests/validation/test_picklable.py 0 → 100644 +41 −0 Original line number Diff line number Diff line import pickle from unittest import TestCase from django.core.exceptions import ValidationError class PickableValidationErrorTestCase(TestCase): def test_validationerror_is_picklable(self): original = ValidationError('a', code='something') unpickled = pickle.loads(pickle.dumps(original)) self.assertIs(unpickled, unpickled.error_list[0]) self.assertEqual(original.message, unpickled.message) self.assertEqual(original.code, unpickled.code) original = ValidationError('a', code='something') unpickled = pickle.loads(pickle.dumps(ValidationError(original))) self.assertIs(unpickled, unpickled.error_list[0]) self.assertEqual(original.message, unpickled.message) self.assertEqual(original.code, unpickled.code) original = ValidationError(['a', 'b']) unpickled = pickle.loads(pickle.dumps(original)) self.assertEqual(original.error_list[0].message, unpickled.error_list[0].message) self.assertEqual(original.error_list[1].message, unpickled.error_list[1].message) original = ValidationError(['a', 'b']) unpickled = pickle.loads(pickle.dumps(ValidationError(original))) self.assertEqual(original.error_list[0].message, unpickled.error_list[0].message) self.assertEqual(original.error_list[1].message, unpickled.error_list[1].message) original = ValidationError([ValidationError('a'), ValidationError('b')]) unpickled = pickle.loads(pickle.dumps(original)) self.assertIs(unpickled.args[0][0], unpickled.error_list[0]) self.assertEqual(original.error_list[0].message, unpickled.error_list[0].message) self.assertEqual(original.error_list[1].message, unpickled.error_list[1].message) message_dict = {'field1': ['a', 'b'], 'field2': ['c', 'd']} original = ValidationError(message_dict) unpickled = pickle.loads(pickle.dumps(original)) self.assertEqual(unpickled.message_dict, message_dict) Loading
django/core/exceptions.py +9 −1 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ Global Django exception and warning classes. from functools import reduce import operator from django.utils import six from django.utils.encoding import force_text Loading Loading @@ -84,10 +85,17 @@ class ValidationError(Exception): list or dictionary can be an actual `list` or `dict` or an instance of ValidationError with its `error_list` or `error_dict` attribute set. """ # PY2 can't pickle naive exception: http://bugs.python.org/issue1692335. super(ValidationError, self).__init__(message, code, params) if isinstance(message, ValidationError): if hasattr(message, 'error_dict'): message = message.error_dict elif not hasattr(message, 'message'): # PY2 has a `message` property which is always there so we can't # duck-type on it. It was introduced in Python 2.5 and already # deprecated in Python 2.6. elif not hasattr(message, 'message' if six.PY3 else 'code'): message = message.error_list else: message, code, params = message.message, message.code, message.params Loading
tests/validation/test_picklable.py 0 → 100644 +41 −0 Original line number Diff line number Diff line import pickle from unittest import TestCase from django.core.exceptions import ValidationError class PickableValidationErrorTestCase(TestCase): def test_validationerror_is_picklable(self): original = ValidationError('a', code='something') unpickled = pickle.loads(pickle.dumps(original)) self.assertIs(unpickled, unpickled.error_list[0]) self.assertEqual(original.message, unpickled.message) self.assertEqual(original.code, unpickled.code) original = ValidationError('a', code='something') unpickled = pickle.loads(pickle.dumps(ValidationError(original))) self.assertIs(unpickled, unpickled.error_list[0]) self.assertEqual(original.message, unpickled.message) self.assertEqual(original.code, unpickled.code) original = ValidationError(['a', 'b']) unpickled = pickle.loads(pickle.dumps(original)) self.assertEqual(original.error_list[0].message, unpickled.error_list[0].message) self.assertEqual(original.error_list[1].message, unpickled.error_list[1].message) original = ValidationError(['a', 'b']) unpickled = pickle.loads(pickle.dumps(ValidationError(original))) self.assertEqual(original.error_list[0].message, unpickled.error_list[0].message) self.assertEqual(original.error_list[1].message, unpickled.error_list[1].message) original = ValidationError([ValidationError('a'), ValidationError('b')]) unpickled = pickle.loads(pickle.dumps(original)) self.assertIs(unpickled.args[0][0], unpickled.error_list[0]) self.assertEqual(original.error_list[0].message, unpickled.error_list[0].message) self.assertEqual(original.error_list[1].message, unpickled.error_list[1].message) message_dict = {'field1': ['a', 'b'], 'field2': ['c', 'd']} original = ValidationError(message_dict) unpickled = pickle.loads(pickle.dumps(original)) self.assertEqual(unpickled.message_dict, message_dict)