From 52397fcf322df9e848d13f811cbbc768feedc41f Mon Sep 17 00:00:00 2001 From: Nick Hall Date: Tue, 15 Oct 2024 00:27:02 +0100 Subject: [PATCH] Refactor JSON serialization --- gramps/gen/lib/baseobj.py | 12 ++++++++++++ gramps/gen/lib/date.py | 14 ++++++++++++++ gramps/gen/lib/event.py | 15 +++++++++++++++ gramps/gen/lib/eventref.py | 10 ++++++++++ gramps/gen/lib/grampstype.py | 16 +++++++++++++++- gramps/gen/lib/mediaref.py | 6 ++++++ gramps/gen/lib/person.py | 11 +++++++++++ gramps/gen/lib/serialize.py | 32 ++++++++------------------------ gramps/gen/lib/styledtext.py | 10 ++++++++++ gramps/gen/lib/styledtexttag.py | 12 ++++++++++++ gramps/gen/lib/tag.py | 19 +++++++++++++++++++ 11 files changed, 132 insertions(+), 25 deletions(-) diff --git a/gramps/gen/lib/baseobj.py b/gramps/gen/lib/baseobj.py index f5bf2e6a0cd..8ccd154afc1 100644 --- a/gramps/gen/lib/baseobj.py +++ b/gramps/gen/lib/baseobj.py @@ -57,6 +57,18 @@ def unserialize(self, data): Convert a serialized tuple of data to an object. """ + def get_object_state(self): + attr_dict = {"_class": self.__class__.__name__} + for key, value in self.__dict__.items(): + if not key.startswith("_"): + attr_dict[key] = value + return attr_dict + + def set_object_state(self, attr_dict): + for key, value in attr_dict.items(): + if key != "_class": + setattr(self, key, value) + def matches_string(self, pattern, case_sensitive=False): """ Return True if any text data in the object or any of it's child diff --git a/gramps/gen/lib/date.py b/gramps/gen/lib/date.py index 8905966792e..b7896f4aba1 100644 --- a/gramps/gen/lib/date.py +++ b/gramps/gen/lib/date.py @@ -750,6 +750,20 @@ def unserialize(self, data): raise DateError("Invalid date to unserialize") return self + def get_object_state(self): + attr_dict = {"_class": self.__class__.__name__} + for key, value in self.__dict__.items(): + if not key.startswith("_"): + attr_dict[key] = value + return attr_dict + + def set_object_state(self, attr_dict): + for key, value in attr_dict.items(): + if key == "dateval": + value = tuple(value) + if key != "_class": + setattr(self, key, value) + @classmethod def get_schema(cls): """ diff --git a/gramps/gen/lib/event.py b/gramps/gen/lib/event.py index 2fc1980b027..f2428b9b57b 100644 --- a/gramps/gen/lib/event.py +++ b/gramps/gen/lib/event.py @@ -136,6 +136,21 @@ def serialize(self, no_text_date=False): self.private, ) + def get_object_state(self): + attr_dict = super().get_object_state() + attr_dict["type"] = self.__type + attr_dict["description"] = self.__description + return attr_dict + + def set_object_state(self, attr_dict): + if "type" in attr_dict: + self.__type = attr_dict["type"] + del attr_dict["type"] + if "description" in attr_dict: + self.__description = attr_dict["description"] + del attr_dict["description"] + super().set_object_state(attr_dict) + @classmethod def get_schema(cls): """ diff --git a/gramps/gen/lib/eventref.py b/gramps/gen/lib/eventref.py index 655cc6be7aa..d843c2613dc 100644 --- a/gramps/gen/lib/eventref.py +++ b/gramps/gen/lib/eventref.py @@ -86,6 +86,16 @@ def serialize(self): self.__role.serialize(), ) + def get_object_state(self): + attr_dict = super().get_object_state() + attr_dict["role"] = self.__role + return attr_dict + + def set_object_state(self, attr_dict): + self.__role = attr_dict["role"] + del attr_dict["role"] + super().set_object_state(attr_dict) + @classmethod def get_schema(cls): """ diff --git a/gramps/gen/lib/grampstype.py b/gramps/gen/lib/grampstype.py index 8e9d94480b6..881f54f6a99 100644 --- a/gramps/gen/lib/grampstype.py +++ b/gramps/gen/lib/grampstype.py @@ -136,6 +136,19 @@ def __init__(self, value=None): if value is not None: self.set(value) + def get_object_state(self): + attr_dict = {"_class": self.__class__.__name__} + attr_dict["value"] = self.__value + attr_dict["string"] = self.__string + return attr_dict + + def set_object_state(self, attr_dict): + self.__value = attr_dict["value"] + if self.__value == self._CUSTOM: + self.__string = attr_dict["string"] + else: + self.__string = "" + def __set_tuple(self, value): "Set the value/string properties from a tuple." val, strg = self._DEFAULT, "" @@ -225,7 +238,8 @@ def get_schema(cls): "title": _("Type"), "properties": { "_class": {"enum": [cls.__name__]}, - "string": {"type": "string", "title": _("Type")}, + "string": {"type": "string", "title": _("Type String")}, + "value": {"type": "integer", "title": _("Type Value")}, }, } diff --git a/gramps/gen/lib/mediaref.py b/gramps/gen/lib/mediaref.py index 9e52e116080..f6f6bff768d 100644 --- a/gramps/gen/lib/mediaref.py +++ b/gramps/gen/lib/mediaref.py @@ -151,6 +151,12 @@ def unserialize(self, data): RefBase.unserialize(self, ref) return self + def set_object_state(self, attr_dict): + rect = attr_dict["rect"] + if rect is not None: + attr_dict["rect"] = tuple(rect) + super().set_object_state(attr_dict) + def get_text_data_child_list(self): """ Return the list of child objects that may carry textual data. diff --git a/gramps/gen/lib/person.py b/gramps/gen/lib/person.py index 1d59671fe86..f9ebefca744 100644 --- a/gramps/gen/lib/person.py +++ b/gramps/gen/lib/person.py @@ -322,6 +322,17 @@ def unserialize(self, data): TagBase.unserialize(self, tag_list) return self + def get_object_state(self): + attr_dict = super().get_object_state() + attr_dict["gender"] = self.__gender + return attr_dict + + def set_object_state(self, attr_dict): + if "gender" in attr_dict: + self.__gender = attr_dict["gender"] + del attr_dict["gender"] + super().set_object_state(attr_dict) + def _has_handle_reference(self, classname, handle): """ Return True if the object has reference to a given handle of given diff --git a/gramps/gen/lib/serialize.py b/gramps/gen/lib/serialize.py index df0c323bd7a..0ffb98ea473 100644 --- a/gramps/gen/lib/serialize.py +++ b/gramps/gen/lib/serialize.py @@ -37,38 +37,22 @@ import gramps.gen.lib as lib -def __default(obj): - obj_dict = {"_class": obj.__class__.__name__} - if isinstance(obj, lib.GrampsType): - obj_dict["string"] = getattr(obj, "string") - if isinstance(obj, lib.Date): - if obj.is_empty() and not obj.text: - return None - for key, value in obj.__dict__.items(): - if not key.startswith("_"): - obj_dict[key] = value - for key, value in obj.__class__.__dict__.items(): - if isinstance(value, property): - if key != "year": - obj_dict[key] = getattr(obj, key) - return obj_dict - - def __object_hook(obj_dict): obj = getattr(lib, obj_dict["_class"])() - for key, value in obj_dict.items(): - if key != "_class": - if key in ("dateval", "rect") and value is not None: - value = tuple(value) - if key == "ranges": - value = [tuple(item) for item in value] - setattr(obj, key, value) + obj.set_object_state(obj_dict) if obj_dict["_class"] == "Date": if obj.is_empty() and not obj.text: return None return obj +def __default(obj): + if isinstance(obj, lib.Date): + if obj.is_empty() and not obj.text: + return None + return obj.get_object_state() + + def to_json(obj): """ Encode a Gramps object in JSON format. diff --git a/gramps/gen/lib/styledtext.py b/gramps/gen/lib/styledtext.py index 1c793115a16..dfcee6f00aa 100644 --- a/gramps/gen/lib/styledtext.py +++ b/gramps/gen/lib/styledtext.py @@ -102,6 +102,16 @@ def __init__(self, text="", tags=None): else: self._tags = [] + def get_object_state(self): + attr_dict = {"_class": self.__class__.__name__} + attr_dict["tags"] = self._tags + attr_dict["string"] = self._string + return attr_dict + + def set_object_state(self, attr_dict): + self._tags = attr_dict["tags"] + self._string = attr_dict["string"] + # special methods def __str__(self): diff --git a/gramps/gen/lib/styledtexttag.py b/gramps/gen/lib/styledtexttag.py index e1ee33396cc..b3befe9d421 100644 --- a/gramps/gen/lib/styledtexttag.py +++ b/gramps/gen/lib/styledtexttag.py @@ -70,6 +70,18 @@ def __init__(self, name=None, value=None, ranges=None): # Current use of StyledTextTag is such that a shallow copy suffices. self.ranges = ranges + def get_object_state(self): + attr_dict = {"_class": self.__class__.__name__} + attr_dict["name"] = self.name + attr_dict["value"] = self.value + attr_dict["ranges"] = self.ranges + return attr_dict + + def set_object_state(self, attr_dict): + self.name = attr_dict["name"] + self.value = attr_dict["value"] + self.ranges = [tuple(item) for item in attr_dict["ranges"]] + def serialize(self): """Convert the object to a serialized tuple of data. diff --git a/gramps/gen/lib/tag.py b/gramps/gen/lib/tag.py index f6fe87d1e31..012b946d75a 100644 --- a/gramps/gen/lib/tag.py +++ b/gramps/gen/lib/tag.py @@ -108,6 +108,25 @@ def unserialize(self, data): ) = data return self + def get_object_state(self): + attr_dict = super().get_object_state() + attr_dict["name"] = self.__name + attr_dict["color"] = self.__color + attr_dict["priority"] = self.__priority + return attr_dict + + def set_object_state(self, attr_dict): + if "name" in attr_dict: + self.__name = attr_dict["name"] + del attr_dict["name"] + if "color" in attr_dict: + self.__color = attr_dict["color"] + del attr_dict["color"] + if "priority" in attr_dict: + self.__priority = attr_dict["priority"] + del attr_dict["priority"] + super().set_object_state(attr_dict) + @classmethod def get_schema(cls): """