Mercurial > hgrepos > Python > libs > data-schema
changeset 44:ea8c2d01a9d9
Begin pickling support for ValidatenProblems, _Schema and Context
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Wed, 02 Aug 2023 09:31:49 +0200 |
| parents | 4ca530618303 |
| children | 8a560e0c3180 |
| files | data_schema/__init__.py tests/test_schema.py |
| diffstat | 2 files changed, 133 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/data_schema/__init__.py Thu Jul 20 09:37:22 2023 +0200 +++ b/data_schema/__init__.py Wed Aug 02 09:31:49 2023 +0200 @@ -32,6 +32,7 @@ import copy import datetime import enum +import pickle import re import urllib.parse @@ -56,6 +57,9 @@ WARNING = 30 ERROR = 40 + def __reduce_ex__(self, protocol): + return (getattr, (self.__class__, self._name_)) + @enum.unique class ERRORS(enum.Enum): @@ -120,11 +124,17 @@ E10058 = NC_("schema-msg", "failing `all-of' item") E10059 = NC_("schema-msg", "forbidden key detected") + def __reduce_ex__(self, protocol): + return (getattr, (self.__class__, self._name_)) + @enum.unique class WARNINGS(enum.Enum): W80000 = NC_("schema-msg", "duplicate dict key") + def __reduce_ex__(self, protocol): + return (getattr, (self.__class__, self._name_)) + # Check some invariants at import time for e in ERRORS.__members__: @@ -217,6 +227,28 @@ self.cause = cause self.index = index + def __eq__(self, other): + if not isinstance(other, ValidationProblem): + return NotImplemented + return ((self.code == other.code) + and (self.severity == other.severity) + and (self.hint == other.hint) + and (self.context == other.context) + and (self.cause == other.cause) + and (self.index == other.index)) + + def __getstate__(self): + return (1, self.code, self.severity, self.hint, self.context, + self.cause, self.index) + + def __setstate__(self, state): + ver = state[0] + if ver == 1: + _dummy, self.code, self.severity, self.hint, self.context, self.cause, self.index = state + else: + raise pickle.UnpicklingError( + "Unsupported pickle version for ValidationProblem: %d" % (ver,)) + def __repr__(self): try: msg = " (" + problem_message(self) + ")" @@ -265,6 +297,26 @@ else: self.is_sub_root = is_sub_root + def __reduce_ex__(self, proto): + rv = super().__reduce_ex__(proto) + #assert False, repr(rv) + print("RRRRRRR\n\n", repr(rv)) + assert False, repr(rv) + return rv + + def __getstate__(self): + return (1, self.parent, self.is_sub_root) + + def __setstate__(self, state): + ver = state[0] + if ver == 1: + _dummy, self.parent, self.is_sub_root = state + if self.parent is None: + self._schema_cache = {} + else: + raise pickle.UnpicklingError( + "Unsupported pickle version for _Schema: %d" % (ver,)) + @property def ROOT(self): """Get the root schema""" @@ -397,6 +449,19 @@ self._current_object = current_object self._settings = settings + def __getstate__(self): + return (1, self._parent, self._key, self._key_index, self._index, + self.root_object, self.root_schema, + self._current_object, self._settings) + + def __setstate__(self, state): + ver = state[0] + if ver == 1: + _dummy, self._parent, self._key, self._key_index, self._index, self.root_object, self.root_schema, self._current_object, self._settings = state + else: + raise pickle.UnpicklingError( + "Unsupported pickle version for _Context: %d" % (ver,)) + @property def parent(self): return self._parent
--- a/tests/test_schema.py Thu Jul 20 09:37:22 2023 +0200 +++ b/tests/test_schema.py Wed Aug 02 09:31:49 2023 +0200 @@ -2,6 +2,7 @@ import copy import datetime import functools +import pickle import re import unittest @@ -22,6 +23,54 @@ yield from () +class Pickling(unittest.TestCase): + + def test_severity(self): + for sev in SEVERITY: + b = pickle.dumps(sev) + sev2 = pickle.loads(b) + self.assertEqual(sev, sev2) + + def test_errors(self): + for err in ERRORS: + b = pickle.dumps(err) + err2 = pickle.loads(b) + self.assertEqual(err, err2) + + def test_warnings(self): + for warn in ERRORS: + b = pickle.dumps(warn) + warn2 = pickle.loads(b) + self.assertEqual(warn, warn2) + + def test_combination(self): + obj = (SEVERITY.ERROR, ERRORS.E10001, WARNINGS.W80000) + b = pickle.dumps(obj) + obj2 = pickle.loads(b) + self.assertEqual(obj, obj2) + + def test_problem_1(self): + problem = data_schema.ValidationProblem( + code=ERRORS.E10002, + severity=SEVERITY.ERROR, + hint="a-hint") + b = pickle.dumps(problem) + problem2 = pickle.loads(b) + self.assertIsInstance(problem2, data_schema.ValidationProblem) + self.assertEqual(problem, problem2) + + def test_problem_2(self): + problem = data_schema.ValidationProblem( + code=ERRORS.E10002, + severity=SEVERITY.ERROR, + hint="a-hint") + + def _cmp(a, b): + return a == b + + self.assertFalse(_cmp(problem, 1)) + + class YAML(unittest.TestCase): """Tests to load Python objects from YAML with complex Python-specific @@ -2483,6 +2532,25 @@ self.assertEqual(1, len(pr)) self.assertEqual(ERRORS.E10030, pr[0].code) + def test_number_pickle(self): + pr = list(data_schema.validate(1.8, {"$type": "number"})) + self.assertEqual(0, len(pr)) + pr = list(data_schema.validate(1, {"$type": "num"})) + self.assertEqual(0, len(pr)) + + pr = list(data_schema.validate( + 2.0, + {"$type": "number", + "min-value": 3, + "max-value": 1.3})) + + pr2 = pickle.loads(pickle.dumps(pr)) + self.assertEqual(2, len(pr2)) + self.assertEqual(ERRORS.E10031, pr2[0].code) + self.assertEqual(ERRORS.E10032, pr2[1].code) + self.maxDiff = None + self.assertEqual(repr(pr), repr(pr2)) + def test_bool(self): pr = list(data_schema.validate(True, {"$type": "bool"})) self.assertEqual(0, len(pr))
