diff 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
line wrap: on
line diff
--- a/data_schema/__init__.py	Wed Aug 02 13:58:25 2023 +0200
+++ b/data_schema/__init__.py	Wed Aug 02 16:51:34 2023 +0200
@@ -34,6 +34,7 @@
 import enum
 import pickle
 import re
+import sys
 import urllib.parse
 
 import rfc3986
@@ -147,8 +148,6 @@
 
 TYPE_RE = type(re.compile(r"\A.+\Z"))
 
-_SENTINEL = object()
-
 SCHEMA_REF_KEY = "$ref"
 """Key name for schema references (like a symlink within a schema)"""
 
@@ -159,6 +158,20 @@
 """URI path to the current schema"""
 
 
+class _SENTINELType(object):
+
+    @staticmethod
+    def _get_single(module, name):
+        return getattr(sys.modules[module], name)
+
+    def __reduce_ex__(self, proto):
+        """Make sure the _SENTINEL is ever only instantiated as singleton"""
+        return (_SENTINELType._get_single, (self.__module__, "_SENTINEL"))
+
+
+_SENTINEL = _SENTINELType()
+
+
 def problem_message(pr):
     """
 
@@ -309,11 +322,7 @@
             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
+        return super().__reduce_ex__(proto)
 
     def __getstate__(self):
         return (1, self.parent, self.is_sub_root)
@@ -447,8 +456,10 @@
                 raise TypeError("one of `key` and `index` must be given in a non-root context")
             if root_object is not _SENTINEL:
                 raise TypeError("non-root context may not have a root object")
+            self.root_object = root_object
             if root_schema is not _SENTINEL:
                 raise TypeError("non-root context may not have a root schema")
+            self.root_schema = root_schema
         if key is not _SENTINEL and index is not _SENTINEL:
             raise ValueError("only one of `key` and `index` may be given in a context")
         if key_index is not _SENTINEL and key is _SENTINEL:
@@ -473,6 +484,30 @@
             raise pickle.UnpicklingError(
                 "Unsupported pickle version for _Context: %d" % (ver,))
 
+    def __eq__(self, other):
+        if not isinstance(other, Context):
+            return NotImplemented
+        return ((self._parent == other._parent)
+                and (self._key == other._key)
+                and (self._key_index == other._key_index)
+# XXX FIXME ???
+#                and (self.root_object == other.root_object)
+#                and (self.root_schema == other.root_schema)
+#                and (self._current_object == other._current_object)
+                and (self._settings == other._settings)
+        )
+
+    def __ne__(self, other):
+        #
+        # While the default in Python3 is sensible implementing is recommended
+        # when a built-in __eq__ is overwritten (Raymond Hettinger).
+        #
+        # Do not use not self == other because NotImplemented is not handled
+        # properly in some early Python versions (including Py2).
+        #
+        equal = self.__eq__(other)
+        return NotImplemented if equal is NotImplemented else not equal
+
     @property
     def parent(self):
         return self._parent