diff --git a/gramps/gen/db/base.py b/gramps/gen/db/base.py index 1e34048a1..b93b2aada 100644 --- a/gramps/gen/db/base.py +++ b/gramps/gen/db/base.py @@ -1419,14 +1419,6 @@ class DbReadBase: """ raise NotImplementedError - def _hash_name(self, table, name): - """ - Used in SQL functions to eval expressions involving selected - data. - """ - name = self.get_table_func(table, "class_func").get_field_alias(name) - return name.replace(".", "__") - class DbWriteBase(DbReadBase): """ diff --git a/gramps/gen/lib/address.py b/gramps/gen/lib/address.py index 89a02ed53..09d5cdc6c 100644 --- a/gramps/gen/lib/address.py +++ b/gramps/gen/lib/address.py @@ -5,6 +5,7 @@ # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2011 Tim G L Lyons # Copyright (C) 2013 Doug Blank +# 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 @@ -80,6 +81,38 @@ class Address(SecondaryObject, PrivacyBase, CitationBase, NoteBase, DateBase, LocationBase.unserialize(self, location) return self + @classmethod + def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ + from .date import Date + return { + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "private": {"type": "boolean"}, + "citation_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "date": {"oneOf": [{"type": "null"}, Date.get_schema()]}, + "street": {"type": "string"}, + "locality": {"type": "string"}, + "city": {"type": "string"}, + "county": {"type": "string"}, + "state": {"type": "string"}, + "country": {"type": "string"}, + "postal": {"type": "string"}, + "phone": {"type": "string"} + } + } + def get_text_data_list(self): """ Return the list of all textual attributes of the object. diff --git a/gramps/gen/lib/attribute.py b/gramps/gen/lib/attribute.py index 39fcd47d1..7ab2a6f12 100644 --- a/gramps/gen/lib/attribute.py +++ b/gramps/gen/lib/attribute.py @@ -4,6 +4,7 @@ # Copyright (C) 2000-2007 Donald N. Allingham # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2011 Tim G L Lyons +# 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 @@ -220,6 +221,30 @@ class Attribute(AttributeRoot, CitationBase, NoteBase): self.type.unserialize(the_type) return self + @classmethod + def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ + return { + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "private": {"type": "boolean"}, + "citation_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "type": AttributeType.get_schema(), + "value": {"type": "string"} + } + } + def get_referenced_handles(self): """ Return the list of (classname, handle) tuples for all directly diff --git a/gramps/gen/lib/childref.py b/gramps/gen/lib/childref.py index 822f9dbfe..2dda97a7a 100644 --- a/gramps/gen/lib/childref.py +++ b/gramps/gen/lib/childref.py @@ -5,6 +5,7 @@ # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2011 Tim G L Lyons # Copyright (C) 2013 Doug Blank +# 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 @@ -36,7 +37,6 @@ from .notebase import NoteBase from .refbase import RefBase from .childreftype import ChildRefType from .const import IDENTICAL, EQUAL, DIFFERENT -from .handle import Handle #------------------------------------------------------------------------- # @@ -90,6 +90,32 @@ class ChildRef(SecondaryObject, PrivacyBase, CitationBase, NoteBase, RefBase): self.mrel.unserialize(mrel) return self + @classmethod + def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ + return { + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "private": {"type": "boolean"}, + "citation_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "ref": {"type": "string", + "maxLength": 50}, + "frel": ChildRefType.get_schema(), + "mrel": ChildRefType.get_schema() + } + } + def get_text_data_list(self): """ Return the list of all textual attributes of the object. diff --git a/gramps/gen/lib/citation.py b/gramps/gen/lib/citation.py index cf48c304a..a6bae4cc9 100644 --- a/gramps/gen/lib/citation.py +++ b/gramps/gen/lib/citation.py @@ -4,6 +4,7 @@ # Copyright (C) 2000-2007 Donald N. Allingham # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2011 Tim G L Lyons +# 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 @@ -43,7 +44,6 @@ from .datebase import DateBase from .tagbase import TagBase from .attrbase import SrcAttributeBase from .citationbase import IndirectCitationBase -from .handle import Handle LOG = logging.getLogger(".citation") @@ -82,23 +82,41 @@ class Citation(MediaBase, NoteBase, SrcAttributeBase, IndirectCitationBase, @classmethod def get_schema(cls): """ - Return the schema as a dictionary for this class. + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict """ from .srcattribute import SrcAttribute + from .mediaref import MediaRef from .date import Date return { - "handle": Handle("Citation", "CITATION-HANDLE"), - "gramps_id": str, - "date": Date, - "page": str, - "confidence": str, - "source_handle": Handle("Source", "SOURCE-HANDLE"), - "note_list": [Handle("Note", "NOTE-HANDLE")], - "media_list": [Handle("Media", "MEDIA-HANDLE")], - "srcattr_list": [SrcAttribute], - "change": int, - "tag_list": [Handle("Tag", "TAG-HANDLE")], - "private": bool, + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "handle": {"type": "string", + "maxLength": 50}, + "gramps_id": {"type": "string"}, + "date": {"oneOf": [{"type": "null"}, Date.get_schema()]}, + "page": {"type": "string"}, + "confidence": {"type": "integer", + "minimum": 0, + "maximum": 4}, + "source_handle": {"type": "string", + "maxLength": 50}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "media_list": {"type": "array", + "items": MediaRef.get_schema()}, + "srcattr_list": {"type": "array", + "items": SrcAttribute.get_schema()}, + "change": {"type": "integer"}, + "tag_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "private": {"type": "boolean"} + } } @classmethod diff --git a/gramps/gen/lib/date.py b/gramps/gen/lib/date.py index 03664d098..d7e9e9892 100644 --- a/gramps/gen/lib/date.py +++ b/gramps/gen/lib/date.py @@ -5,6 +5,7 @@ # Copyright (C) 2009-2013 Douglas S. Blank # Copyright (C) 2013 Paul Franklin # Copyright (C) 2013-2014 Vassilii Khachaturov +# 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 @@ -692,6 +693,29 @@ class Date: raise DateError("Invalid date to unserialize") return self + @classmethod + def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ + return { + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "calendar": {"type": "integer"}, + "modifier": {"type": "integer"}, + "quality": {"type": "integer"}, + "dateval": {"type": "array", + "items": {"type": ["integer", "boolean"]}}, + "text": {"type": "string"}, + "sortval": {"type": "integer"}, + "newyear": {"type": "integer"} + } + } + def copy(self, source): """ Copy all the attributes of the given Date instance to the present diff --git a/gramps/gen/lib/event.py b/gramps/gen/lib/event.py index 5cf4f4295..0dc1d8d5b 100644 --- a/gramps/gen/lib/event.py +++ b/gramps/gen/lib/event.py @@ -4,6 +4,7 @@ # Copyright (C) 2000-2007 Donald N. Allingham # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2011 Tim G L Lyons +# 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 @@ -45,7 +46,6 @@ from .datebase import DateBase from .placebase import PlaceBase from .tagbase import TagBase from .eventtype import EventType -from .handle import Handle LOG = logging.getLogger(".citation") @@ -121,28 +121,42 @@ class Event(CitationBase, NoteBase, MediaBase, AttributeBase, @classmethod def get_schema(cls): """ - Return the schema as a dictionary for this class. + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict """ from .attribute import Attribute - from .citation import Citation - from .note import Note from .date import Date - from .tag import Tag - from .media import Media + from .mediaref import MediaRef return { - "handle": Handle("Event", "EVENT-HANDLE"), - "gramps_id": str, - "type": EventType, - "date": Date, - "description": str, - "place": Handle("Place", "PLACE-HANDLE"), - "citation_list": [Citation], - "note_list": [Note], - "media_list": [Media], - "attribute_list": [Attribute], - "change": int, - "tag_list": [Tag], - "private": bool, + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "handle": {"type": "string", + "maxLength": 50}, + "gramps_id": {"type": "string"}, + "type": EventType.get_schema(), + "date": {"oneOf": [{"type": "null"}, Date.get_schema()]}, + "description": {"type": "string"}, + "place": {"type": ["string", "null"], + "maxLength": 50}, + "citation_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "media_list": {"type": "array", + "items": MediaRef.get_schema()}, + "attribute_list": {"type": "array", + "items": Attribute.get_schema()}, + "change": {"type": "integer"}, + "tag_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "private": {"type": "boolean"}, + } } @classmethod diff --git a/gramps/gen/lib/eventref.py b/gramps/gen/lib/eventref.py index 49af525fb..b64cf63eb 100644 --- a/gramps/gen/lib/eventref.py +++ b/gramps/gen/lib/eventref.py @@ -5,6 +5,7 @@ # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2011 Tim G L Lyons # Copyright (C) 2013 Doug Blank +# 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 @@ -38,7 +39,6 @@ from .refbase import RefBase from .eventroletype import EventRoleType from .const import IDENTICAL, EQUAL, DIFFERENT from .citationbase import IndirectCitationBase -from .handle import Handle #------------------------------------------------------------------------- # @@ -82,18 +82,26 @@ class EventRef(PrivacyBase, NoteBase, AttributeBase, RefBase, @classmethod def get_schema(cls): """ - Returns the schema for EventRef. + Returns the JSON Schema for this class. - :returns: Returns a dict containing the fields to types. + :returns: Returns a dict containing the schema. :rtype: dict """ from .attribute import Attribute return { - "private": bool, - "note_list": [Handle("Note", "NOTE-HANDLE")], - "attribute_list": [Attribute], - "ref": Handle("Event", "EVENT-HANDLE"), - "role": EventRoleType, + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "private": {"type": "boolean"}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "attribute_list": {"type": "array", + "items": Attribute.get_schema()}, + "ref": {"type": "string", + "maxLength": 50}, + "role": EventRoleType.get_schema(), + } } @classmethod diff --git a/gramps/gen/lib/family.py b/gramps/gen/lib/family.py index d6236b584..29158a7ba 100644 --- a/gramps/gen/lib/family.py +++ b/gramps/gen/lib/family.py @@ -3,7 +3,7 @@ # # Copyright (C) 2000-2007 Donald N. Allingham # Copyright (C) 2010 Michiel D. Nauta -# Copyright (C) 2010 Nick Hall +# Copyright (C) 2010,2017 Nick Hall # Copyright (C) 2011 Tim G L Lyons # # This program is free software; you can redistribute it and/or modify @@ -49,7 +49,6 @@ from .tagbase import TagBase from .childref import ChildRef from .familyreltype import FamilyRelType from .const import IDENTICAL, EQUAL, DIFFERENT -from .handle import Handle LOG = logging.getLogger(".citation") @@ -129,26 +128,50 @@ class Family(CitationBase, NoteBase, MediaBase, AttributeBase, LdsOrdBase, @classmethod def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ from .mediaref import MediaRef from .ldsord import LdsOrd from .childref import ChildRef from .attribute import Attribute return { - "handle": Handle("Family", "FAMILY-HANDLE"), - "gramps_id": str, - "father_handle": Handle("Person", "PERSON-HANDLE"), - "mother_handle": Handle("Person", "PERSON-HANDLE"), - "child_ref_list": [ChildRef], - "type": FamilyRelType, - "event_ref_list": [EventRef], - "media_list": [MediaRef], - "attribute_list": [Attribute], - "lds_ord_list": [LdsOrd], - "citation_list": [Handle("Citation", "CITATION-HANDLE")], - "note_list": [Handle("Note", "NOTE-HANDLE")], - "change": int, - "tag_list": [Handle("Tag", "TAG-HANDLE")], - "private": bool + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "handle": {"type": "string", + "maxLength": 50}, + "gramps_id": {"type": "string"}, + "father_handle": {"type": ["string", "null"], + "maxLength": 50}, + "mother_handle": {"type": ["string", "null"], + "maxLength": 50}, + "child_ref_list": {"type": "array", + "items": ChildRef.get_schema()}, + "type": FamilyRelType.get_schema(), + "event_ref_list": {"type": "array", + "items": EventRef.get_schema()}, + "media_list": {"type": "array", + "items": MediaRef.get_schema()}, + "attribute_list": {"type": "array", + "items": Attribute.get_schema()}, + "lds_ord_list": {"type": "array", + "items": LdsOrd.get_schema()}, + "citation_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "change": {"type": "integer"}, + "tag_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "private": {"type": "boolean"} + } } @classmethod diff --git a/gramps/gen/lib/grampstype.py b/gramps/gen/lib/grampstype.py index 3042affea..a6dd7b721 100644 --- a/gramps/gen/lib/grampstype.py +++ b/gramps/gen/lib/grampstype.py @@ -2,6 +2,7 @@ # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2000-2007 Donald N. Allingham +# 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 @@ -207,6 +208,22 @@ class GrampsType(object, metaclass=GrampsTypeMeta): """Convert the object to a serialized tuple of data. """ return (self.__value, self.__string) + @classmethod + def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ + return { + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "string": {"type": "string"}, + } + } + @classmethod def get_labels(cls, _): return { diff --git a/gramps/gen/lib/ldsord.py b/gramps/gen/lib/ldsord.py index c9cef5efe..18036d2f9 100644 --- a/gramps/gen/lib/ldsord.py +++ b/gramps/gen/lib/ldsord.py @@ -5,6 +5,7 @@ # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2011 Tim G L Lyons # Copyright (C) 2013 Doug Blank +# 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 @@ -155,6 +156,35 @@ class LdsOrd(SecondaryObject, CitationBase, NoteBase, DateBase.unserialize(self, date) return self + @classmethod + def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ + from .date import Date + return { + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "citation_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "date": {"oneOf": [{"type": "null"}, Date.get_schema()]}, + "type": {"type": "integer"}, + "place": {"type": "string"}, + "famc": {"type": ["null", "string"]}, + "temple": {"type": "string"}, + "status": {"type": "integer"}, + "private": {"type": "boolean"} + } + } + def get_text_data_list(self): """ Return the list of all textual attributes of the object. diff --git a/gramps/gen/lib/location.py b/gramps/gen/lib/location.py index dd5d7f6a8..841f589dd 100644 --- a/gramps/gen/lib/location.py +++ b/gramps/gen/lib/location.py @@ -4,6 +4,7 @@ # Copyright (C) 2000-2006 Donald N. Allingham # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2013 Doug Blank +# 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 @@ -71,6 +72,30 @@ class Location(SecondaryObject, LocationBase): LocationBase.unserialize(self, lbase) return self + @classmethod + def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ + return { + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "street": {"type": "string"}, + "locality": {"type": "string"}, + "city": {"type": "string"}, + "county": {"type": "string"}, + "state": {"type": "string"}, + "country": {"type": "string"}, + "postal": {"type": "string"}, + "phone": {"type": "string"}, + "parish": {"type": "string"} + } + } + def get_text_data_list(self): """ Return the list of all textual attributes of the object. diff --git a/gramps/gen/lib/media.py b/gramps/gen/lib/media.py index 4c15e57c2..e2c1dffc5 100644 --- a/gramps/gen/lib/media.py +++ b/gramps/gen/lib/media.py @@ -3,7 +3,7 @@ # # Copyright (C) 2000-2007 Donald N. Allingham # Copyright (C) 2010 Michiel D. Nauta -# Copyright (C) 2010 Nick Hall +# Copyright (C) 2010,2017 Nick Hall # Copyright (C) 2011 Tim G L Lyons # # This program is free software; you can redistribute it and/or modify @@ -45,7 +45,6 @@ from .notebase import NoteBase from .datebase import DateBase from .attrbase import AttributeBase from .tagbase import TagBase -from .handle import Handle LOG = logging.getLogger(".citation") @@ -121,27 +120,38 @@ class Media(CitationBase, NoteBase, DateBase, AttributeBase, @classmethod def get_schema(cls): """ - Returns the schema for EventRef. + Returns the JSON Schema for this class. - :returns: Returns a dict containing the fields to types. + :returns: Returns a dict containing the schema. :rtype: dict """ from .attribute import Attribute from .date import Date return { - "handle": Handle("Media", "MEDIA-HANDLE"), - "gramps_id": str, - "path": str, - "mime": str, - "desc": str, - "checksum": str, - "attribute_list": [Attribute], - "citation_list": [Handle("Citation", "CITATION-HANDLE")], - "note_list": [Handle("Note", "NOTE-HANDLE")], - "change": int, - "date": Date, - "tag_list": [Handle("Tag", "TAG-HANDLE")], - "private": bool, + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "handle": {"type": "string", + "maxLength": 50}, + "gramps_id": {"type": "string"}, + "path": {"type": "string"}, + "mime": {"type": "string"}, + "desc": {"type": "string"}, + "checksum": {"type": "string"}, + "attribute_list": {"type": "array", + "items": Attribute.get_schema()}, + "citation_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "note_list": {"type": "array", + "items": {"type": "string"}}, + "change": {"type": "integer"}, + "date": {"oneOf": [{"type": "null"}, Date.get_schema()]}, + "tag_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "private": {"type": "boolean"} + } } @classmethod diff --git a/gramps/gen/lib/mediaref.py b/gramps/gen/lib/mediaref.py index b87df5e2e..c908c5abb 100644 --- a/gramps/gen/lib/mediaref.py +++ b/gramps/gen/lib/mediaref.py @@ -5,6 +5,7 @@ # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2011 Tim G L Lyons # Copyright (C) 2013 Doug Blank +# 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 @@ -37,7 +38,6 @@ from .notebase import NoteBase from .refbase import RefBase from .attrbase import AttributeBase from .const import IDENTICAL, EQUAL, DIFFERENT -from .handle import Handle #------------------------------------------------------------------------- # @@ -73,21 +73,33 @@ class MediaRef(SecondaryObject, PrivacyBase, CitationBase, NoteBase, RefBase, @classmethod def get_schema(cls): """ - Returns the schema for MediaRef. + Returns the JSON Schema for this class. - :returns: Returns a dict containing the fields to types. + :returns: Returns a dict containing the schema. :rtype: dict """ from .attribute import Attribute - from .citation import Citation - from .note import Note return { - "private": bool, - "citation_list": [Citation], - "note_list": [Note], - "attribute_list": [Attribute], - "ref": Handle("Media", "MEDIA-HANDLE"), - "rect": tuple, # or None if (0,0,0,0) + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "private": {"type": "boolean"}, + "citation_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "attribute_list": {"type": "array", + "items": Attribute.get_schema()}, + "ref": {"type": "string", + "maxLength": 50}, + "rect": {"oneOf": [{"type": "null"}, + {"type": "array", + "items": {"type": "integer"}, + "minItems": 4, + "maxItems": 4}]} + } } def unserialize(self, data): diff --git a/gramps/gen/lib/name.py b/gramps/gen/lib/name.py index 91de6c856..e89421320 100644 --- a/gramps/gen/lib/name.py +++ b/gramps/gen/lib/name.py @@ -5,6 +5,7 @@ # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2011 Tim G L Lyons # Copyright (C) 2013 Doug Blank +# 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 @@ -37,7 +38,6 @@ from .notebase import NoteBase from .datebase import DateBase from .surnamebase import SurnameBase from .nametype import NameType -from .handle import Handle from .const import IDENTICAL, EQUAL, DIFFERENT from .date import Date from gramps.gen.const import GRAMPS_LOCALE as glocale @@ -152,23 +152,38 @@ class Name(SecondaryObject, PrivacyBase, SurnameBase, CitationBase, NoteBase, @classmethod def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ from .surname import Surname return { - "private": bool, - "citation_list": [Handle("Citation", "CITATION-HANDLE")], - "note_list": [Handle("Note", "NOTE-HANDLE")], - "date": Date, - "first_name": str, - "surname_list": [Surname], - "suffix": str, - "title": str, - "type": NameType, - "group_as": str, - "sort_as": str, - "display_as": str, - "call": str, - "nick": str, - "famnick": str, + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "private": {"type": "boolean"}, + "citation_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "date": {"oneOf": [{"type": "null"}, Date.get_schema()]}, + "first_name": {"type": "string"}, + "surname_list": {"type": "array", + "items": Surname.get_schema()}, + "suffix": {"type": "string"}, + "title": {"type": "string"}, + "type": NameType.get_schema(), + "group_as": {"type": "string"}, + "sort_as": {"type": "integer"}, + "display_as": {"type": "integer"}, + "call": {"type": "string"}, + "nick": {"type": "string"}, + "famnick": {"type": "string"} + } } def is_empty(self): diff --git a/gramps/gen/lib/note.py b/gramps/gen/lib/note.py index c7e02334c..d7e19420e 100644 --- a/gramps/gen/lib/note.py +++ b/gramps/gen/lib/note.py @@ -3,7 +3,7 @@ # # Copyright (C) 2000-2007 Donald N. Allingham # Copyright (C) 2010 Michiel D. Nauta -# Copyright (C) 2010 Nick Hall +# Copyright (C) 2010,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 @@ -34,7 +34,6 @@ from .tagbase import TagBase from .notetype import NoteType from .styledtext import StyledText from .styledtexttagtype import StyledTextTagType -from .handle import Handle #------------------------------------------------------------------------- # @@ -98,17 +97,27 @@ class Note(BasicPrimaryObject): @classmethod def get_schema(cls): """ - The schema for Note. + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict """ return { - "handle": Handle("Note", "NOTE-HANDLE"), - "gramps_id": str, - "text": StyledText, - "format": int, - "type": NoteType, - "change": int, - "tag_list": [Handle("Tag", "TAG-HANDLE")], - "private": bool, + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "handle": {"type": "string", + "maxLength": 50}, + "gramps_id": {"type": "string"}, + "text": StyledText.get_schema(), + "format": {"type": "integer"}, + "type": NoteType.get_schema(), + "change": {"type": "integer"}, + "tag_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "private": {"type": "boolean"} + } } @classmethod diff --git a/gramps/gen/lib/person.py b/gramps/gen/lib/person.py index c79227e91..693fd3775 100644 --- a/gramps/gen/lib/person.py +++ b/gramps/gen/lib/person.py @@ -3,7 +3,7 @@ # # Copyright (C) 2000-2007 Donald N. Allingham # Copyright (C) 2010 Michiel D. Nauta -# Copyright (C) 2010 Nick Hall +# Copyright (C) 2010,2017 Nick Hall # Copyright (C) 2011 Tim G L Lyons # # This program is free software; you can redistribute it and/or modify @@ -46,7 +46,6 @@ from .attrtype import AttributeType from .eventroletype import EventRoleType from .attribute import Attribute from .const import IDENTICAL, EQUAL, DIFFERENT -from .handle import Handle from ..const import GRAMPS_LOCALE as glocale _ = glocale.translation.gettext @@ -187,34 +186,62 @@ class Person(CitationBase, NoteBase, AttributeBase, MediaBase, @classmethod def get_schema(cls): """ - Return the schema as a dictionary for this class. + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict """ from .mediaref import MediaRef from .address import Address from .url import Url from .ldsord import LdsOrd return { - "handle": Handle("Person", "PERSON-HANDLE"), - "gramps_id": str, - "gender": int, - "primary_name": Name, - "alternate_names": [Name], - "death_ref_index": int, - "birth_ref_index": int, - "event_ref_list": [EventRef], - "family_list": [Handle("Family", "FAMILY-HANDLE")], - "parent_family_list": [Handle("Family", "FAMILY-HANDLE")], - "media_list": [MediaRef], - "address_list": [Address], - "attribute_list": [Attribute], - "urls": [Url], - "lds_ord_list": [LdsOrd], - "citation_list": [Handle("Citation", "CITATION-HANDLE")], - "note_list": [Handle("Note", "NOTE-HANDLE")], - "change": int, - "tag_list": [Handle("Tag", "TAG-HANDLE")], - "private": bool, - "person_ref_list": [PersonRef] + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "handle": {"type": "string", + "maxLength": 50}, + "gramps_id": {"type": "string"}, + "gender": {"type": "integer", + "minimum": 0, + "maximum": 2}, + "primary_name": Name.get_schema(), + "alternate_names": {"type": "array", + "items": Name.get_schema()}, + "death_ref_index": {"type": "integer"}, + "birth_ref_index": {"type": "integer"}, + "event_ref_list": {"type": "array", + "items": EventRef.get_schema()}, + "family_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "parent_family_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "media_list": {"type": "array", + "items": MediaRef.get_schema()}, + "address_list": {"type": "array", + "items": Address.get_schema()}, + "attribute_list": {"type": "array", + "items": Attribute.get_schema()}, + "urls": {"type": "array", + "items": Url.get_schema()}, + "lds_ord_list": {"type": "array", + "items": LdsOrd.get_schema()}, + "citation_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "change": {"type": "integer"}, + "tag_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "private": {"type": "boolean"}, + "person_ref_list": {"type": "array", + "items": PersonRef.get_schema()} + } } def unserialize(self, data): diff --git a/gramps/gen/lib/personref.py b/gramps/gen/lib/personref.py index 78506585c..a64150d0a 100644 --- a/gramps/gen/lib/personref.py +++ b/gramps/gen/lib/personref.py @@ -5,6 +5,7 @@ # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2011 Tim G L Lyons # Copyright (C) 2013 Doug Blank +# 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 @@ -36,7 +37,6 @@ from .citationbase import CitationBase from .notebase import NoteBase from .refbase import RefBase from .const import IDENTICAL, EQUAL, DIFFERENT -from .handle import Handle #------------------------------------------------------------------------- # @@ -83,6 +83,31 @@ class PersonRef(SecondaryObject, PrivacyBase, CitationBase, NoteBase, RefBase): RefBase.unserialize(self, ref) return self + @classmethod + def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ + return { + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "private": {"type": "boolean"}, + "citation_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "ref": {"type": "string", + "maxLength": 50}, + "rel": {"type": "string"} + } + } + def get_text_data_list(self): """ Return the list of all textual attributes of the object. diff --git a/gramps/gen/lib/place.py b/gramps/gen/lib/place.py index 6ce434ad7..a6301cc03 100644 --- a/gramps/gen/lib/place.py +++ b/gramps/gen/lib/place.py @@ -5,6 +5,7 @@ # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2011 Tim G L Lyons # Copyright (C) 2013 Doug Blank +# 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 @@ -40,7 +41,6 @@ from .mediabase import MediaBase from .urlbase import UrlBase from .tagbase import TagBase from .location import Location -from .handle import Handle #------------------------------------------------------------------------- # @@ -142,28 +142,48 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject): @classmethod def get_schema(cls): """ - Return the schema as a dictionary for this class. + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict """ from .url import Url + from .mediaref import MediaRef return { - "handle": Handle("Place", "PLACE-HANDLE"), - "gramps_id": str, - "title": str, - "long": str, - "lat": str, - "placeref_list": [PlaceRef], - "name": PlaceName, - "alt_names": [PlaceName], - "place_type": PlaceType, - "code": str, - "alt_loc": [Location], - "urls": [Url], - "media_list": [Handle("Media", "MEDIA-HANDLE")], - "citation_list": [Handle("Citation", "CITATION-HANDLE")], - "note_list": [Handle("Note", "NOTE-HANDLE")], - "change": int, - "tag_list": [Handle("Tag", "TAG-HANDLE")], - "private": bool + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "handle": {"type": "string", + "maxLength": 50}, + "gramps_id": {"type": "string"}, + "title": {"type": "string"}, + "long": {"type": "string"}, + "lat": {"type": "string"}, + "placeref_list": {"type": "array", + "items": PlaceRef.get_schema()}, + "name": PlaceName.get_schema(), + "alt_names": {"type": "array", + "items": PlaceName.get_schema()}, + "place_type": PlaceType.get_schema(), + "code": {"type": "string"}, + "alt_loc": {"type": "array", + "items": Location.get_schema()}, + "urls": {"type": "array", + "items": Url.get_schema()}, + "media_list": {"type": "array", + "items": MediaRef.get_schema()}, + "citation_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "change": {"type": "integer"}, + "tag_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "private": {"type": "boolean"} + } } def unserialize(self, data): diff --git a/gramps/gen/lib/placename.py b/gramps/gen/lib/placename.py index 80d6fb731..3a97fcecb 100644 --- a/gramps/gen/lib/placename.py +++ b/gramps/gen/lib/placename.py @@ -2,7 +2,7 @@ # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2000-2007 Donald N. Allingham -# Copyright (C) 2015 Nick Hall +# Copyright (C) 2015,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 @@ -79,6 +79,25 @@ class PlaceName(SecondaryObject, DateBase): DateBase.unserialize(self, date) return self + @classmethod + def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ + from .date import Date + return { + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "value": {"type": "string"}, + "date": {"oneOf": [{"type": "null"}, Date.get_schema()]}, + "lang": {"type": "string"} + } + } + def get_text_data_list(self): """ Return the list of all textual attributes of the object. diff --git a/gramps/gen/lib/placeref.py b/gramps/gen/lib/placeref.py index c5f1b0970..673657688 100644 --- a/gramps/gen/lib/placeref.py +++ b/gramps/gen/lib/placeref.py @@ -2,7 +2,7 @@ # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2000-2007 Donald N. Allingham -# Copyright (C) 2013 Nick Hall +# Copyright (C) 2013,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 @@ -32,7 +32,6 @@ from .secondaryobj import SecondaryObject from .refbase import RefBase from .datebase import DateBase from .const import IDENTICAL, EQUAL, DIFFERENT -from .handle import Handle #------------------------------------------------------------------------- # @@ -72,6 +71,25 @@ class PlaceRef(RefBase, DateBase, SecondaryObject): DateBase.unserialize(self, date) return self + @classmethod + def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ + from .date import Date + return { + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "ref": {"type": "string", + "maxLength": 50}, + "date": {"oneOf": [{"type": "null"}, Date.get_schema()]} + } + } + def get_text_data_list(self): """ Return the list of all textual attributes of the object. diff --git a/gramps/gen/lib/repo.py b/gramps/gen/lib/repo.py index bd94a8436..487b995f8 100644 --- a/gramps/gen/lib/repo.py +++ b/gramps/gen/lib/repo.py @@ -4,6 +4,7 @@ # Copyright (C) 2000-2007 Donald N. Allingham # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2011 Tim G L Lyons +# 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 @@ -35,7 +36,6 @@ from .addressbase import AddressBase from .urlbase import UrlBase from .tagbase import TagBase from .repotype import RepositoryType -from .handle import Handle from .citationbase import IndirectCitationBase #------------------------------------------------------------------------- @@ -87,21 +87,35 @@ class Repository(NoteBase, AddressBase, UrlBase, IndirectCitationBase, @classmethod def get_schema(cls): """ - Return the schema as a dictionary for this class. + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict """ from .address import Address from .url import Url return { - "handle": Handle("Repository", "REPOSITORY-HANDLE"), - "gramps_id": str, - "type": RepositoryType, - "name": str, - "note_list": [Handle("Note", "NOTE-HANDLE")], - "address_list": [Address], - "urls": [Url], - "change": int, - "tag_list": [Handle("Tag", "TAG-HANDLE")], - "private": bool + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "handle": {"type": "string", + "maxLength": 50}, + "gramps_id": {"type": "string"}, + "type": RepositoryType.get_schema(), + "name": {"type": "string"}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "address_list": {"type": "array", + "items": Address.get_schema()}, + "urls": {"type": "array", + "items": Url.get_schema()}, + "change": {"type": "integer"}, + "tag_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "private": {"type": "boolean"} + } } def unserialize(self, data): diff --git a/gramps/gen/lib/reporef.py b/gramps/gen/lib/reporef.py index fe9717c4f..e281b9ea9 100644 --- a/gramps/gen/lib/reporef.py +++ b/gramps/gen/lib/reporef.py @@ -4,6 +4,7 @@ # Copyright (C) 2000-2007 Donald N. Allingham # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2013 Doug Blank +# 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 @@ -35,7 +36,6 @@ from .notebase import NoteBase from .refbase import RefBase from .srcmediatype import SourceMediaType from .const import IDENTICAL, EQUAL, DIFFERENT -from .handle import Handle #------------------------------------------------------------------------- # @@ -81,6 +81,29 @@ class RepoRef(SecondaryObject, PrivacyBase, NoteBase, RefBase): RefBase.unserialize(self, ref) return self + @classmethod + def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ + return { + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "ref": {"type": "string", + "maxLength": 50}, + "call_number": {"type": "string"}, + "media_type": SourceMediaType.get_schema(), + "private": {"type": "boolean"} + } + } + def get_text_data_list(self): """ Return the list of all textual attributes of the object. diff --git a/gramps/gen/lib/src.py b/gramps/gen/lib/src.py index 6cb988a62..193a69ce9 100644 --- a/gramps/gen/lib/src.py +++ b/gramps/gen/lib/src.py @@ -5,6 +5,7 @@ # Copyright (C) 2010 Michiel D. Nauta # Copyright (C) 2011 Tim G L Lyons # Copyright (C) 2013 Doug Blank +# 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 @@ -37,7 +38,6 @@ from .tagbase import TagBase from .attrbase import SrcAttributeBase from .reporef import RepoRef from .const import DIFFERENT, EQUAL, IDENTICAL -from .handle import Handle from .citationbase import IndirectCitationBase #------------------------------------------------------------------------- @@ -100,25 +100,40 @@ class Source(MediaBase, NoteBase, SrcAttributeBase, IndirectCitationBase, @classmethod def get_schema(cls): """ - Return the schema as a dictionary for this class. + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict """ from .srcattribute import SrcAttribute from .reporef import RepoRef - from .url import Url + from .mediaref import MediaRef return { - "handle": Handle("Source", "SOURCE-HANDLE"), - "gramps_id": str, - "title": str, - "author": str, - "pubinfo": str, - "note_list": [Handle("Note", "NOTE-HANDLE")], - "media_list": [Handle("Media", "MEDIA-HANDLE")], - "abbrev": str, - "change": int, - "srcattr_list": [SrcAttribute], - "reporef_list": [RepoRef], - "tag_list": [Handle("Tag", "")], - "private": bool + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "handle": {"type": "string", + "maxLength": 50}, + "gramps_id": {"type": "string"}, + "title": {"type": "string"}, + "author": {"type": "string"}, + "pubinfo": {"type": "string"}, + "note_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "media_list": {"type": "array", + "items": MediaRef.get_schema()}, + "abbrev": {"type": "string"}, + "change": {"type": "integer"}, + "srcattr_list": {"type": "array", + "items": SrcAttribute.get_schema()}, + "reporef_list": {"type": "array", + "items": RepoRef.get_schema()}, + "tag_list": {"type": "array", + "items": {"type": "string", + "maxLength": 50}}, + "private": {"type": "boolean"} + } } def unserialize(self, data): diff --git a/gramps/gen/lib/srcattribute.py b/gramps/gen/lib/srcattribute.py index a30c6c727..728a226b3 100644 --- a/gramps/gen/lib/srcattribute.py +++ b/gramps/gen/lib/srcattribute.py @@ -2,6 +2,7 @@ # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2013 Benny Malengier +# 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 @@ -53,3 +54,21 @@ class SrcAttribute(AttributeRoot): else: self.type = SrcAttributeType() self.value = "" + + @classmethod + def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ + return { + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "private": {"type": "boolean"}, + "type": SrcAttributeType.get_schema(), + "value": {"type": "string"} + } + } diff --git a/gramps/gen/lib/styledtext.py b/gramps/gen/lib/styledtext.py index fed0a5474..5d57611a4 100644 --- a/gramps/gen/lib/styledtext.py +++ b/gramps/gen/lib/styledtext.py @@ -3,6 +3,7 @@ # # Copyright (C) 2008 Zsolt Foldvari # Copyright (C) 2013 Doug Blank +# 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 @@ -291,11 +292,19 @@ class StyledText: @classmethod def get_schema(cls): """ - The schema for StyledText. + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict """ return { - "string": str, - "tags": [StyledTextTag], + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "string": {"type": "string"}, + "tags": {"type": "array", + "items": StyledTextTag.get_schema()} + } } @classmethod diff --git a/gramps/gen/lib/styledtexttag.py b/gramps/gen/lib/styledtexttag.py index f6dfc73d7..dee7a38e1 100644 --- a/gramps/gen/lib/styledtexttag.py +++ b/gramps/gen/lib/styledtexttag.py @@ -3,6 +3,7 @@ # # Copyright (C) 2008 Zsolt Foldvari # Copyright (C) 2013 Doug Blank +# 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 @@ -84,3 +85,25 @@ class StyledTextTag: self.name = StyledTextTagType() self.name.unserialize(the_name) return self + + @classmethod + def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ + return { + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "name": StyledTextTagType.get_schema(), + "value": {"type": ["null", "string", "integer"]}, + "ranges": {"type": "array", + "items": {"type": "array", + "items": {"type": "integer"}, + "minItems": 2, + "maxItems": 2}} + } + } diff --git a/gramps/gen/lib/surname.py b/gramps/gen/lib/surname.py index 22ddeda26..fe7c99592 100644 --- a/gramps/gen/lib/surname.py +++ b/gramps/gen/lib/surname.py @@ -3,6 +3,7 @@ # # Copyright (C) 2010 Benny Malengier # Copyright (C) 2013 Doug Blank +# 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 @@ -73,12 +74,22 @@ class Surname(SecondaryObject): @classmethod def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ return { - "surname": str, - "prefix": str, - "primary": str, - "origintype": NameOriginType, - "connector": str + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "surname": {"type": "string"}, + "prefix": {"type": "string"}, + "primary": {"type": "boolean"}, + "origintype": NameOriginType.get_schema(), + "connector": {"type": "string"} + } } @classmethod diff --git a/gramps/gen/lib/tableobj.py b/gramps/gen/lib/tableobj.py index 9332fc0f1..7927ff00d 100644 --- a/gramps/gen/lib/tableobj.py +++ b/gramps/gen/lib/tableobj.py @@ -1,7 +1,7 @@ # # Gramps - a GTK+/GNOME based genealogy program # -# Copyright (C) 2010 Nick Hall +# Copyright (C) 2010,2017 Nick Hall # Copyright (C) 2013 Doug Blank # # This program is free software; you can redistribute it and/or modify @@ -155,21 +155,6 @@ class TableObject(BaseObject): """ return {} - @classmethod - def field_aliases(cls): - """ - Return dictionary of alias to full field names - for this object class. - """ - return {} - - @classmethod - def get_field_alias(cls, alias): - """ - Return full field name for an alias, if one. - """ - return cls.field_aliases().get(alias, alias) - @classmethod def get_schema(cls): """ @@ -177,219 +162,21 @@ class TableObject(BaseObject): """ return {} - @classmethod - def get_extra_secondary_fields(cls): - """ - Return a list of full field names and types for secondary - fields that are not directly listed in the schema. - """ - return [] - - @classmethod - def get_index_fields(cls): - """ - Return a list of full field names for indices. - """ - return [] - @classmethod def get_secondary_fields(cls): """ - Return all seconday fields and their types + Return all secondary fields and their types """ - from .handle import HandleClass - return ([(key.lower(), value) - for (key, value) in cls.get_schema().items() - if value in [str, int, float, bool] or - isinstance(value, HandleClass)] + - cls.get_extra_secondary_fields()) - - @classmethod - def get_label(cls, field, _): - """ - Get the associated label given a field name of this object. - No index positions allowed on lists. - """ - chain = field.split(".") - path = cls._follow_schema_path(chain[:-1]) - labels = path.get_labels(_) - if chain[-1] in labels: - return labels[chain[-1]] - else: - raise Exception("%s has no such label on %s: '%s'" % - (cls, path, field)) - - @classmethod - def get_field_type(cls, field): - """ - Get the associated label given a field name of this object. - No index positions allowed on lists. - """ - field = cls.get_field_alias(field) - chain = field.split(".") - ftype = cls._follow_schema_path(chain) - return ftype - - @classmethod - def _follow_schema_path(cls, chain): - """ - Follow a list of schema items. Return endpoint. - """ - path = cls - for part in chain: - schema = path.get_schema() - if part.isdigit(): - pass # skip over - elif part in schema.keys(): - path = schema[part] - else: - raise Exception("No such field. Valid fields are: %s" % list(schema.keys())) - if isinstance(path, (list, tuple)): - path = path[0] - return path - - def get_field(self, field, db=None, ignore_errors=False): - """ - Get the value of a field. - """ - field = self.__class__.get_field_alias(field) - chain = field.split(".") - path = self._follow_field_path(chain, db, ignore_errors) - return path - - def _follow_field_path(self, chain, db=None, ignore_errors=False): - """ - Follow a list of items. Return endpoint(s) only. - With the db argument, can do joins across tables. - self - current object - returns - None, endpoint, of recursive list of endpoints - """ - from .handle import HandleClass - # start with [self, self, chain, path_to=[]] - # results = [] - # expand when you reach multiple answers [obj, chain_left, []] - # if you get to an endpoint, put results - # go until nothing left to expand - todo = [(self, self, [], chain)] - results = [] - while todo: - parent, current, path_to, chain = todo.pop() - #print("expand:", parent.__class__.__name__, - # current.__class__.__name__, - # path_to, - # chain) - keep_going = True - p = 0 - while p < len(chain) and keep_going: - #print("while:", path_to, chain[p:]) - part = chain[p] - if hasattr(current, part): # attribute - current = getattr(current, part) - path_to.append(part) - # need to consider current+part if current is list: - elif isinstance(current, (list, tuple)): - if part.isdigit(): - # followed by index, so continue here - if int(part) < len(current): - current = current[int(part)] - path_to.append(part) - elif ignore_errors: - current = None - keeping_going = False - else: - raise Exception("invalid index position") - else: # else branch! in middle, split paths - for i in range(len(current)): - #print("split list:", self.__class__.__name__, - # current.__class__.__name__, - # path_to[:], - # [str(i)] + chain[p:]) - todo.append([self, current, path_to[:], [str(i)] + chain[p:]]) - current = None - keep_going = False - else: # part not found on this self - # current is a handle - # part is something on joined object - if parent: - ptype = parent.__class__.get_field_type(".".join(path_to)) - if isinstance(ptype, HandleClass): - if db: - # start over here: - obj = None - if current: - try: - obj = ptype.join(db, current) - except HandleError: - if ignore_errors: - obj = None - else: - raise - if part == "self": - current = obj - path_to = [] - #print("split self:", obj.__class__.__name__, - # current.__class__.__name__, - # path_to, - # chain[p + 1:]) - todo.append([obj, current, path_to, chain[p + 1:]]) - elif obj: - current = getattr(obj, part) - #print("split :", obj.__class__.__name__, - # current.__class__.__name__, - # [part], - # chain[p + 1:]) - todo.append([obj, current, [part], chain[p + 1:]]) - current = None - keep_going = False - else: - raise Exception("Can't join without database") - elif part == "self": - pass - elif ignore_errors: - pass - else: - raise Exception("%s is not a valid field of %s; use %s" % - (part, current, dir(current))) - current = None - keep_going = False - p += 1 - if keep_going: - results.append(current) - if len(results) == 1: - return results[0] - elif len(results) == 0: - return None - else: - return results - - def set_field(self, field, value, db=None, ignore_errors=False): - """ - Set the value of a basic field (str, int, float, or bool). - value can be a string or actual value. - Returns number of items changed. - """ - field = self.__class__.get_field_alias(field) - chain = field.split(".") - path = self._follow_field_path(chain[:-1], db, ignore_errors) - ftype = self.get_field_type(field) - # ftype is str, bool, float, or int - value = (value in ['True', True]) if ftype is bool else value - return self._set_fields(path, chain[-1], value, ftype) - - def _set_fields(self, path, attr, value, ftype): - """ - Helper function to handle recursive lists of items. - """ - from .handle import HandleClass - if isinstance(path, (list, tuple)): - count = 0 - for item in path: - count += self._set_fields(item, attr, value, ftype) - elif isinstance(ftype, HandleClass): - setattr(path, attr, value) - count = 1 - else: - setattr(path, attr, ftype(value)) - count = 1 - return count - + result = [] + for (key, value) in cls.get_schema()["properties"].items(): + schema_type = value.get("type") + if isinstance(schema_type, list): + schema_type.remove("null") + schema_type = schema_type[0] + elif isinstance(schema_type, dict): + schema_type = None + if schema_type in ("string", "integer", "number", "boolean"): + result.append((key.lower(), + schema_type, + value.get("maxLength"))) + return result diff --git a/gramps/gen/lib/tag.py b/gramps/gen/lib/tag.py index 44dc3c75d..af3c8228f 100644 --- a/gramps/gen/lib/tag.py +++ b/gramps/gen/lib/tag.py @@ -1,7 +1,7 @@ # # Gramps - a GTK+/GNOME based genealogy program # -# Copyright (C) 2010 Nick Hall +# Copyright (C) 2010,2017 Nick Hall # Copyright (C) 2013 Doug Blank # # This program is free software; you can redistribute it and/or modify @@ -29,7 +29,6 @@ Tag object for Gramps. # #------------------------------------------------------------------------- from .tableobj import TableObject -from .handle import Handle #------------------------------------------------------------------------- # @@ -104,14 +103,24 @@ class Tag(TableObject): @classmethod def get_schema(cls): """ - Return the schema for Tag + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict """ return { - "handle": Handle("Tag", "TAG-HANDLE"), - "name": str, - "color": str, - "priority": int, - "change": int, + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "handle": {"type": "string", + "maxLength": 50}, + "name": {"type": "string"}, + "color": {"type": "string", + "maxLength": 13}, + "priority": {"type": "integer", + "minimum": 0}, + "change": {"type": "integer"} + } } @classmethod diff --git a/gramps/gen/lib/test/field_test.py b/gramps/gen/lib/test/field_test.py deleted file mode 100644 index fefff80ad..000000000 --- a/gramps/gen/lib/test/field_test.py +++ /dev/null @@ -1,69 +0,0 @@ -# -# Gramps - a GTK+/GNOME based genealogy program -# -# Copyright (C) 2016 Gramps Development Team -# -# 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. -# - -""" Tests for using database fields """ - -import unittest - -from gramps.gen.db import DbTxn -from gramps.gen.db.utils import make_database - -from ..import (Person, Surname, Name, NameType, Family, FamilyRelType, - Event, EventType, Source, Place, PlaceName, Citation, Date, - Repository, RepositoryType, Media, Note, NoteType, - StyledText, StyledTextTag, StyledTextTagType, Tag, - ChildRef, ChildRefType, Attribute, MediaRef, AttributeType, - Url, UrlType, Address, EventRef, EventRoleType, RepoRef, - FamilyRelType, LdsOrd, MediaRef, PersonRef, PlaceType, - SrcAttribute, SrcAttributeType) - -class FieldBaseTest(unittest.TestCase): - - def setUp(self): - db = make_database("inmemorydb") - db.load(None) - with DbTxn("Test", db) as trans: - # Add some people: - person1 = Person() - person1.primary_name = Name() - person1.primary_name.surname_list.append(Surname()) - person1.primary_name.surname_list[0].surname = "Smith" - person1.gramps_id = "I0001" - db.add_person(person1, trans) # person gets a handle - - # Add some families: - family1 = Family() - family1.father_handle = person1.handle - family1.gramps_id = "F0001" - db.add_family(family1, trans) - self.db = db - - def test_field_access01(self): - person = self.db.get_person_from_gramps_id("I0001") - self.assertEqual(person.get_field("primary_name.surname_list.0.surname"), - "Smith") - - def test_field_join01(self): - family = self.db.get_family_from_gramps_id("F0001") - self.assertEqual(family.get_field("father_handle.primary_name.surname_list.0.surname", self.db), - "Smith") - -if __name__ == "__main__": - unittest.main() diff --git a/gramps/gen/lib/test/schema_test.py b/gramps/gen/lib/test/schema_test.py new file mode 100644 index 000000000..0d2e55293 --- /dev/null +++ b/gramps/gen/lib/test/schema_test.py @@ -0,0 +1,128 @@ +# +# 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. +# + +""" Unittest for JSON schema """ + +import os +import unittest +import json +import jsonschema + +from .. import (Person, Family, Event, Place, Repository, Source, Citation, + Media, Note, Tag) +from ..serialize import to_json +from ...db.utils import import_as_dict +from ...const import DATA_DIR +from gramps.cli.user import User + +TEST_DIR = os.path.abspath(os.path.join(DATA_DIR, "tests")) +EXAMPLE = os.path.join(TEST_DIR, "example.gramps") + +class BaseTest(unittest.TestCase): + def _schema_test(self, obj): + instance = json.loads(to_json(obj)) + try: + jsonschema.validate(instance, self.schema) + except jsonschema.exceptions.ValidationError: + self.fail("JSON Schema validation error") + +class PersonTest(BaseTest): + @classmethod + def setUpClass(cls): + cls.schema = Person.get_schema() + +class FamilyTest(BaseTest): + @classmethod + def setUpClass(cls): + cls.schema = Family.get_schema() + +class EventTest(BaseTest): + @classmethod + def setUpClass(cls): + cls.schema = Event.get_schema() + +class PlaceTest(BaseTest): + @classmethod + def setUpClass(cls): + cls.schema = Place.get_schema() + +class RepositoryTest(BaseTest): + @classmethod + def setUpClass(cls): + cls.schema = Repository.get_schema() + +class SourceTest(BaseTest): + @classmethod + def setUpClass(cls): + cls.schema = Source.get_schema() + +class CitationTest(BaseTest): + @classmethod + def setUpClass(cls): + cls.schema = Citation.get_schema() + +class MediaTest(BaseTest): + @classmethod + def setUpClass(cls): + cls.schema = Media.get_schema() + +class NoteTest(BaseTest): + @classmethod + def setUpClass(cls): + cls.schema = Note.get_schema() + +class TagTest(BaseTest): + @classmethod + def setUpClass(cls): + cls.schema = Tag.get_schema() + +def generate_case(obj, test_class): + """ + Dynamically generate tests. + """ + def test(self): + self._schema_test(obj) + name = "test_schema_%s_%s" % (obj.__class__.__name__, obj.handle) + setattr(test_class, name, test) + +db = import_as_dict(EXAMPLE, User()) +for obj in db.iter_people(): + generate_case(obj, PersonTest) +for obj in db.iter_families(): + generate_case(obj, FamilyTest) +for obj in db.iter_events(): + generate_case(obj, EventTest) +for obj in db.iter_places(): + generate_case(obj, PlaceTest) +for obj in db.iter_repositories(): + generate_case(obj, RepositoryTest) +for obj in db.iter_sources(): + generate_case(obj, SourceTest) +for obj in db.iter_citations(): + generate_case(obj, CitationTest) +for obj in db.iter_media(): + generate_case(obj, MediaTest) +for obj in db.iter_notes(): + generate_case(obj, NoteTest) +for obj in db.iter_tags(): + generate_case(obj, TagTest) + +if __name__ == "__main__": + unittest.main() diff --git a/gramps/gen/lib/url.py b/gramps/gen/lib/url.py index 9bc837e72..f7668572b 100644 --- a/gramps/gen/lib/url.py +++ b/gramps/gen/lib/url.py @@ -3,6 +3,7 @@ # # Copyright (C) 2000-2006 Donald N. Allingham # Copyright (C) 2009-2013 Doug Blank +# 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 @@ -72,6 +73,25 @@ class Url(SecondaryObject, PrivacyBase): self.type.unserialize(type_value) return self + @classmethod + def get_schema(cls): + """ + Returns the JSON Schema for this class. + + :returns: Returns a dict containing the schema. + :rtype: dict + """ + return { + "type": "object", + "properties": { + "_class": {"enum": [cls.__name__]}, + "private": {"type": "boolean"}, + "path": {"type": "string"}, + "desc": {"type": "string"}, + "type": UrlType.get_schema() + } + } + def get_text_data_list(self): """ Return the list of all textual attributes of the object. diff --git a/gramps/plugins/db/dbapi/dbapi.py b/gramps/plugins/db/dbapi/dbapi.py index cac044184..54bd34447 100644 --- a/gramps/plugins/db/dbapi/dbapi.py +++ b/gramps/plugins/db/dbapi/dbapi.py @@ -2,7 +2,7 @@ # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2015-2016 Douglas S. Blank -# Copyright (C) 2016 Nick Hall +# Copyright (C) 2016-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 @@ -891,19 +891,19 @@ class DBAPI(DbGeneric): surname_list.append(row[0]) return surname_list - def _sql_type(self, python_type): + def _sql_type(self, schema_type, max_length): """ Given a schema type, return the SQL type for a new column. """ - from gramps.gen.lib.handle import HandleClass - if isinstance(python_type, HandleClass): - return "VARCHAR(50)" - elif python_type == str: - return "TEXT" - elif python_type in [bool, int]: + if schema_type == 'string': + if max_length: + return "VARCHAR(%s)" % max_length + else: + return "TEXT" + elif schema_type in ['boolean', 'integer']: return "INTEGER" - elif python_type in [float]: + elif schema_type == 'number': return "REAL" else: return "BLOB" @@ -918,11 +918,9 @@ class DBAPI(DbGeneric): "get_secondary_fields"): continue table_name = table.lower() - for field_pair in self.get_table_func( + for field, schema_type, max_length in self.get_table_func( table, "class_func").get_secondary_fields(): - field, python_type = field_pair - field = self._hash_name(table, field) - sql_type = self._sql_type(python_type) + sql_type = self._sql_type(schema_type, max_length) try: # test to see if it exists: self.dbapi.execute("SELECT %s FROM %s LIMIT 1" @@ -944,14 +942,12 @@ class DBAPI(DbGeneric): """ table = obj.__class__.__name__ fields = self.get_table_func(table, "class_func").get_secondary_fields() - fields = [field for (field, direction) in fields] + fields = [field for (field, schema_type, max_length) in fields] sets = [] values = [] for field in fields: - value = obj.get_field(field, self, ignore_errors=True) - field = self._hash_name(obj.__class__.__name__, field) sets.append("%s = ?" % field) - values.append(value) + values.append(getattr(obj, field)) # Derived fields if table == 'Person': diff --git a/po/POTFILES.skip b/po/POTFILES.skip index 37ad9abe6..396746327 100644 --- a/po/POTFILES.skip +++ b/po/POTFILES.skip @@ -177,6 +177,7 @@ gramps/gen/lib/tag.py gramps/gen/lib/test/date_test.py gramps/gen/lib/test/grampstype_test.py gramps/gen/lib/test/merge_test.py +gramps/gen/lib/test/schema_test.py gramps/gen/lib/url.py gramps/gen/lib/urlbase.py #