comparison data_schema/__init__.py @ 46:92ae1e882cef

Enhance pickling support
author Franz Glasner <f.glasner@feldmann-mg.com>
date Wed, 02 Aug 2023 16:51:34 +0200
parents 8a560e0c3180
children e7f6fc454f84
comparison
equal deleted inserted replaced
45:8a560e0c3180 46:92ae1e882cef
32 import copy 32 import copy
33 import datetime 33 import datetime
34 import enum 34 import enum
35 import pickle 35 import pickle
36 import re 36 import re
37 import sys
37 import urllib.parse 38 import urllib.parse
38 39
39 import rfc3986 40 import rfc3986
40 41
41 try: 42 try:
145 assert 80000 <= int(w[1:], 10), "Invalid WARNING code number in `{}'".format(w) 146 assert 80000 <= int(w[1:], 10), "Invalid WARNING code number in `{}'".format(w)
146 147
147 148
148 TYPE_RE = type(re.compile(r"\A.+\Z")) 149 TYPE_RE = type(re.compile(r"\A.+\Z"))
149 150
150 _SENTINEL = object()
151
152 SCHEMA_REF_KEY = "$ref" 151 SCHEMA_REF_KEY = "$ref"
153 """Key name for schema references (like a symlink within a schema)""" 152 """Key name for schema references (like a symlink within a schema)"""
154 153
155 SCHEMA_PATH_ROOT = "$root" 154 SCHEMA_PATH_ROOT = "$root"
156 """URI path to the root schema""" 155 """URI path to the root schema"""
157 156
158 SCHEMA_PATH_SELF = "$self" 157 SCHEMA_PATH_SELF = "$self"
159 """URI path to the current schema""" 158 """URI path to the current schema"""
159
160
161 class _SENTINELType(object):
162
163 @staticmethod
164 def _get_single(module, name):
165 return getattr(sys.modules[module], name)
166
167 def __reduce_ex__(self, proto):
168 """Make sure the _SENTINEL is ever only instantiated as singleton"""
169 return (_SENTINELType._get_single, (self.__module__, "_SENTINEL"))
170
171
172 _SENTINEL = _SENTINELType()
160 173
161 174
162 def problem_message(pr): 175 def problem_message(pr):
163 """ 176 """
164 177
307 self.is_sub_root = True 320 self.is_sub_root = True
308 else: 321 else:
309 self.is_sub_root = is_sub_root 322 self.is_sub_root = is_sub_root
310 323
311 def __reduce_ex__(self, proto): 324 def __reduce_ex__(self, proto):
312 rv = super().__reduce_ex__(proto) 325 return super().__reduce_ex__(proto)
313 #assert False, repr(rv)
314 print("RRRRRRR\n\n", repr(rv))
315 assert False, repr(rv)
316 return rv
317 326
318 def __getstate__(self): 327 def __getstate__(self):
319 return (1, self.parent, self.is_sub_root) 328 return (1, self.parent, self.is_sub_root)
320 329
321 def __setstate__(self, state): 330 def __setstate__(self, state):
445 else: 454 else:
446 if key is _SENTINEL and index is _SENTINEL: 455 if key is _SENTINEL and index is _SENTINEL:
447 raise TypeError("one of `key` and `index` must be given in a non-root context") 456 raise TypeError("one of `key` and `index` must be given in a non-root context")
448 if root_object is not _SENTINEL: 457 if root_object is not _SENTINEL:
449 raise TypeError("non-root context may not have a root object") 458 raise TypeError("non-root context may not have a root object")
459 self.root_object = root_object
450 if root_schema is not _SENTINEL: 460 if root_schema is not _SENTINEL:
451 raise TypeError("non-root context may not have a root schema") 461 raise TypeError("non-root context may not have a root schema")
462 self.root_schema = root_schema
452 if key is not _SENTINEL and index is not _SENTINEL: 463 if key is not _SENTINEL and index is not _SENTINEL:
453 raise ValueError("only one of `key` and `index` may be given in a context") 464 raise ValueError("only one of `key` and `index` may be given in a context")
454 if key_index is not _SENTINEL and key is _SENTINEL: 465 if key_index is not _SENTINEL and key is _SENTINEL:
455 raise ValueError("when having a `key_index` a `key` also must be given") 466 raise ValueError("when having a `key_index` a `key` also must be given")
456 self._parent = parent 467 self._parent = parent
470 if ver == 1: 481 if ver == 1:
471 _dummy, self._parent, self._key, self._key_index, self._index, self.root_object, self.root_schema, self._current_object, self._settings = state 482 _dummy, self._parent, self._key, self._key_index, self._index, self.root_object, self.root_schema, self._current_object, self._settings = state
472 else: 483 else:
473 raise pickle.UnpicklingError( 484 raise pickle.UnpicklingError(
474 "Unsupported pickle version for _Context: %d" % (ver,)) 485 "Unsupported pickle version for _Context: %d" % (ver,))
486
487 def __eq__(self, other):
488 if not isinstance(other, Context):
489 return NotImplemented
490 return ((self._parent == other._parent)
491 and (self._key == other._key)
492 and (self._key_index == other._key_index)
493 # XXX FIXME ???
494 # and (self.root_object == other.root_object)
495 # and (self.root_schema == other.root_schema)
496 # and (self._current_object == other._current_object)
497 and (self._settings == other._settings)
498 )
499
500 def __ne__(self, other):
501 #
502 # While the default in Python3 is sensible implementing is recommended
503 # when a built-in __eq__ is overwritten (Raymond Hettinger).
504 #
505 # Do not use not self == other because NotImplemented is not handled
506 # properly in some early Python versions (including Py2).
507 #
508 equal = self.__eq__(other)
509 return NotImplemented if equal is NotImplemented else not equal
475 510
476 @property 511 @property
477 def parent(self): 512 def parent(self):
478 return self._parent 513 return self._parent
479 514