From 4c2464cb4918390d0174577d86a7f504fc3f82b6 Mon Sep 17 00:00:00 2001 From: Nick Hall Date: Fri, 20 Jan 2017 17:53:17 +0000 Subject: [PATCH] Create serialize module --- gramps/gen/lib/serialize.py | 89 +++++++++++++++++++ gramps/gen/lib/styledtext.py | 19 +++- .../{struct_test.py => serialize_test.py} | 28 +++--- po/POTFILES.skip | 1 + 4 files changed, 122 insertions(+), 15 deletions(-) create mode 100644 gramps/gen/lib/serialize.py rename gramps/gen/lib/test/{struct_test.py => serialize_test.py} (82%) diff --git a/gramps/gen/lib/serialize.py b/gramps/gen/lib/serialize.py new file mode 100644 index 000000000..5e4dcea14 --- /dev/null +++ b/gramps/gen/lib/serialize.py @@ -0,0 +1,89 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2017 Nick Hall +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +""" +Serialization utilities for Gramps. +""" + +#------------------------------------------------------------------------ +# +# Python modules +# +#------------------------------------------------------------------------ +import json + +#------------------------------------------------------------------------ +# +# Gramps modules +# +#------------------------------------------------------------------------ +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) + if obj_dict['_class'] == 'Date': + if obj.is_empty() and not obj.text: + return None + return obj + +def to_json(obj): + """ + Encode a Gramps object in JSON format. + + :param obj: The object to be serialized. + :type obj: object + :returns: A JSON string. + :rtype: str + """ + return json.dumps(obj, default=__default) + +def from_json(data): + """ + Decode JSON data into a Gramps object hierarchy. + + :param data: The JSON string to be unserialized. + :type data: str + :returns: A Gramps object. + :rtype: object + """ + return json.loads(data, object_hook=__object_hook) diff --git a/gramps/gen/lib/styledtext.py b/gramps/gen/lib/styledtext.py index 4ec33bee7..fe48d7e20 100644 --- a/gramps/gen/lib/styledtext.py +++ b/gramps/gen/lib/styledtext.py @@ -372,14 +372,29 @@ class StyledText: """ return self._tags + def set_tags(self, tags): + """ + Set the list of formatting tags. + + :param tags: The formatting tags applied on the text. + :type tags: list of 0 or more :py:class:`.StyledTextTag` instances. + """ + self._tags = tags + def get_string(self): """ Accessor for the associated string. """ return self._string - tags = property(get_tags) - string = property(get_string) + def set_string(self, string): + """ + Setter for the associated string. + """ + self._string = string + + tags = property(get_tags, set_tags) + string = property(get_string, set_string) if __name__ == '__main__': from .styledtexttagtype import StyledTextTagType diff --git a/gramps/gen/lib/test/struct_test.py b/gramps/gen/lib/test/serialize_test.py similarity index 82% rename from gramps/gen/lib/test/struct_test.py rename to gramps/gen/lib/test/serialize_test.py index 83db0cf63..aa644b85f 100644 --- a/gramps/gen/lib/test/struct_test.py +++ b/gramps/gen/lib/test/serialize_test.py @@ -18,13 +18,14 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # -""" Unittest for to_struct, from_struct """ +""" Unittest for to_json, from_json """ import unittest import os -from .. import (Person, Family, Event, Source, Place, Citation, - Repository, Media, Note, Tag) +from .. import (Person, Family, Event, Source, Place, Citation, + Repository, Media, Note, Tag) +from ..serialize import to_json, from_json from gramps.gen.db.utils import import_as_dict from gramps.cli.user import User from gramps.gen.const import DATA_DIR @@ -33,14 +34,15 @@ TEST_DIR = os.path.abspath(os.path.join(DATA_DIR, "tests")) EXAMPLE = os.path.join(TEST_DIR, "example.gramps") class BaseCheck: - def test_from_struct(self): - struct = self.object.to_struct() - serialized = self.cls.from_struct(struct) - self.assertEqual(self.object.serialize(), serialized) + def test_from_json(self): + data = to_json(self.object) + obj = from_json(data) + self.assertEqual(self.object.serialize(), obj.serialize()) - def test_from_empty_struct(self): - serialized = self.cls.from_struct({}) - self.assertEqual(self.object.serialize(), serialized) + def test_from_empty_json(self): + data = '{"_class": "%s"}' % self.cls.__name__ + obj = from_json(data) + self.assertEqual(self.object.serialize(), obj.serialize()) class PersonCheck(unittest.TestCase, BaseCheck): def setUp(self): @@ -99,10 +101,10 @@ def generate_case(obj): """ Dynamically generate tests and attach to DatabaseCheck. """ - struct = obj.to_struct() - serialized = obj.__class__.from_struct(struct) + data = to_json(obj) + obj2 = from_json(data) def test(self): - self.assertEqual(obj.serialize(), serialized) + self.assertEqual(obj.serialize(), obj2.serialize()) name = "test_serialize_%s_%s" % (obj.__class__.__name__, obj.handle) setattr(DatabaseCheck, name, test) #### diff --git a/po/POTFILES.skip b/po/POTFILES.skip index 3cd332f29..37ad9abe6 100644 --- a/po/POTFILES.skip +++ b/po/POTFILES.skip @@ -164,6 +164,7 @@ gramps/gen/lib/repo.py gramps/gen/lib/reporef.py gramps/gen/lib/researcher.py gramps/gen/lib/secondaryobj.py +gramps/gen/lib/serialize.py gramps/gen/lib/src.py gramps/gen/lib/srcbase.py gramps/gen/lib/srcref.py