From 7bcb6295471629c5c524dab2bdf0d62257bec6ff Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Tue, 2 Jun 2015 10:55:38 -0400 Subject: [PATCH] Updated backends to 5.0; moved Django and DBAPI to addons --- gramps/plugins/database/bsddb.gpr.py | 2 +- gramps/plugins/database/dbapi.gpr.py | 31 - gramps/plugins/database/dbapi.py | 2855 ----------------- .../defaults/default_settings.py | 7 - gramps/plugins/database/dictionarydb.gpr.py | 2 +- .../defaults/default_settings.py | 150 - .../django_support/defaults/sqlite.db | Bin 293888 -> 0 bytes .../database/django_support/libdjango.py | 2063 ------------ gramps/plugins/database/djangodb.gpr.py | 32 - gramps/plugins/database/djangodb.py | 2150 ------------- 10 files changed, 2 insertions(+), 7290 deletions(-) delete mode 100644 gramps/plugins/database/dbapi.gpr.py delete mode 100644 gramps/plugins/database/dbapi.py delete mode 100644 gramps/plugins/database/dbapi_support/defaults/default_settings.py delete mode 100644 gramps/plugins/database/django_support/defaults/default_settings.py delete mode 100644 gramps/plugins/database/django_support/defaults/sqlite.db delete mode 100644 gramps/plugins/database/django_support/libdjango.py delete mode 100644 gramps/plugins/database/djangodb.gpr.py delete mode 100644 gramps/plugins/database/djangodb.py diff --git a/gramps/plugins/database/bsddb.gpr.py b/gramps/plugins/database/bsddb.gpr.py index 20f2e9fda..82a23573c 100644 --- a/gramps/plugins/database/bsddb.gpr.py +++ b/gramps/plugins/database/bsddb.gpr.py @@ -24,7 +24,7 @@ plg.name = _("BSDDB Database Backend") plg.name_accell = _("_BSDDB Database Backend") plg.description = _("Berkeley Software Distribution Database Backend") plg.version = '1.0' -plg.gramps_target_version = "4.2" +plg.gramps_target_version = "5.0" plg.status = STABLE plg.fname = 'bsddb.py' plg.ptype = DATABASE diff --git a/gramps/plugins/database/dbapi.gpr.py b/gramps/plugins/database/dbapi.gpr.py deleted file mode 100644 index 2749e7a50..000000000 --- a/gramps/plugins/database/dbapi.gpr.py +++ /dev/null @@ -1,31 +0,0 @@ -# -# Gramps - a GTK+/GNOME based genealogy program -# -# Copyright (C) 2015 Douglas Blank -# -# 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. -# - -plg = newplugin() -plg.id = 'dbapi' -plg.name = _("DB-API 2.0") -plg.name_accell = _("DB-_API 2.0") -plg.description = _("DB-API 2.0 Database Backend") -plg.version = '1.0' -plg.gramps_target_version = "4.2" -plg.status = STABLE -plg.fname = 'dbapi.py' -plg.ptype = DATABASE -plg.databaseclass = 'DBAPI' diff --git a/gramps/plugins/database/dbapi.py b/gramps/plugins/database/dbapi.py deleted file mode 100644 index 5b1485d50..000000000 --- a/gramps/plugins/database/dbapi.py +++ /dev/null @@ -1,2855 +0,0 @@ -#------------------------------------------------------------------------ -# -# Python Modules -# -#------------------------------------------------------------------------ -import pickle -import base64 -import time -import re -import os -import logging -import shutil -import bisect - -#------------------------------------------------------------------------ -# -# Gramps Modules -# -#------------------------------------------------------------------------ -import gramps -from gramps.gen.const import GRAMPS_LOCALE as glocale -_ = glocale.translation.gettext -from gramps.gen.db import (DbReadBase, DbWriteBase, DbTxn, DbUndo, - KEY_TO_NAME_MAP, KEY_TO_CLASS_MAP, - CLASS_TO_KEY_MAP) -from gramps.gen.utils.callback import Callback -from gramps.gen.updatecallback import UpdateCallback -from gramps.gen.db.dbconst import * -from gramps.gen.db import (PERSON_KEY, - FAMILY_KEY, - CITATION_KEY, - SOURCE_KEY, - EVENT_KEY, - MEDIA_KEY, - PLACE_KEY, - REPOSITORY_KEY, - NOTE_KEY, - TAG_KEY) - -from gramps.gen.utils.id import create_id -from gramps.gen.lib.researcher import Researcher -from gramps.gen.lib import (Tag, MediaObject, Person, Family, Source, Citation, Event, - Place, Repository, Note, NameOriginType) -from gramps.gen.lib.genderstats import GenderStats - -_LOG = logging.getLogger(DBLOGNAME) - -def touch(fname, mode=0o666, dir_fd=None, **kwargs): - ## After http://stackoverflow.com/questions/1158076/implement-touch-using-python - flags = os.O_CREAT | os.O_APPEND - with os.fdopen(os.open(fname, flags=flags, mode=mode, dir_fd=dir_fd)) as f: - os.utime(f.fileno() if os.utime in os.supports_fd else fname, - dir_fd=None if os.supports_fd else dir_fd, **kwargs) - -class DBAPIUndo(DbUndo): - def __init__(self, grampsdb, path): - super(DBAPIUndo, self).__init__(grampsdb) - self.undodb = grampsdb - self.path = path - - def open(self, value=None): - """ - Open the backing storage. Needs to be overridden in the derived - class. - """ - pass - # FIXME - - def close(self): - """ - Close the backing storage. Needs to be overridden in the derived - class. - """ - pass - # FIXME - - def append(self, value): - """ - Add a new entry on the end. Needs to be overridden in the derived - class. - """ - pass - # FIXME - - def __getitem__(self, index): - """ - Returns an entry by index number. Needs to be overridden in the - derived class. - """ - return None - # FIXME - - def __setitem__(self, index, value): - """ - Set an entry to a value. Needs to be overridden in the derived class. - """ - pass - # FIXME - - def __len__(self): - """ - Returns the number of entries. Needs to be overridden in the derived - class. - """ - return 0 - # FIXME - - def __redo(self, update_history): - """ - """ - pass - # FIXME - - def __undo(self, update_history): - """ - """ - pass - # FIXME - -class Environment(object): - """ - Implements the Environment API. - """ - def __init__(self, db): - self.db = db - - def txn_begin(self): - return DBAPITxn("DBAPIDb Transaction", self.db) - -class Table(object): - """ - Implements Table interface. - """ - def __init__(self, db, table_name, funcs=None): - self.db = db - self.table_name = table_name - if funcs: - self.funcs = funcs - else: - self.funcs = db._tables[table_name] - - def cursor(self): - """ - Returns a Cursor for this Table. - """ - return self.funcs["cursor_func"]() - - def put(self, key, data, txn=None): - self.funcs["add_func"](data, txn) - -class Map(object): - """ - Implements the map API for person_map, etc. - - Takes a Table() as argument. - """ - def __init__(self, table, - keys_func="handles_func", - contains_func="has_handle_func", - *args, **kwargs): - super().__init__(*args, **kwargs) - self.table = table - self.keys_func = keys_func - self.contains_func = contains_func - self.txn = DBAPITxn("Dummy transaction", db=self.table.db, batch=True) - - def keys(self): - return self.table.funcs[self.keys_func]() - - def values(self): - return self.table.funcs["cursor_func"]() - - def __contains__(self, key): - return self.table.funcs[self.contains_func](key) - - def __getitem__(self, key): - if self.table.funcs[self.contains_func](key): - return self.table.funcs["raw_func"](key) - - def __setitem__(self, key, value): - """ - This is only done in a low-level raw import. - - value: serialized object - key: bytes key (ignored in this implementation) - """ - obj = self.table.funcs["class_func"].create(value) - self.table.funcs["commit_func"](obj, self.txn) - - def __len__(self): - return self.table.funcs["count_func"]() - -class MetaCursor(object): - def __init__(self): - pass - def __enter__(self): - return self - def __iter__(self): - return self.__next__() - def __next__(self): - yield None - def __exit__(self, *args, **kwargs): - pass - def iter(self): - yield None - def first(self): - self._iter = self.__iter__() - return self.next() - def next(self): - try: - return next(self._iter) - except: - return None - def close(self): - pass - -class Cursor(object): - def __init__(self, map): - self.map = map - self._iter = self.__iter__() - def __enter__(self): - return self - def __iter__(self): - for item in self.map.keys(): - yield (bytes(item, "utf-8"), self.map[item]) - def __next__(self): - try: - return self._iter.__next__() - except StopIteration: - return None - def __exit__(self, *args, **kwargs): - pass - def iter(self): - for item in self.map.keys(): - yield (bytes(item, "utf-8"), self.map[item]) - def first(self): - self._iter = self.__iter__() - try: - return next(self._iter) - except: - return - def next(self): - try: - return next(self._iter) - except: - return - def close(self): - pass - -class Bookmarks(object): - def __init__(self, default=[]): - self.handles = list(default) - - def set(self, handles): - self.handles = list(handles) - - def get(self): - return self.handles - - def append(self, handle): - self.handles.append(handle) - - def append_list(self, handles): - self.handles += handles - - def remove(self, handle): - self.handles.remove(handle) - - def pop(self, item): - return self.handles.pop(item) - - def insert(self, pos, item): - self.handles.insert(pos, item) - - def close(self): - del self.handles - - -class DBAPITxn(DbTxn): - def __init__(self, message, db, batch=False): - DbTxn.__init__(self, message, db, batch) - - def get(self, key, default=None, txn=None, **kwargs): - """ - Returns the data object associated with key - """ - if txn and key in txn: - return txn[key] - else: - return None - - def put(self, handle, new_data, txn): - """ - """ - txn[handle] = new_data - -class DBAPI(DbWriteBase, DbReadBase, UpdateCallback, Callback): - """ - A Gramps Database Backend. This replicates the grampsdb functions. - """ - __signals__ = dict((obj+'-'+op, signal) - for obj in - ['person', 'family', 'event', 'place', - 'source', 'citation', 'media', 'note', 'repository', 'tag'] - for op, signal in zip( - ['add', 'update', 'delete', 'rebuild'], - [(list,), (list,), (list,), None] - ) - ) - - # 2. Signals for long operations - __signals__.update(('long-op-'+op, signal) for op, signal in zip( - ['start', 'heartbeat', 'end'], - [(object,), None, None] - )) - - # 3. Special signal for change in home person - __signals__['home-person-changed'] = None - - # 4. Signal for change in person group name, parameters are - __signals__['person-groupname-rebuild'] = (str, str) - - __callback_map = {} - - def __init__(self, directory=None): - DbReadBase.__init__(self) - DbWriteBase.__init__(self) - Callback.__init__(self) - self._tables['Person'].update( - { - "handle_func": self.get_person_from_handle, - "gramps_id_func": self.get_person_from_gramps_id, - "class_func": Person, - "cursor_func": self.get_person_cursor, - "handles_func": self.get_person_handles, - "add_func": self.add_person, - "commit_func": self.commit_person, - "iter_func": self.iter_people, - "ids_func": self.get_person_gramps_ids, - "has_handle_func": self.has_handle_for_person, - "has_gramps_id_func": self.has_gramps_id_for_person, - "count": self.get_number_of_people, - "raw_func": self._get_raw_person_data, - }) - self._tables['Family'].update( - { - "handle_func": self.get_family_from_handle, - "gramps_id_func": self.get_family_from_gramps_id, - "class_func": Family, - "cursor_func": self.get_family_cursor, - "handles_func": self.get_family_handles, - "add_func": self.add_family, - "commit_func": self.commit_family, - "iter_func": self.iter_families, - "ids_func": self.get_family_gramps_ids, - "has_handle_func": self.has_handle_for_family, - "has_gramps_id_func": self.has_gramps_id_for_family, - "count": self.get_number_of_families, - "raw_func": self._get_raw_family_data, - }) - self._tables['Source'].update( - { - "handle_func": self.get_source_from_handle, - "gramps_id_func": self.get_source_from_gramps_id, - "class_func": Source, - "cursor_func": self.get_source_cursor, - "handles_func": self.get_source_handles, - "add_func": self.add_source, - "commit_func": self.commit_source, - "iter_func": self.iter_sources, - "ids_func": self.get_source_gramps_ids, - "has_handle_func": self.has_handle_for_source, - "has_gramps_id_func": self.has_gramps_id_for_source, - "count": self.get_number_of_sources, - "raw_func": self._get_raw_source_data, - }) - self._tables['Citation'].update( - { - "handle_func": self.get_citation_from_handle, - "gramps_id_func": self.get_citation_from_gramps_id, - "class_func": Citation, - "cursor_func": self.get_citation_cursor, - "handles_func": self.get_citation_handles, - "add_func": self.add_citation, - "commit_func": self.commit_citation, - "iter_func": self.iter_citations, - "ids_func": self.get_citation_gramps_ids, - "has_handle_func": self.has_handle_for_citation, - "has_gramps_id_func": self.has_gramps_id_for_citation, - "count": self.get_number_of_citations, - "raw_func": self._get_raw_citation_data, - }) - self._tables['Event'].update( - { - "handle_func": self.get_event_from_handle, - "gramps_id_func": self.get_event_from_gramps_id, - "class_func": Event, - "cursor_func": self.get_event_cursor, - "handles_func": self.get_event_handles, - "add_func": self.add_event, - "commit_func": self.commit_event, - "iter_func": self.iter_events, - "ids_func": self.get_event_gramps_ids, - "has_handle_func": self.has_handle_for_event, - "has_gramps_id_func": self.has_gramps_id_for_event, - "count": self.get_number_of_events, - "raw_func": self._get_raw_event_data, - }) - self._tables['Media'].update( - { - "handle_func": self.get_object_from_handle, - "gramps_id_func": self.get_object_from_gramps_id, - "class_func": MediaObject, - "cursor_func": self.get_media_cursor, - "handles_func": self.get_media_object_handles, - "add_func": self.add_object, - "commit_func": self.commit_media_object, - "iter_func": self.iter_media_objects, - "ids_func": self.get_media_gramps_ids, - "has_handle_func": self.has_handle_for_media, - "has_gramps_id_func": self.has_gramps_id_for_media, - "count": self.get_number_of_media_objects, - "raw_func": self._get_raw_media_data, - }) - self._tables['Place'].update( - { - "handle_func": self.get_place_from_handle, - "gramps_id_func": self.get_place_from_gramps_id, - "class_func": Place, - "cursor_func": self.get_place_cursor, - "handles_func": self.get_place_handles, - "add_func": self.add_place, - "commit_func": self.commit_place, - "iter_func": self.iter_places, - "ids_func": self.get_place_gramps_ids, - "has_handle_func": self.has_handle_for_place, - "has_gramps_id_func": self.has_gramps_id_for_place, - "count": self.get_number_of_places, - "raw_func": self._get_raw_place_data, - }) - self._tables['Repository'].update( - { - "handle_func": self.get_repository_from_handle, - "gramps_id_func": self.get_repository_from_gramps_id, - "class_func": Repository, - "cursor_func": self.get_repository_cursor, - "handles_func": self.get_repository_handles, - "add_func": self.add_repository, - "commit_func": self.commit_repository, - "iter_func": self.iter_repositories, - "ids_func": self.get_repository_gramps_ids, - "has_handle_func": self.has_handle_for_repository, - "has_gramps_id_func": self.has_gramps_id_for_repository, - "count": self.get_number_of_repositories, - "raw_func": self._get_raw_repository_data, - }) - self._tables['Note'].update( - { - "handle_func": self.get_note_from_handle, - "gramps_id_func": self.get_note_from_gramps_id, - "class_func": Note, - "cursor_func": self.get_note_cursor, - "handles_func": self.get_note_handles, - "add_func": self.add_note, - "commit_func": self.commit_note, - "iter_func": self.iter_notes, - "ids_func": self.get_note_gramps_ids, - "has_handle_func": self.has_handle_for_note, - "has_gramps_id_func": self.has_gramps_id_for_note, - "count": self.get_number_of_notes, - "raw_func": self._get_raw_note_data, - }) - self._tables['Tag'].update( - { - "handle_func": self.get_tag_from_handle, - "gramps_id_func": None, - "class_func": Tag, - "cursor_func": self.get_tag_cursor, - "handles_func": self.get_tag_handles, - "add_func": self.add_tag, - "commit_func": self.commit_tag, - "has_handle_func": self.has_handle_for_tag, - "iter_func": self.iter_tags, - "count": self.get_number_of_tags, - "raw_func": self._get_raw_tag_data, - }) - self.set_save_path(directory) - # skip GEDCOM cross-ref check for now: - self.set_feature("skip-check-xref", True) - self.set_feature("skip-import-additions", True) - self.readonly = False - self.db_is_open = True - self.name_formats = [] - # Bookmarks: - self.bookmarks = Bookmarks() - self.family_bookmarks = Bookmarks() - self.event_bookmarks = Bookmarks() - self.place_bookmarks = Bookmarks() - self.citation_bookmarks = Bookmarks() - self.source_bookmarks = Bookmarks() - self.repo_bookmarks = Bookmarks() - self.media_bookmarks = Bookmarks() - self.note_bookmarks = Bookmarks() - self.set_person_id_prefix('I%04d') - self.set_object_id_prefix('O%04d') - self.set_family_id_prefix('F%04d') - self.set_citation_id_prefix('C%04d') - self.set_source_id_prefix('S%04d') - self.set_place_id_prefix('P%04d') - self.set_event_id_prefix('E%04d') - self.set_repository_id_prefix('R%04d') - self.set_note_id_prefix('N%04d') - # ---------------------------------- - self.undodb = None - self.id_trans = DBAPITxn("ID Transaction", self) - self.fid_trans = DBAPITxn("FID Transaction", self) - self.pid_trans = DBAPITxn("PID Transaction", self) - self.cid_trans = DBAPITxn("CID Transaction", self) - self.sid_trans = DBAPITxn("SID Transaction", self) - self.oid_trans = DBAPITxn("OID Transaction", self) - self.rid_trans = DBAPITxn("RID Transaction", self) - self.nid_trans = DBAPITxn("NID Transaction", self) - self.eid_trans = DBAPITxn("EID Transaction", self) - self.cmap_index = 0 - self.smap_index = 0 - self.emap_index = 0 - self.pmap_index = 0 - self.fmap_index = 0 - self.lmap_index = 0 - self.omap_index = 0 - self.rmap_index = 0 - self.nmap_index = 0 - self.env = Environment(self) - self.person_map = Map(Table(self, "Person")) - self.person_id_map = Map(Table(self, "Person"), - keys_func="ids_func", - contains_func="has_gramps_id_func") - self.family_map = Map(Table(self, "Family")) - self.family_id_map = Map(Table(self, "Family"), - keys_func="ids_func", - contains_func="has_gramps_id_func") - self.place_map = Map(Table(self, "Place")) - self.place_id_map = Map(Table(self, "Place"), - keys_func="ids_func", - contains_func="has_gramps_id_func") - self.citation_map = Map(Table(self, "Citation")) - self.citation_id_map = Map(Table(self, "Citation"), - keys_func="ids_func", - contains_func="has_gramps_id_func") - self.source_map = Map(Table(self, "Source")) - self.source_id_map = Map(Table(self, "Source"), - keys_func="ids_func", - contains_func="has_gramps_id_func") - self.repository_map = Map(Table(self, "Repository")) - self.repository_id_map = Map(Table(self, "Repository"), - keys_func="ids_func", - contains_func="has_gramps_id_func") - self.note_map = Map(Table(self, "Note")) - self.note_id_map = Map(Table(self, "Note"), - keys_func="ids_func", - contains_func="has_gramps_id_func") - self.media_map = Map(Table(self, "Media")) - self.media_id_map = Map(Table(self, "Media"), - keys_func="ids_func", - contains_func="has_gramps_id_func") - self.event_map = Map(Table(self, "Event")) - self.event_id_map = Map(Table(self, "Event"), - keys_func="ids_func", - contains_func="has_gramps_id_func") - self.tag_map = Map(Table(self, "Tag")) - self.metadata = Map(Table(self, "Metadata", funcs={"cursor_func": lambda: MetaCursor()})) - self.undo_callback = None - self.redo_callback = None - self.undo_history_callback = None - self.modified = 0 - self.txn = DBAPITxn("DBAPI Transaction", self) - self.transaction = None - self.abort_possible = False - self._bm_changes = 0 - self.has_changed = False - self.genderStats = GenderStats() # can pass in loaded stats as dict - self.owner = Researcher() - if directory: - self.load(directory) - - def version_supported(self): - """Return True when the file has a supported version.""" - return True - - def get_table_names(self): - """Return a list of valid table names.""" - return list(self._tables.keys()) - - def get_table_metadata(self, table_name): - """Return the metadata for a valid table name.""" - if table_name in self._tables: - return self._tables[table_name] - return None - - def transaction_commit(self, txn): - self.dbapi.commit() - - def transaction_abort(self, txn): - self.dbapi.rollback() - - @staticmethod - def _validated_id_prefix(val, default): - if isinstance(val, str) and val: - try: - str_ = val % 1 - except TypeError: # missing conversion specifier - prefix_var = val + "%d" - except ValueError: # incomplete format - prefix_var = default+"%04d" - else: - prefix_var = val # OK as given - else: - prefix_var = default+"%04d" # not a string or empty string - return prefix_var - - @staticmethod - def __id2user_format(id_pattern): - """ - Return a method that accepts a Gramps ID and adjusts it to the users - format. - """ - pattern_match = re.match(r"(.*)%[0 ](\d+)[diu]$", id_pattern) - if pattern_match: - str_prefix = pattern_match.group(1) - nr_width = int(pattern_match.group(2)) - def closure_func(gramps_id): - if gramps_id and gramps_id.startswith(str_prefix): - id_number = gramps_id[len(str_prefix):] - if id_number.isdigit(): - id_value = int(id_number, 10) - #if len(str(id_value)) > nr_width: - # # The ID to be imported is too large to fit in the - # # users format. For now just create a new ID, - # # because that is also what happens with IDs that - # # are identical to IDs already in the database. If - # # the problem of colliding import and already - # # present IDs is solved the code here also needs - # # some solution. - # gramps_id = id_pattern % 1 - #else: - gramps_id = id_pattern % id_value - return gramps_id - else: - def closure_func(gramps_id): - return gramps_id - return closure_func - - def set_person_id_prefix(self, val): - """ - Set the naming template for GRAMPS Person ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as I%d or I%04d. - """ - self.person_prefix = self._validated_id_prefix(val, "I") - self.id2user_format = self.__id2user_format(self.person_prefix) - - def set_citation_id_prefix(self, val): - """ - Set the naming template for GRAMPS Citation ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as C%d or C%04d. - """ - self.citation_prefix = self._validated_id_prefix(val, "C") - self.cid2user_format = self.__id2user_format(self.citation_prefix) - - def set_source_id_prefix(self, val): - """ - Set the naming template for GRAMPS Source ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as S%d or S%04d. - """ - self.source_prefix = self._validated_id_prefix(val, "S") - self.sid2user_format = self.__id2user_format(self.source_prefix) - - def set_object_id_prefix(self, val): - """ - Set the naming template for GRAMPS MediaObject ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as O%d or O%04d. - """ - self.mediaobject_prefix = self._validated_id_prefix(val, "O") - self.oid2user_format = self.__id2user_format(self.mediaobject_prefix) - - def set_place_id_prefix(self, val): - """ - Set the naming template for GRAMPS Place ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as P%d or P%04d. - """ - self.place_prefix = self._validated_id_prefix(val, "P") - self.pid2user_format = self.__id2user_format(self.place_prefix) - - def set_family_id_prefix(self, val): - """ - Set the naming template for GRAMPS Family ID values. The string is - expected to be in the form of a simple text string, or in a format - that contains a C/Python style format string using %d, such as F%d - or F%04d. - """ - self.family_prefix = self._validated_id_prefix(val, "F") - self.fid2user_format = self.__id2user_format(self.family_prefix) - - def set_event_id_prefix(self, val): - """ - Set the naming template for GRAMPS Event ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as E%d or E%04d. - """ - self.event_prefix = self._validated_id_prefix(val, "E") - self.eid2user_format = self.__id2user_format(self.event_prefix) - - def set_repository_id_prefix(self, val): - """ - Set the naming template for GRAMPS Repository ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as R%d or R%04d. - """ - self.repository_prefix = self._validated_id_prefix(val, "R") - self.rid2user_format = self.__id2user_format(self.repository_prefix) - - def set_note_id_prefix(self, val): - """ - Set the naming template for GRAMPS Note ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as N%d or N%04d. - """ - self.note_prefix = self._validated_id_prefix(val, "N") - self.nid2user_format = self.__id2user_format(self.note_prefix) - - def __find_next_gramps_id(self, prefix, map_index, trans): - """ - Helper function for find_next__gramps_id methods - """ - index = prefix % map_index - while trans.get(str(index), txn=self.txn) is not None: - map_index += 1 - index = prefix % map_index - map_index += 1 - return (map_index, index) - - def find_next_person_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Person object based off the - person ID prefix. - """ - self.pmap_index, gid = self.__find_next_gramps_id(self.person_prefix, - self.pmap_index, self.id_trans) - return gid - - def find_next_place_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Place object based off the - place ID prefix. - """ - self.lmap_index, gid = self.__find_next_gramps_id(self.place_prefix, - self.lmap_index, self.pid_trans) - return gid - - def find_next_event_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Event object based off the - event ID prefix. - """ - self.emap_index, gid = self.__find_next_gramps_id(self.event_prefix, - self.emap_index, self.eid_trans) - return gid - - def find_next_object_gramps_id(self): - """ - Return the next available GRAMPS' ID for a MediaObject object based - off the media object ID prefix. - """ - self.omap_index, gid = self.__find_next_gramps_id(self.mediaobject_prefix, - self.omap_index, self.oid_trans) - return gid - - def find_next_citation_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Citation object based off the - citation ID prefix. - """ - self.cmap_index, gid = self.__find_next_gramps_id(self.citation_prefix, - self.cmap_index, self.cid_trans) - return gid - - def find_next_source_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Source object based off the - source ID prefix. - """ - self.smap_index, gid = self.__find_next_gramps_id(self.source_prefix, - self.smap_index, self.sid_trans) - return gid - - def find_next_family_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Family object based off the - family ID prefix. - """ - self.fmap_index, gid = self.__find_next_gramps_id(self.family_prefix, - self.fmap_index, self.fid_trans) - return gid - - def find_next_repository_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Respository object based - off the repository ID prefix. - """ - self.rmap_index, gid = self.__find_next_gramps_id(self.repository_prefix, - self.rmap_index, self.rid_trans) - return gid - - def find_next_note_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Note object based off the - note ID prefix. - """ - self.nmap_index, gid = self.__find_next_gramps_id(self.note_prefix, - self.nmap_index, self.nid_trans) - return gid - - def get_mediapath(self): - return self.get_metadata("media-path", "") - - def set_mediapath(self, mediapath): - return self.set_metadata("media-path", mediapath) - - def get_metadata(self, key, default=[]): - """ - Get an item from the database. - """ - cur = self.dbapi.execute("SELECT * FROM metadata WHERE setting = ?;", [key]) - row = cur.fetchone() - if row: - return pickle.loads(row["value"]) - elif default == []: - return [] - else: - return default - - def set_metadata(self, key, value): - """ - key: string - value: item, will be serialized here - """ - cur = self.dbapi.execute("SELECT * FROM metadata WHERE setting = ?;", [key]) - row = cur.fetchone() - if row: - cur = self.dbapi.execute("UPDATE metadata SET value = ? WHERE setting = ?;", - [pickle.dumps(value), key]) - else: - cur = self.dbapi.execute("INSERT INTO metadata (setting, value) VALUES (?, ?);", - [key, pickle.dumps(value)]) - self.dbapi.commit() - - def set_default_person_handle(self, handle): - self.set_metadata("default-person-handle", handle) - self.emit('home-person-changed') - - def get_name_group_keys(self): - cur = self.dbapi.execute("SELECT name FROM name_group ORDER BY name;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_name_group_mapping(self, key): - cur = self.dbapi.execute("SELECT grouping FROM name_group WHERE name = ?;", - [key]) - row = cur.fetchone() - if row: - return row[0] - - def get_person_handles(self, sort_handles=False): - if sort_handles: - cur = self.dbapi.execute("SELECT handle FROM person ORDER BY order_by;") - else: - cur = self.dbapi.execute("SELECT handle FROM person;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_family_handles(self): - cur = self.dbapi.execute("SELECT handle FROM family;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_event_handles(self): - cur = self.dbapi.execute("SELECT handle FROM event;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_citation_handles(self, sort_handles=False): - if sort_handles: - cur = self.dbapi.execute("SELECT handle FROM citation ORDER BY order_by;") - else: - cur = self.dbapi.execute("SELECT handle FROM citation;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_source_handles(self, sort_handles=False): - if sort_handles: - cur = self.dbapi.execute("SELECT handle FROM source ORDER BY order_by;") - else: - cur = self.dbapi.execute("SELECT handle from source;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_place_handles(self, sort_handles=False): - if sort_handles: - cur = self.dbapi.execute("SELECT handle FROM place ORDER BY order_by;") - else: - cur = self.dbapi.execute("SELECT handle FROM place;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_repository_handles(self): - cur = self.dbapi.execute("SELECT handle FROM repository;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_media_object_handles(self, sort_handles=False): - if sort_handles: - cur = self.dbapi.execute("SELECT handle FROM media ORDER BY order_by;") - else: - cur = self.dbapi.execute("SELECT handle FROM media;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_note_handles(self): - cur = self.dbapi.execute("SELECT handle FROM note;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_tag_handles(self, sort_handles=False): - if sort_handles: - cur = self.dbapi.execute("SELECT handle FROM tag ORDER BY order_by;") - else: - cur = self.dbapi.execute("SELECT handle FROM tag;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_event_from_handle(self, handle): - if isinstance(handle, bytes): - handle = str(handle, "utf-8") - event = None - if handle in self.event_map: - event = Event.create(self._get_raw_event_data(handle)) - return event - - def get_family_from_handle(self, handle): - if isinstance(handle, bytes): - handle = str(handle, "utf-8") - family = None - if handle in self.family_map: - family = Family.create(self._get_raw_family_data(handle)) - return family - - def get_repository_from_handle(self, handle): - if isinstance(handle, bytes): - handle = str(handle, "utf-8") - repository = None - if handle in self.repository_map: - repository = Repository.create(self._get_raw_repository_data(handle)) - return repository - - def get_person_from_handle(self, handle): - if isinstance(handle, bytes): - handle = str(handle, "utf-8") - person = None - if handle in self.person_map: - person = Person.create(self._get_raw_person_data(handle)) - return person - - def get_place_from_handle(self, handle): - if isinstance(handle, bytes): - handle = str(handle, "utf-8") - place = None - if handle in self.place_map: - place = Place.create(self._get_raw_place_data(handle)) - return place - - def get_citation_from_handle(self, handle): - if isinstance(handle, bytes): - handle = str(handle, "utf-8") - citation = None - if handle in self.citation_map: - citation = Citation.create(self._get_raw_citation_data(handle)) - return citation - - def get_source_from_handle(self, handle): - if isinstance(handle, bytes): - handle = str(handle, "utf-8") - source = None - if handle in self.source_map: - source = Source.create(self._get_raw_source_data(handle)) - return source - - def get_note_from_handle(self, handle): - if isinstance(handle, bytes): - handle = str(handle, "utf-8") - note = None - if handle in self.note_map: - note = Note.create(self._get_raw_note_data(handle)) - return note - - def get_object_from_handle(self, handle): - if isinstance(handle, bytes): - handle = str(handle, "utf-8") - media = None - if handle in self.media_map: - media = MediaObject.create(self._get_raw_media_data(handle)) - return media - - def get_tag_from_handle(self, handle): - if isinstance(handle, bytes): - handle = str(handle, "utf-8") - tag = None - if handle in self.tag_map: - tag = Tag.create(self._get_raw_tag_data(handle)) - return tag - - def get_default_person(self): - handle = self.get_default_handle() - if handle: - return self.get_person_from_handle(handle) - else: - return None - - def iter_people(self): - return (Person.create(data[1]) for data in self.get_person_cursor()) - - def iter_person_handles(self): - return (data[0] for data in self.get_person_cursor()) - - def iter_families(self): - return (Family.create(data[1]) for data in self.get_family_cursor()) - - def iter_family_handles(self): - return (handle for handle in self.family_map.keys()) - - def get_tag_from_name(self, name): - cur = self.dbapi.execute("""select handle from tag where order_by = ?;""", - [self._order_by_tag_key(name)]) - row = cur.fetchone() - if row: - self.get_tag_from_handle(row[0]) - return None - - def get_person_from_gramps_id(self, gramps_id): - if gramps_id in self.person_id_map: - return Person.create(self.person_id_map[gramps_id]) - return None - - def get_family_from_gramps_id(self, gramps_id): - if gramps_id in self.family_id_map: - return Family.create(self.family_id_map[gramps_id]) - return None - - def get_citation_from_gramps_id(self, gramps_id): - if gramps_id in self.citation_id_map: - return Citation.create(self.citation_id_map[gramps_id]) - return None - - def get_source_from_gramps_id(self, gramps_id): - if gramps_id in self.source_id_map: - return Source.create(self.source_id_map[gramps_id]) - return None - - def get_event_from_gramps_id(self, gramps_id): - if gramps_id in self.event_id_map: - return Event.create(self.event_id_map[gramps_id]) - return None - - def get_media_from_gramps_id(self, gramps_id): - if gramps_id in self.media_id_map: - return MediaObject.create(self.media_id_map[gramps_id]) - return None - - def get_place_from_gramps_id(self, gramps_id): - if gramps_id in self.place_id_map: - return Place.create(self.place_id_map[gramps_id]) - return None - - def get_repository_from_gramps_id(self, gramps_id): - if gramps_id in self.repository_id_map: - return Repository.create(self.repository_id_map[gramps_id]) - return None - - def get_note_from_gramps_id(self, gramps_id): - if gramps_id in self.note_id_map: - return Note.create(self.note_id_map[gramps_id]) - return None - - def get_number_of_people(self): - cur = self.dbapi.execute("SELECT count(handle) FROM person;") - row = cur.fetchone() - return row[0] - - def get_number_of_events(self): - cur = self.dbapi.execute("SELECT count(handle) FROM event;") - row = cur.fetchone() - return row[0] - - def get_number_of_places(self): - cur = self.dbapi.execute("SELECT count(handle) FROM place;") - row = cur.fetchone() - return row[0] - - def get_number_of_tags(self): - cur = self.dbapi.execute("SELECT count(handle) FROM tag;") - row = cur.fetchone() - return row[0] - - def get_number_of_families(self): - cur = self.dbapi.execute("SELECT count(handle) FROM family;") - row = cur.fetchone() - return row[0] - - def get_number_of_notes(self): - cur = self.dbapi.execute("SELECT count(handle) FROM note;") - row = cur.fetchone() - return row[0] - - def get_number_of_citations(self): - cur = self.dbapi.execute("SELECT count(handle) FROM citation;") - row = cur.fetchone() - return row[0] - - def get_number_of_sources(self): - cur = self.dbapi.execute("SELECT count(handle) FROM source;") - row = cur.fetchone() - return row[0] - - def get_number_of_media_objects(self): - cur = self.dbapi.execute("SELECT count(handle) FROM media;") - row = cur.fetchone() - return row[0] - - def get_number_of_repositories(self): - cur = self.dbapi.execute("SELECT count(handle) FROM repository;") - row = cur.fetchone() - return row[0] - - def get_place_cursor(self): - return Cursor(self.place_map) - - def get_person_cursor(self): - return Cursor(self.person_map) - - def get_family_cursor(self): - return Cursor(self.family_map) - - def get_event_cursor(self): - return Cursor(self.event_map) - - def get_note_cursor(self): - return Cursor(self.note_map) - - def get_tag_cursor(self): - return Cursor(self.tag_map) - - def get_repository_cursor(self): - return Cursor(self.repository_map) - - def get_media_cursor(self): - return Cursor(self.media_map) - - def get_citation_cursor(self): - return Cursor(self.citation_map) - - def get_source_cursor(self): - return Cursor(self.source_map) - - def has_gramps_id(self, obj_key, gramps_id): - key2table = { - PERSON_KEY: self.person_id_map, - FAMILY_KEY: self.family_id_map, - SOURCE_KEY: self.source_id_map, - CITATION_KEY: self.citation_id_map, - EVENT_KEY: self.event_id_map, - MEDIA_KEY: self.media_id_map, - PLACE_KEY: self.place_id_map, - REPOSITORY_KEY: self.repository_id_map, - NOTE_KEY: self.note_id_map, - } - return gramps_id in key2table[obj_key] - - def has_person_handle(self, handle): - return handle in self.person_map - - def has_family_handle(self, handle): - return handle in self.family_map - - def has_citation_handle(self, handle): - return handle in self.citation_map - - def has_source_handle(self, handle): - return handle in self.source_map - - def has_repository_handle(self, handle): - return handle in self.repository_map - - def has_note_handle(self, handle): - return handle in self.note_map - - def has_place_handle(self, handle): - return handle in self.place_map - - def has_event_handle(self, handle): - return handle in self.event_map - - def has_tag_handle(self, handle): - return handle in self.tag_map - - def has_object_handle(self, handle): - return handle in self.media_map - - def has_name_group_key(self, key): - cur = self.dbapi.execute("SELECT grouping FROM name_group WHERE name = ?;", - [key]) - row = cur.fetchone() - return True if row else False - - def set_name_group_mapping(self, name, grouping): - sname = name.encode("utf-8") - cur = self.dbapi.execute("SELECT * FROM name_group WHERE name = ?;", - [sname]) - row = cur.fetchone() - if row: - cur = self.dbapi.execute("DELETE FROM name_group WHERE name = ?;", - [sname]) - cur = self.dbapi.execute("INSERT INTO name_group (name, grouping) VALUES(?, ?);", - [sname, grouping]) - self.dbapi.commit() - - def get_raw_person_data(self, handle): - if handle in self.person_map: - return self.person_map[handle] - return None - - def get_raw_family_data(self, handle): - if handle in self.family_map: - return self.family_map[handle] - return None - - def get_raw_citation_data(self, handle): - if handle in self.citation_map: - return self.citation_map[handle] - return None - - def get_raw_source_data(self, handle): - if handle in self.source_map: - return self.source_map[handle] - return None - - def get_raw_repository_data(self, handle): - if handle in self.repository_map: - return self.repository_map[handle] - return None - - def get_raw_note_data(self, handle): - if handle in self.note_map: - return self.note_map[handle] - return None - - def get_raw_place_data(self, handle): - if handle in self.place_map: - return self.place_map[handle] - return None - - def get_raw_object_data(self, handle): - if handle in self.media_map: - return self.media_map[handle] - return None - - def get_raw_tag_data(self, handle): - if handle in self.tag_map: - return self.tag_map[handle] - return None - - def get_raw_event_data(self, handle): - if handle in self.event_map: - return self.event_map[handle] - return None - - def add_person(self, person, trans, set_gid=True): - if not person.handle: - person.handle = create_id() - if not person.gramps_id and set_gid: - person.gramps_id = self.find_next_person_gramps_id() - self.commit_person(person, trans) - return person.handle - - def add_family(self, family, trans, set_gid=True): - if not family.handle: - family.handle = create_id() - if not family.gramps_id and set_gid: - family.gramps_id = self.find_next_family_gramps_id() - self.commit_family(family, trans) - return family.handle - - def add_citation(self, citation, trans, set_gid=True): - if not citation.handle: - citation.handle = create_id() - if not citation.gramps_id and set_gid: - citation.gramps_id = self.find_next_citation_gramps_id() - self.commit_citation(citation, trans) - return citation.handle - - def add_source(self, source, trans, set_gid=True): - if not source.handle: - source.handle = create_id() - if not source.gramps_id and set_gid: - source.gramps_id = self.find_next_source_gramps_id() - self.commit_source(source, trans) - return source.handle - - def add_repository(self, repository, trans, set_gid=True): - if not repository.handle: - repository.handle = create_id() - if not repository.gramps_id and set_gid: - repository.gramps_id = self.find_next_repository_gramps_id() - self.commit_repository(repository, trans) - return repository.handle - - def add_note(self, note, trans, set_gid=True): - if not note.handle: - note.handle = create_id() - if not note.gramps_id and set_gid: - note.gramps_id = self.find_next_note_gramps_id() - self.commit_note(note, trans) - return note.handle - - def add_place(self, place, trans, set_gid=True): - if not place.handle: - place.handle = create_id() - if not place.gramps_id and set_gid: - place.gramps_id = self.find_next_place_gramps_id() - self.commit_place(place, trans) - return place.handle - - def add_event(self, event, trans, set_gid=True): - if not event.handle: - event.handle = create_id() - if not event.gramps_id and set_gid: - event.gramps_id = self.find_next_event_gramps_id() - self.commit_event(event, trans) - return event.handle - - def add_tag(self, tag, trans): - if not tag.handle: - tag.handle = create_id() - self.commit_tag(tag, trans) - return tag.handle - - def add_object(self, obj, transaction, set_gid=True): - """ - Add a MediaObject to the database, assigning internal IDs if they have - not already been defined. - - If not set_gid, then gramps_id is not set. - """ - if not obj.handle: - obj.handle = create_id() - if not obj.gramps_id and set_gid: - obj.gramps_id = self.find_next_object_gramps_id() - self.commit_media_object(obj, transaction) - return obj.handle - - def commit_person(self, person, trans, change_time=None): - emit = None - if person.handle in self.person_map: - emit = "person-update" - old_person = self.get_person_from_handle(person.handle) - # Update gender statistics if necessary - if (old_person.gender != person.gender or - old_person.primary_name.first_name != - person.primary_name.first_name): - - self.genderStats.uncount_person(old_person) - self.genderStats.count_person(person) - # Update surname list if necessary - if (self._order_by_person_key(person) != - self._order_by_person_key(old_person)): - self.remove_from_surname_list(old_person) - self.add_to_surname_list(person, trans.batch) - # update the person: - self.dbapi.execute("""UPDATE person SET gramps_id = ?, - order_by = ?, - blob = ? - WHERE handle = ?;""", - [person.gramps_id, - self._order_by_person_key(person), - pickle.dumps(person.serialize()), - person.handle]) - else: - emit = "person-add" - self.genderStats.count_person(person) - self.add_to_surname_list(person, trans.batch) - # Insert the person: - self.dbapi.execute("""INSERT INTO person (handle, order_by, gramps_id, blob) - VALUES(?, ?, ?, ?);""", - [person.handle, - self._order_by_person_key(person), - person.gramps_id, - pickle.dumps(person.serialize())]) - if not trans.batch: - self.update_backlinks(person) - self.dbapi.commit() - # Other misc update tasks: - self.individual_attributes.update( - [str(attr.type) for attr in person.attribute_list - if attr.type.is_custom() and str(attr.type)]) - - self.event_role_names.update([str(eref.role) - for eref in person.event_ref_list - if eref.role.is_custom()]) - - self.name_types.update([str(name.type) - for name in ([person.primary_name] - + person.alternate_names) - if name.type.is_custom()]) - all_surn = [] # new list we will use for storage - all_surn += person.primary_name.get_surname_list() - for asurname in person.alternate_names: - all_surn += asurname.get_surname_list() - self.origin_types.update([str(surn.origintype) for surn in all_surn - if surn.origintype.is_custom()]) - all_surn = None - self.url_types.update([str(url.type) for url in person.urls - if url.type.is_custom()]) - attr_list = [] - for mref in person.media_list: - attr_list += [str(attr.type) for attr in mref.attribute_list - if attr.type.is_custom() and str(attr.type)] - self.media_attributes.update(attr_list) - # Emit after added: - if emit: - self.emit(emit, ([person.handle],)) - self.has_changed = True - - def add_to_surname_list(self, person, batch_transaction): - """ - Add surname to surname list - """ - if batch_transaction: - return - # TODO: check to see if this is correct - name = None - primary_name = person.get_primary_name() - if primary_name: - surname_list = primary_name.get_surname_list() - if len(surname_list) > 0: - name = surname_list[0].surname - if name is None: - return - i = bisect.bisect(self.surname_list, name) - if 0 < i <= len(self.surname_list): - if self.surname_list[i-1] != name: - self.surname_list.insert(i, name) - else: - self.surname_list.insert(i, name) - - def remove_from_surname_list(self, person): - """ - Check whether there are persons with the same surname left in - the database. - - If not then we need to remove the name from the list. - The function must be overridden in the derived class. - """ - name = None - primary_name = person.get_primary_name() - if primary_name: - surname_list = primary_name.get_surname_list() - if len(surname_list) > 0: - name = surname_list[0].surname - if name is None: - return - if name in self.surname_list: - self.surname_list.remove(name) - - def commit_family(self, family, trans, change_time=None): - emit = None - if family.handle in self.family_map: - emit = "family-update" - self.dbapi.execute("""UPDATE family SET gramps_id = ?, - blob = ? - WHERE handle = ?;""", - [family.gramps_id, - pickle.dumps(family.serialize()), - family.handle]) - else: - emit = "family-add" - self.dbapi.execute("""INSERT INTO family (handle, gramps_id, blob) - VALUES(?, ?, ?);""", - [family.handle, family.gramps_id, - pickle.dumps(family.serialize())]) - if not trans.batch: - self.update_backlinks(family) - self.dbapi.commit() - # Misc updates: - self.family_attributes.update( - [str(attr.type) for attr in family.attribute_list - if attr.type.is_custom() and str(attr.type)]) - - rel_list = [] - for ref in family.child_ref_list: - if ref.frel.is_custom(): - rel_list.append(str(ref.frel)) - if ref.mrel.is_custom(): - rel_list.append(str(ref.mrel)) - self.child_ref_types.update(rel_list) - - self.event_role_names.update( - [str(eref.role) for eref in family.event_ref_list - if eref.role.is_custom()]) - - if family.type.is_custom(): - self.family_rel_types.add(str(family.type)) - - attr_list = [] - for mref in family.media_list: - attr_list += [str(attr.type) for attr in mref.attribute_list - if attr.type.is_custom() and str(attr.type)] - self.media_attributes.update(attr_list) - # Emit after added: - if emit: - self.emit(emit, ([family.handle],)) - self.has_changed = True - - def commit_citation(self, citation, trans, change_time=None): - emit = None - if citation.handle in self.citation_map: - emit = "citation-update" - self.dbapi.execute("""UPDATE citation SET gramps_id = ?, - order_by = ?, - blob = ? - WHERE handle = ?;""", - [citation.gramps_id, - self._order_by_citation_key(citation), - pickle.dumps(citation.serialize()), - citation.handle]) - else: - emit = "citation-add" - self.dbapi.execute("""INSERT INTO citation (handle, order_by, gramps_id, blob) - VALUES(?, ?, ?, ?);""", - [citation.handle, - self._order_by_citation_key(citation), - citation.gramps_id, - pickle.dumps(citation.serialize())]) - if not trans.batch: - self.update_backlinks(citation) - self.dbapi.commit() - # Misc updates: - attr_list = [] - for mref in citation.media_list: - attr_list += [str(attr.type) for attr in mref.attribute_list - if attr.type.is_custom() and str(attr.type)] - self.media_attributes.update(attr_list) - - self.source_attributes.update( - [str(attr.type) for attr in citation.attribute_list - if attr.type.is_custom() and str(attr.type)]) - - # Emit after added: - if emit: - self.emit(emit, ([citation.handle],)) - self.has_changed = True - - def commit_source(self, source, trans, change_time=None): - emit = None - if source.handle in self.source_map: - emit = "source-update" - self.dbapi.execute("""UPDATE source SET gramps_id = ?, - order_by = ?, - blob = ? - WHERE handle = ?;""", - [source.gramps_id, - self._order_by_source_key(source), - pickle.dumps(source.serialize()), - source.handle]) - else: - emit = "source-add" - self.dbapi.execute("""INSERT INTO source (handle, order_by, gramps_id, blob) - VALUES(?, ?, ?, ?);""", - [source.handle, - self._order_by_source_key(source), - source.gramps_id, - pickle.dumps(source.serialize())]) - if not trans.batch: - self.update_backlinks(source) - self.dbapi.commit() - # Misc updates: - self.source_media_types.update( - [str(ref.media_type) for ref in source.reporef_list - if ref.media_type.is_custom()]) - - attr_list = [] - for mref in source.media_list: - attr_list += [str(attr.type) for attr in mref.attribute_list - if attr.type.is_custom() and str(attr.type)] - self.media_attributes.update(attr_list) - self.source_attributes.update( - [str(attr.type) for attr in source.attribute_list - if attr.type.is_custom() and str(attr.type)]) - # Emit after added: - if emit: - self.emit(emit, ([source.handle],)) - self.has_changed = True - - def commit_repository(self, repository, trans, change_time=None): - emit = None - if repository.handle in self.repository_map: - emit = "repository-update" - self.dbapi.execute("""UPDATE repository SET gramps_id = ?, - blob = ? - WHERE handle = ?;""", - [repository.gramps_id, - pickle.dumps(repository.serialize()), - repository.handle]) - else: - emit = "repository-add" - self.dbapi.execute("""INSERT INTO repository (handle, gramps_id, blob) - VALUES(?, ?, ?);""", - [repository.handle, repository.gramps_id, pickle.dumps(repository.serialize())]) - if not trans.batch: - self.update_backlinks(repository) - self.dbapi.commit() - # Misc updates: - if repository.type.is_custom(): - self.repository_types.add(str(repository.type)) - - self.url_types.update([str(url.type) for url in repository.urls - if url.type.is_custom()]) - # Emit after added: - if emit: - self.emit(emit, ([repository.handle],)) - self.has_changed = True - - def commit_note(self, note, trans, change_time=None): - emit = None - if note.handle in self.note_map: - emit = "note-update" - self.dbapi.execute("""UPDATE note SET gramps_id = ?, - blob = ? - WHERE handle = ?;""", - [note.gramps_id, - pickle.dumps(note.serialize()), - note.handle]) - else: - emit = "note-add" - self.dbapi.execute("""INSERT INTO note (handle, gramps_id, blob) - VALUES(?, ?, ?);""", - [note.handle, note.gramps_id, pickle.dumps(note.serialize())]) - if not trans.batch: - self.update_backlinks(note) - self.dbapi.commit() - # Misc updates: - if note.type.is_custom(): - self.note_types.add(str(note.type)) - # Emit after added: - if emit: - self.emit(emit, ([note.handle],)) - self.has_changed = True - - def commit_place(self, place, trans, change_time=None): - emit = None - if place.handle in self.place_map: - emit = "place-update" - self.dbapi.execute("""UPDATE place SET gramps_id = ?, - order_by = ?, - blob = ? - WHERE handle = ?;""", - [place.gramps_id, - self._order_by_place_key(place), - pickle.dumps(place.serialize()), - place.handle]) - else: - emit = "place-add" - self.dbapi.execute("""INSERT INTO place (handle, order_by, gramps_id, blob) - VALUES(?, ?, ?, ?);""", - [place.handle, - self._order_by_place_key(place), - place.gramps_id, - pickle.dumps(place.serialize())]) - if not trans.batch: - self.update_backlinks(place) - self.dbapi.commit() - # Misc updates: - if place.get_type().is_custom(): - self.place_types.add(str(place.get_type())) - - self.url_types.update([str(url.type) for url in place.urls - if url.type.is_custom()]) - - attr_list = [] - for mref in place.media_list: - attr_list += [str(attr.type) for attr in mref.attribute_list - if attr.type.is_custom() and str(attr.type)] - self.media_attributes.update(attr_list) - # Emit after added: - if emit: - self.emit(emit, ([place.handle],)) - self.has_changed = True - - def commit_event(self, event, trans, change_time=None): - emit = None - if event.handle in self.event_map: - emit = "event-update" - self.dbapi.execute("""UPDATE event SET gramps_id = ?, - blob = ? - WHERE handle = ?;""", - [event.gramps_id, - pickle.dumps(event.serialize()), - event.handle]) - else: - emit = "event-add" - self.dbapi.execute("""INSERT INTO event (handle, gramps_id, blob) - VALUES(?, ?, ?);""", - [event.handle, - event.gramps_id, - pickle.dumps(event.serialize())]) - if not trans.batch: - self.update_backlinks(event) - self.dbapi.commit() - # Misc updates: - self.event_attributes.update( - [str(attr.type) for attr in event.attribute_list - if attr.type.is_custom() and str(attr.type)]) - if event.type.is_custom(): - self.event_names.add(str(event.type)) - attr_list = [] - for mref in event.media_list: - attr_list += [str(attr.type) for attr in mref.attribute_list - if attr.type.is_custom() and str(attr.type)] - self.media_attributes.update(attr_list) - # Emit after added: - if emit: - self.emit(emit, ([event.handle],)) - self.has_changed = True - - def update_backlinks(self, obj): - # First, delete the current references: - self.dbapi.execute("DELETE FROM reference WHERE obj_handle = ?;", - [obj.handle]) - # Now, add the current ones: - references = set(obj.get_referenced_handles_recursively()) - for (ref_class_name, ref_handle) in references: - self.dbapi.execute("""INSERT INTO reference - (obj_handle, obj_class, ref_handle, ref_class) - VALUES(?, ?, ?, ?);""", - [obj.handle, - obj.__class__.__name__, - ref_handle, - ref_class_name]) - # This function is followed by a commit. - - def commit_tag(self, tag, trans, change_time=None): - emit = None - if tag.handle in self.tag_map: - emit = "tag-update" - self.dbapi.execute("""UPDATE tag SET blob = ?, - order_by = ? - WHERE handle = ?;""", - [pickle.dumps(tag.serialize()), - self._order_by_tag_key(tag), - tag.handle]) - else: - emit = "tag-add" - self.dbapi.execute("""INSERT INTO tag (handle, order_by, blob) - VALUES(?, ?, ?);""", - [tag.handle, - self._order_by_tag_key(tag), - pickle.dumps(tag.serialize())]) - if not trans.batch: - self.update_backlinks(tag) - self.dbapi.commit() - # Emit after added: - if emit: - self.emit(emit, ([tag.handle],)) - - def commit_media_object(self, media, trans, change_time=None): - emit = None - if media.handle in self.media_map: - emit = "media-update" - self.dbapi.execute("""UPDATE media SET gramps_id = ?, - order_by = ?, - blob = ? - WHERE handle = ?;""", - [media.gramps_id, - self._order_by_media_key(media), - pickle.dumps(media.serialize()), - media.handle]) - else: - emit = "media-add" - self.dbapi.execute("""INSERT INTO media (handle, order_by, gramps_id, blob) - VALUES(?, ?, ?, ?);""", - [media.handle, - self._order_by_media_key(media), - media.gramps_id, - pickle.dumps(media.serialize())]) - if not trans.batch: - self.update_backlinks(media) - self.dbapi.commit() - # Misc updates: - self.media_attributes.update( - [str(attr.type) for attr in media.attribute_list - if attr.type.is_custom() and str(attr.type)]) - # Emit after added: - if emit: - self.emit(emit, ([media.handle],)) - - def get_gramps_ids(self, obj_key): - key2table = { - PERSON_KEY: self.person_id_map, - FAMILY_KEY: self.family_id_map, - CITATION_KEY: self.citation_id_map, - SOURCE_KEY: self.source_id_map, - EVENT_KEY: self.event_id_map, - MEDIA_KEY: self.media_id_map, - PLACE_KEY: self.place_id_map, - REPOSITORY_KEY: self.repository_id_map, - NOTE_KEY: self.note_id_map, - } - return list(key2table[obj_key].keys()) - - def transaction_begin(self, transaction): - """ - Transactions are handled automatically by the db layer. - """ - return - - def set_researcher(self, owner): - self.owner.set_from(owner) - - def get_researcher(self): - return self.owner - - def request_rebuild(self): - self.emit('person-rebuild') - self.emit('family-rebuild') - self.emit('place-rebuild') - self.emit('source-rebuild') - self.emit('citation-rebuild') - self.emit('media-rebuild') - self.emit('event-rebuild') - self.emit('repository-rebuild') - self.emit('note-rebuild') - self.emit('tag-rebuild') - - def copy_from_db(self, db): - """ - A (possibily) implementation-specific method to get data from - db into this database. - """ - for key in db._tables.keys(): - cursor = db._tables[key]["cursor_func"] - class_ = db._tables[key]["class_func"] - for (handle, data) in cursor(): - map = getattr(self, "%s_map" % key.lower()) - map[handle] = class_.create(data) - - def get_transaction_class(self): - """ - Get the transaction class associated with this database backend. - """ - return DBAPITxn - - def get_from_name_and_handle(self, table_name, handle): - """ - Returns a gen.lib object (or None) given table_name and - handle. - - Examples: - - >>> self.get_from_name_and_handle("Person", "a7ad62365bc652387008") - >>> self.get_from_name_and_handle("Media", "c3434653675bcd736f23") - """ - if table_name in self._tables: - return self._tables[table_name]["handle_func"](handle) - return None - - def get_from_name_and_gramps_id(self, table_name, gramps_id): - """ - Returns a gen.lib object (or None) given table_name and - Gramps ID. - - Examples: - - >>> self.get_from_name_and_gramps_id("Person", "I00002") - >>> self.get_from_name_and_gramps_id("Family", "F056") - >>> self.get_from_name_and_gramps_id("Media", "M00012") - """ - if table_name in self._tables: - return self._tables[table_name]["gramps_id_func"](gramps_id) - return None - - def remove_person(self, handle, transaction): - """ - Remove the Person specified by the database handle from the database, - preserving the change in the passed transaction. - """ - - if self.readonly or not handle: - return - if handle in self.person_map: - person = Person.create(self.person_map[handle]) - #del self.person_map[handle] - #del self.person_id_map[person.gramps_id] - self.dbapi.execute("DELETE FROM person WHERE handle = ?;", [handle]) - self.emit("person-delete", ([handle],)) - if not transaction.batch: - self.dbapi.commit() - - def remove_source(self, handle, transaction): - """ - Remove the Source specified by the database handle from the - database, preserving the change in the passed transaction. - """ - self.__do_remove(handle, transaction, self.source_map, - self.source_id_map, SOURCE_KEY) - - def remove_citation(self, handle, transaction): - """ - Remove the Citation specified by the database handle from the - database, preserving the change in the passed transaction. - """ - self.__do_remove(handle, transaction, self.citation_map, - self.citation_id_map, CITATION_KEY) - - def remove_event(self, handle, transaction): - """ - Remove the Event specified by the database handle from the - database, preserving the change in the passed transaction. - """ - self.__do_remove(handle, transaction, self.event_map, - self.event_id_map, EVENT_KEY) - - def remove_object(self, handle, transaction): - """ - Remove the MediaObjectPerson specified by the database handle from the - database, preserving the change in the passed transaction. - """ - self.__do_remove(handle, transaction, self.media_map, - self.media_id_map, MEDIA_KEY) - - def remove_place(self, handle, transaction): - """ - Remove the Place specified by the database handle from the - database, preserving the change in the passed transaction. - """ - self.__do_remove(handle, transaction, self.place_map, - self.place_id_map, PLACE_KEY) - - def remove_family(self, handle, transaction): - """ - Remove the Family specified by the database handle from the - database, preserving the change in the passed transaction. - """ - self.__do_remove(handle, transaction, self.family_map, - self.family_id_map, FAMILY_KEY) - - def remove_repository(self, handle, transaction): - """ - Remove the Repository specified by the database handle from the - database, preserving the change in the passed transaction. - """ - self.__do_remove(handle, transaction, self.repository_map, - self.repository_id_map, REPOSITORY_KEY) - - def remove_note(self, handle, transaction): - """ - Remove the Note specified by the database handle from the - database, preserving the change in the passed transaction. - """ - self.__do_remove(handle, transaction, self.note_map, - self.note_id_map, NOTE_KEY) - - def remove_tag(self, handle, transaction): - """ - Remove the Tag specified by the database handle from the - database, preserving the change in the passed transaction. - """ - self.__do_remove(handle, transaction, self.tag_map, - None, TAG_KEY) - - def is_empty(self): - """ - Return true if there are no [primary] records in the database - """ - for table in self._tables: - if len(self._tables[table]["handles_func"]()) > 0: - return False - return True - - def __do_remove(self, handle, transaction, data_map, data_id_map, key): - key2table = { - PERSON_KEY: "person", - FAMILY_KEY: "family", - SOURCE_KEY: "source", - CITATION_KEY: "citation", - EVENT_KEY: "event", - MEDIA_KEY: "media", - PLACE_KEY: "place", - REPOSITORY_KEY: "repository", - NOTE_KEY: "note", - } - if self.readonly or not handle: - return - if handle in data_map: - self.dbapi.execute("DELETE FROM %s WHERE handle = ?;" % key2table[key], - [handle]) - self.emit(KEY_TO_NAME_MAP[key] + "-delete", ([handle],)) - if not transaction.batch: - self.dbapi.commit() - - def close(self): - if self._directory: - filename = os.path.join(self._directory, "meta_data.db") - touch(filename) - # Save metadata - self.set_metadata('bookmarks', self.bookmarks.get()) - self.set_metadata('family_bookmarks', self.family_bookmarks.get()) - self.set_metadata('event_bookmarks', self.event_bookmarks.get()) - self.set_metadata('source_bookmarks', self.source_bookmarks.get()) - self.set_metadata('citation_bookmarks', self.citation_bookmarks.get()) - self.set_metadata('repo_bookmarks', self.repo_bookmarks.get()) - self.set_metadata('media_bookmarks', self.media_bookmarks.get()) - self.set_metadata('place_bookmarks', self.place_bookmarks.get()) - self.set_metadata('note_bookmarks', self.note_bookmarks.get()) - - # Custom type values, sets - self.set_metadata('event_names', self.event_names) - self.set_metadata('fattr_names', self.family_attributes) - self.set_metadata('pattr_names', self.individual_attributes) - self.set_metadata('sattr_names', self.source_attributes) - self.set_metadata('marker_names', self.marker_names) - self.set_metadata('child_refs', self.child_ref_types) - self.set_metadata('family_rels', self.family_rel_types) - self.set_metadata('event_roles', self.event_role_names) - self.set_metadata('name_types', self.name_types) - self.set_metadata('origin_types', self.origin_types) - self.set_metadata('repo_types', self.repository_types) - self.set_metadata('note_types', self.note_types) - self.set_metadata('sm_types', self.source_media_types) - self.set_metadata('url_types', self.url_types) - self.set_metadata('mattr_names', self.media_attributes) - self.set_metadata('eattr_names', self.event_attributes) - self.set_metadata('place_types', self.place_types) - - # surname list - self.set_metadata('surname_list', self.surname_list) - - self.dbapi.close() - - def find_backlink_handles(self, handle, include_classes=None): - """ - Find all objects that hold a reference to the object handle. - - Returns an interator over a list of (class_name, handle) tuples. - - :param handle: handle of the object to search for. - :type handle: database handle - :param include_classes: list of class names to include in the results. - Default: None means include all classes. - :type include_classes: list of class names - - Note that this is a generator function, it returns a iterator for - use in loops. If you want a list of the results use:: - - result_list = list(find_backlink_handles(handle)) - """ - cur = self.dbapi.execute("SELECT * FROM reference WHERE ref_handle = ?;", - [handle]) - rows = cur.fetchall() - for row in rows: - if (include_classes is None) or (row["obj_class"] in include_classes): - yield (row["obj_class"], row["obj_handle"]) - - def find_initial_person(self): - handle = self.get_default_handle() - person = None - if handle: - person = self.get_person_from_handle(handle) - if person: - return person - cur = self.dbapi.execute("SELECT handle FROM person;") - row = cur.fetchone() - if row: - return self.get_person_from_handle(row[0]) - - def get_bookmarks(self): - return self.bookmarks - - def get_citation_bookmarks(self): - return self.citation_bookmarks - - def get_default_handle(self): - return self.get_metadata("default-person-handle", None) - - def get_surname_list(self): - """ - Return the list of locale-sorted surnames contained in the database. - """ - return self.surname_list - - def get_event_attribute_types(self): - """ - Return a list of all Attribute types assocated with Event instances - in the database. - """ - return list(self.event_attributes) - - def get_event_types(self): - """ - Return a list of all event types in the database. - """ - return list(self.event_names) - - def get_person_event_types(self): - """ - Deprecated: Use get_event_types - """ - return list(self.event_names) - - def get_person_attribute_types(self): - """ - Return a list of all Attribute types assocated with Person instances - in the database. - """ - return list(self.individual_attributes) - - def get_family_attribute_types(self): - """ - Return a list of all Attribute types assocated with Family instances - in the database. - """ - return list(self.family_attributes) - - def get_family_event_types(self): - """ - Deprecated: Use get_event_types - """ - return list(self.event_names) - - def get_media_attribute_types(self): - """ - Return a list of all Attribute types assocated with Media and MediaRef - instances in the database. - """ - return list(self.media_attributes) - - def get_family_relation_types(self): - """ - Return a list of all relationship types assocated with Family - instances in the database. - """ - return list(self.family_rel_types) - - def get_child_reference_types(self): - """ - Return a list of all child reference types assocated with Family - instances in the database. - """ - return list(self.child_ref_types) - - def get_event_roles(self): - """ - Return a list of all custom event role names assocated with Event - instances in the database. - """ - return list(self.event_role_names) - - def get_name_types(self): - """ - Return a list of all custom names types assocated with Person - instances in the database. - """ - return list(self.name_types) - - def get_origin_types(self): - """ - Return a list of all custom origin types assocated with Person/Surname - instances in the database. - """ - return list(self.origin_types) - - def get_repository_types(self): - """ - Return a list of all custom repository types assocated with Repository - instances in the database. - """ - return list(self.repository_types) - - def get_note_types(self): - """ - Return a list of all custom note types assocated with Note instances - in the database. - """ - return list(self.note_types) - - def get_source_attribute_types(self): - """ - Return a list of all Attribute types assocated with Source/Citation - instances in the database. - """ - return list(self.source_attributes) - - def get_source_media_types(self): - """ - Return a list of all custom source media types assocated with Source - instances in the database. - """ - return list(self.source_media_types) - - def get_url_types(self): - """ - Return a list of all custom names types assocated with Url instances - in the database. - """ - return list(self.url_types) - - def get_place_types(self): - """ - Return a list of all custom place types assocated with Place instances - in the database. - """ - return list(self.place_types) - - def get_event_bookmarks(self): - return self.event_bookmarks - - def get_family_bookmarks(self): - return self.family_bookmarks - - def get_media_bookmarks(self): - return self.media_bookmarks - - def get_note_bookmarks(self): - return self.note_bookmarks - - def get_place_bookmarks(self): - return self.place_bookmarks - - def get_repo_bookmarks(self): - return self.repo_bookmarks - - def get_save_path(self): - return self._directory - - def get_source_bookmarks(self): - return self.source_bookmarks - - def is_open(self): - return self._directory is not None - - def iter_citation_handles(self): - return (data[0] for data in self.get_citation_cursor()) - - def iter_citations(self): - return (Citation.create(data[1]) for data in self.get_citation_cursor()) - - def iter_event_handles(self): - return (data[0] for data in self.get_event_cursor()) - - def iter_events(self): - return (Event.create(data[1]) for data in self.get_event_cursor()) - - def iter_media_objects(self): - return (MediaObject.create(data[1]) for data in self.get_media_cursor()) - - def iter_note_handles(self): - return (data[0] for data in self.get_note_cursor()) - - def iter_notes(self): - return (Note.create(data[1]) for data in self.get_note_cursor()) - - def iter_place_handles(self): - return (data[0] for data in self.get_place_cursor()) - - def iter_places(self): - return (Place.create(data[1]) for data in self.get_place_cursor()) - - def iter_repositories(self): - return (Repository.create(data[1]) for data in self.get_repository_cursor()) - - def iter_repository_handles(self): - return (data[0] for data in self.get_repository_cursor()) - - def iter_source_handles(self): - return (data[0] for data in self.get_source_cursor()) - - def iter_sources(self): - return (Source.create(data[1]) for data in self.get_source_cursor()) - - def iter_tag_handles(self): - return (data[0] for data in self.get_tag_cursor()) - - def iter_tags(self): - return (Tag.create(data[1]) for data in self.get_tag_cursor()) - - def load(self, directory, callback=None, mode=None, - force_schema_upgrade=False, - force_bsddb_upgrade=False, - force_bsddb_downgrade=False, - force_python_upgrade=False): - # Run code from directory - default_settings = {"__file__": - os.path.join(directory, "default_settings.py")} - settings_file = os.path.join(directory, "default_settings.py") - with open(settings_file) as f: - code = compile(f.read(), settings_file, 'exec') - exec(code, globals(), default_settings) - - self.dbapi = default_settings["dbapi"] - - # make sure schema is up to date: - self.dbapi.execute("""CREATE TABLE IF NOT EXISTS person ( - handle TEXT PRIMARY KEY NOT NULL, - order_by TEXT , - gramps_id TEXT , - blob TEXT - );""") - self.dbapi.execute("""CREATE TABLE IF NOT EXISTS family ( - handle TEXT PRIMARY KEY NOT NULL, - gramps_id TEXT , - blob TEXT - );""") - self.dbapi.execute("""CREATE TABLE IF NOT EXISTS source ( - handle TEXT PRIMARY KEY NOT NULL, - order_by TEXT , - gramps_id TEXT , - blob TEXT - );""") - self.dbapi.execute("""CREATE TABLE IF NOT EXISTS citation ( - handle TEXT PRIMARY KEY NOT NULL, - order_by TEXT , - gramps_id TEXT , - blob TEXT - );""") - self.dbapi.execute("""CREATE TABLE IF NOT EXISTS event ( - handle TEXT PRIMARY KEY NOT NULL, - gramps_id TEXT , - blob TEXT - );""") - self.dbapi.execute("""CREATE TABLE IF NOT EXISTS media ( - handle TEXT PRIMARY KEY NOT NULL, - order_by TEXT , - gramps_id TEXT , - blob TEXT - );""") - self.dbapi.execute("""CREATE TABLE IF NOT EXISTS place ( - handle TEXT PRIMARY KEY NOT NULL, - order_by TEXT , - gramps_id TEXT , - blob TEXT - );""") - self.dbapi.execute("""CREATE TABLE IF NOT EXISTS repository ( - handle TEXT PRIMARY KEY NOT NULL, - gramps_id TEXT , - blob TEXT - );""") - self.dbapi.execute("""CREATE TABLE IF NOT EXISTS note ( - handle TEXT PRIMARY KEY NOT NULL, - gramps_id TEXT , - blob TEXT - );""") - self.dbapi.execute("""CREATE TABLE IF NOT EXISTS tag ( - handle TEXT PRIMARY KEY NOT NULL, - order_by TEXT , - blob TEXT - );""") - # Secondary: - self.dbapi.execute("""CREATE TABLE IF NOT EXISTS reference ( - obj_handle TEXT, - obj_class TEXT, - ref_handle TEXT, - ref_class TEXT - );""") - self.dbapi.execute("""CREATE TABLE IF NOT EXISTS name_group ( - name TEXT PRIMARY KEY NOT NULL, - grouping TEXT - );""") - self.dbapi.execute("""CREATE TABLE IF NOT EXISTS metadata ( - setting TEXT PRIMARY KEY NOT NULL, - value TEXT - );""") - ## Indices: - self.dbapi.execute("""CREATE INDEX IF NOT EXISTS - order_by ON person (order_by); - """) - self.dbapi.execute("""CREATE INDEX IF NOT EXISTS - order_by ON source (order_by); - """) - self.dbapi.execute("""CREATE INDEX IF NOT EXISTS - order_by ON citation (order_by); - """) - self.dbapi.execute("""CREATE INDEX IF NOT EXISTS - order_by ON media (order_by); - """) - self.dbapi.execute("""CREATE INDEX IF NOT EXISTS - order_by ON place (order_by); - """) - self.dbapi.execute("""CREATE INDEX IF NOT EXISTS - order_by ON tag (order_by); - """) - self.dbapi.execute("""CREATE INDEX IF NOT EXISTS - ref_handle ON reference (ref_handle); - """) - # Load metadata - self.bookmarks.set(self.get_metadata('bookmarks')) - self.family_bookmarks.set(self.get_metadata('family_bookmarks')) - self.event_bookmarks.set(self.get_metadata('event_bookmarks')) - self.source_bookmarks.set(self.get_metadata('source_bookmarks')) - self.citation_bookmarks.set(self.get_metadata('citation_bookmarks')) - self.repo_bookmarks.set(self.get_metadata('repo_bookmarks')) - self.media_bookmarks.set(self.get_metadata('media_bookmarks')) - self.place_bookmarks.set(self.get_metadata('place_bookmarks')) - self.note_bookmarks.set(self.get_metadata('note_bookmarks')) - - # Custom type values - self.event_names = self.get_metadata('event_names', set()) - self.family_attributes = self.get_metadata('fattr_names', set()) - self.individual_attributes = self.get_metadata('pattr_names', set()) - self.source_attributes = self.get_metadata('sattr_names', set()) - self.marker_names = self.get_metadata('marker_names', set()) - self.child_ref_types = self.get_metadata('child_refs', set()) - self.family_rel_types = self.get_metadata('family_rels', set()) - self.event_role_names = self.get_metadata('event_roles', set()) - self.name_types = self.get_metadata('name_types', set()) - self.origin_types = self.get_metadata('origin_types', set()) - self.repository_types = self.get_metadata('repo_types', set()) - self.note_types = self.get_metadata('note_types', set()) - self.source_media_types = self.get_metadata('sm_types', set()) - self.url_types = self.get_metadata('url_types', set()) - self.media_attributes = self.get_metadata('mattr_names', set()) - self.event_attributes = self.get_metadata('eattr_names', set()) - self.place_types = self.get_metadata('place_types', set()) - - # surname list - self.surname_list = self.get_metadata('surname_list') - - self.set_save_path(directory) - self.undolog = os.path.join(self._directory, DBUNDOFN) - self.undodb = DBAPIUndo(self, self.undolog) - self.undodb.open() - - def set_prefixes(self, person, media, family, source, citation, - place, event, repository, note): - self.set_person_id_prefix(person) - self.set_object_id_prefix(media) - self.set_family_id_prefix(family) - self.set_source_id_prefix(source) - self.set_citation_id_prefix(citation) - self.set_place_id_prefix(place) - self.set_event_id_prefix(event) - self.set_repository_id_prefix(repository) - self.set_note_id_prefix(note) - - def set_save_path(self, directory): - self._directory = directory - if directory: - self.full_name = os.path.abspath(self._directory) - self.path = self.full_name - self.brief_name = os.path.basename(self._directory) - else: - self.full_name = None - self.path = None - self.brief_name = None - - def write_version(self, directory): - """Write files for a newly created DB.""" - versionpath = os.path.join(directory, str(DBBACKEND)) - _LOG.debug("Write database backend file to 'dbapi'") - with open(versionpath, "w") as version_file: - version_file.write("dbapi") - # Write default_settings, sqlite.db - defaults = os.path.join(os.path.dirname(os.path.abspath(__file__)), - "dbapi_support", "defaults") - _LOG.debug("Copy defaults from: " + defaults) - for filename in os.listdir(defaults): - fullpath = os.path.abspath(os.path.join(defaults, filename)) - shutil.copy2(fullpath, directory) - - def report_bm_change(self): - """ - Add 1 to the number of bookmark changes during this session. - """ - self._bm_changes += 1 - - def db_has_bm_changes(self): - """ - Return whethere there were bookmark changes during the session. - """ - return self._bm_changes > 0 - - def get_summary(self): - """ - Returns dictionary of summary item. - Should include, if possible: - - _("Number of people") - _("Version") - _("Schema version") - """ - return { - _("Number of people"): self.get_number_of_people(), - } - - def get_dbname(self): - """ - In DBAPI, the database is in a text file at the path - """ - filepath = os.path.join(self._directory, "name.txt") - try: - name_file = open(filepath, "r") - name = name_file.readline().strip() - name_file.close() - except (OSError, IOError) as msg: - _LOG.error(str(msg)) - name = None - return name - - def reindex_reference_map(self, callback): - callback(4) - self.dbapi.execute("DELETE FROM reference;") - primary_table = ( - (self.get_person_cursor, Person), - (self.get_family_cursor, Family), - (self.get_event_cursor, Event), - (self.get_place_cursor, Place), - (self.get_source_cursor, Source), - (self.get_citation_cursor, Citation), - (self.get_media_cursor, MediaObject), - (self.get_repository_cursor, Repository), - (self.get_note_cursor, Note), - (self.get_tag_cursor, Tag), - ) - # Now we use the functions and classes defined above - # to loop through each of the primary object tables. - for cursor_func, class_func in primary_table: - logging.info("Rebuilding %s reference map" % - class_func.__name__) - with cursor_func() as cursor: - for found_handle, val in cursor: - obj = class_func.create(val) - references = set(obj.get_referenced_handles_recursively()) - # handle addition of new references - for (ref_class_name, ref_handle) in references: - self.dbapi.execute("""INSERT INTO reference (obj_handle, obj_class, ref_handle, ref_class) - VALUES(?, ?, ?, ?);""", - [obj.handle, - obj.__class__.__name__, - ref_handle, - ref_class_name]) - - self.dbapi.commit() - callback(5) - - def rebuild_secondary(self, update): - pass - # FIXME: rebuild the secondary databases/maps: - ## gender stats - ## event_names - ## fattr_names - ## pattr_names - ## sattr_names - ## marker_names - ## child_refs - ## family_rels - ## event_roles - ## name_types - ## origin_types - ## repo_types - ## note_types - ## sm_types - ## url_types - ## mattr_names - ## eattr_names - ## place_types - # surname list - - def prepare_import(self): - """ - Do anything needed before an import. - """ - pass - - def commit_import(self): - """ - Do anything needed after an import. - """ - self.reindex_reference_map(lambda n: n) - - def has_handle_for_person(self, key): - cur = self.dbapi.execute("SELECT * FROM person WHERE handle = ?", [key]) - return cur.fetchone() != None - - def has_handle_for_family(self, key): - cur = self.dbapi.execute("SELECT * FROM family WHERE handle = ?", [key]) - return cur.fetchone() != None - - def has_handle_for_source(self, key): - cur = self.dbapi.execute("SELECT * FROM source WHERE handle = ?", [key]) - return cur.fetchone() != None - - def has_handle_for_citation(self, key): - cur = self.dbapi.execute("SELECT * FROM citation WHERE handle = ?", [key]) - return cur.fetchone() != None - - def has_handle_for_event(self, key): - cur = self.dbapi.execute("SELECT * FROM event WHERE handle = ?", [key]) - return cur.fetchone() != None - - def has_handle_for_media(self, key): - cur = self.dbapi.execute("SELECT * FROM media WHERE handle = ?", [key]) - return cur.fetchone() != None - - def has_handle_for_place(self, key): - cur = self.dbapi.execute("SELECT * FROM place WHERE handle = ?", [key]) - return cur.fetchone() != None - - def has_handle_for_repository(self, key): - cur = self.dbapi.execute("SELECT * FROM repository WHERE handle = ?", [key]) - return cur.fetchone() != None - - def has_handle_for_note(self, key): - cur = self.dbapi.execute("SELECT * FROM note WHERE handle = ?", [key]) - return cur.fetchone() != None - - def has_handle_for_tag(self, key): - cur = self.dbapi.execute("SELECT * FROM tag WHERE handle = ?", [key]) - return cur.fetchone() != None - - def has_gramps_id_for_person(self, key): - cur = self.dbapi.execute("SELECT * FROM person WHERE gramps_id = ?", [key]) - return cur.fetchone() != None - - def has_gramps_id_for_family(self, key): - cur = self.dbapi.execute("SELECT * FROM family WHERE gramps_id = ?", [key]) - return cur.fetchone() != None - - def has_gramps_id_for_source(self, key): - cur = self.dbapi.execute("SELECT * FROM source WHERE gramps_id = ?", [key]) - return cur.fetchone() != None - - def has_gramps_id_for_citation(self, key): - cur = self.dbapi.execute("SELECT * FROM citation WHERE gramps_id = ?", [key]) - return cur.fetchone() != None - - def has_gramps_id_for_event(self, key): - cur = self.dbapi.execute("SELECT * FROM event WHERE gramps_id = ?", [key]) - return cur.fetchone() != None - - def has_gramps_id_for_media(self, key): - cur = self.dbapi.execute("SELECT * FROM media WHERE gramps_id = ?", [key]) - return cur.fetchone() != None - - def has_gramps_id_for_place(self, key): - cur = self.dbapi.execute("SELECT * FROM place WHERE gramps_id = ?", [key]) - return cur.fetchone() != None - - def has_gramps_id_for_repository(self, key): - cur = self.dbapi.execute("SELECT * FROM repository WHERE gramps_id = ?", [key]) - return cur.fetchone() != None - - def has_gramps_id_for_note(self, key): - cur = self.dbapi.execute("SELECT * FROM note WHERE gramps_id = ?", [key]) - return cur.fetchone() != None - - def get_person_gramps_ids(self): - cur = self.dbapi.execute("SELECT gramps_id FROM person;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_family_gramps_ids(self): - cur = self.dbapi.execute("SELECT gramps_id FROM family;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_source_gramps_ids(self): - cur = self.dbapi.execute("SELECT gramps_id FROM source;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_citation_gramps_ids(self): - cur = self.dbapi.execute("SELECT gramps_id FROM citation;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_event_gramps_ids(self): - cur = self.dbapi.execute("SELECT gramps_id FROM event;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_media_gramps_ids(self): - cur = self.dbapi.execute("SELECT gramps_id FROM media;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_place_gramps_ids(self): - cur = self.dbapi.execute("SELECT gramps FROM place;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_repository_gramps_ids(self): - cur = self.dbapi.execute("SELECT gramps_id FROM repository;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def get_note_gramps_ids(self): - cur = self.dbapi.execute("SELECT gramps_id FROM note;") - rows = cur.fetchall() - return [row[0] for row in rows] - - def _get_raw_person_data(self, key): - cur = self.dbapi.execute("SELECT blob FROM person WHERE handle = ?", [key]) - row = cur.fetchone() - if row: - return pickle.loads(row[0]) - - def _get_raw_family_data(self, key): - cur = self.dbapi.execute("SELECT blob FROM family WHERE handle = ?", [key]) - row = cur.fetchone() - if row: - return pickle.loads(row[0]) - - def _get_raw_source_data(self, key): - cur = self.dbapi.execute("SELECT blob FROM source WHERE handle = ?", [key]) - row = cur.fetchone() - if row: - return pickle.loads(row[0]) - - def _get_raw_citation_data(self, key): - cur = self.dbapi.execute("SELECT blob FROM citation WHERE handle = ?", [key]) - row = cur.fetchone() - if row: - return pickle.loads(row[0]) - - def _get_raw_event_data(self, key): - cur = self.dbapi.execute("SELECT blob FROM event WHERE handle = ?", [key]) - row = cur.fetchone() - if row: - return pickle.loads(row[0]) - - def _get_raw_media_data(self, key): - cur = self.dbapi.execute("SELECT blob FROM media WHERE handle = ?", [key]) - row = cur.fetchone() - if row: - return pickle.loads(row[0]) - - def _get_raw_place_data(self, key): - cur = self.dbapi.execute("SELECT blob FROM place WHERE handle = ?", [key]) - row = cur.fetchone() - if row: - return pickle.loads(row[0]) - - def _get_raw_repository_data(self, key): - cur = self.dbapi.execute("SELECT blob FROM repository WHERE handle = ?", [key]) - row = cur.fetchone() - if row: - return pickle.loads(row[0]) - - def _get_raw_note_data(self, key): - cur = self.dbapi.execute("SELECT blob FROM note WHERE handle = ?", [key]) - row = cur.fetchone() - if row: - return pickle.loads(row[0]) - - def _get_raw_tag_data(self, key): - cur = self.dbapi.execute("SELECT blob FROM tag WHERE handle = ?", [key]) - row = cur.fetchone() - if row: - return pickle.loads(row[0]) - - def _order_by_person_key(self, person): - """ - All non pa/matronymic surnames are used in indexing. - pa/matronymic not as they change for every generation! - returns a byte string - """ - if person.primary_name and person.primary_name.surname_list: - order_by = " ".join([x.surname for x in person.primary_name.surname_list if not - (int(x.origintype) in [NameOriginType.PATRONYMIC, - NameOriginType.MATRONYMIC]) ]) - else: - order_by = "" - return glocale.sort_key(order_by) - - def _order_by_place_key(self, place): - return glocale.sort_key(place.title) - - def _order_by_source_key(self, source): - return glocale.sort_key(source.title) - - def _order_by_citation_key(self, citation): - return glocale.sort_key(citation.page) - - def _order_by_media_key(self, media): - return glocale.sort_key(media.desc) - - def _order_by_tag_key(self, tag): - return glocale.sort_key(tag.get_name()) - - def backup(self): - """ - If you wish to support an optional backup routine, put it here. - """ - from gramps.plugins.export.exportxml import XmlWriter - from gramps.cli.user import User - writer = XmlWriter(self, User(), strip_photos=0, compress=1) - filename = os.path.join(self._directory, "data.gramps") - writer.write(filename) - - def restore(self): - """ - If you wish to support an optional restore routine, put it here. - """ - pass - - def get_undodb(self): - return self.undodb - - def undo(self, update_history=True): - return self.undodb.undo(update_history) - - def redo(self, update_history=True): - return self.undodb.redo(update_history) - - def get_dbid(self): - """ - We use the file directory name as the unique ID for - this database on this computer. - """ - return self.brief_name diff --git a/gramps/plugins/database/dbapi_support/defaults/default_settings.py b/gramps/plugins/database/dbapi_support/defaults/default_settings.py deleted file mode 100644 index 8931c8e89..000000000 --- a/gramps/plugins/database/dbapi_support/defaults/default_settings.py +++ /dev/null @@ -1,7 +0,0 @@ -import os -import sqlite3 - -path_to_db = os.path.join(os.path.dirname(os.path.realpath(__file__)), - 'sqlite.db') -dbapi = sqlite3.connect(path_to_db) -dbapi.row_factory = sqlite3.Row # allows access by name diff --git a/gramps/plugins/database/dictionarydb.gpr.py b/gramps/plugins/database/dictionarydb.gpr.py index 3b0e62eca..d035de58a 100644 --- a/gramps/plugins/database/dictionarydb.gpr.py +++ b/gramps/plugins/database/dictionarydb.gpr.py @@ -24,7 +24,7 @@ plg.name = _("Dictionary Database Backend") plg.name_accell = _("Di_ctionary Database Backend") plg.description = _("Dictionary (in-memory) Database Backend") plg.version = '1.0' -plg.gramps_target_version = "4.2" +plg.gramps_target_version = "5.0" plg.status = STABLE plg.fname = 'dictionarydb.py' plg.ptype = DATABASE diff --git a/gramps/plugins/database/django_support/defaults/default_settings.py b/gramps/plugins/database/django_support/defaults/default_settings.py deleted file mode 100644 index fae3ffd06..000000000 --- a/gramps/plugins/database/django_support/defaults/default_settings.py +++ /dev/null @@ -1,150 +0,0 @@ -import os -from gramps.gen.const import DATA_DIR - -WEB_DIR = os.path.dirname(os.path.realpath(__file__)) - -DEBUG = True -TEMPLATE_DEBUG = DEBUG - -INTERNAL_IPS = ('127.0.0.1',) - -ADMINS = ( - ('admin', 'your_email@domain.com'), -) - -MANAGERS = ADMINS -DATABASE_ROUTERS = [] -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(WEB_DIR, 'sqlite.db'), - } -} -DATABASE_ENGINE = 'sqlite3' -DATABASE_NAME = os.path.join(WEB_DIR, 'sqlite.db') -DATABASE_USER = '' -DATABASE_PASSWORD = '' -DATABASE_HOST = '' -DATABASE_PORT = '' -TIME_ZONE = 'America/New_York' -LANGUAGE_CODE = 'en-us' -SITE_ID = 1 -USE_I18N = True -MEDIA_ROOT = '' -MEDIA_URL = '' -ADMIN_MEDIA_PREFIX = '/gramps-media/' -SECRET_KEY = 'zd@%vslj5sqhx94_8)0hsx*rk9tj3^ly$x+^*tq4bggr&uh$ac' - -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', # 1.4 - 'django.template.loaders.app_directories.Loader', # 1.4 - #'django.template.loaders.filesystem.load_template_source', - #'django.template.loaders.app_directories.load_template_source', -) - -MIDDLEWARE_CLASSES = ( - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', -# 'debug_toolbar.middleware.DebugToolbarMiddleware', -) - -ROOT_URLCONF = 'gramps.webapp.urls' -STATIC_URL = '/static/' # 1.4 - -TEMPLATE_DIRS = ( - # Use absolute paths, not relative paths. - os.path.join(DATA_DIR, "templates"), -) - -TEMPLATE_CONTEXT_PROCESSORS = ( - "django.contrib.auth.context_processors.auth", # 1.4 - "django.contrib.messages.context_processors.messages", # 1.4 -# "django.core.context_processors.auth", -# "django.core.context_processors.debug", - "django.core.context_processors.i18n", - "django.core.context_processors.media", - "gramps.webapp.grampsdb.views.context_processor", - "gramps.webapp.context.messages", -) - -INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.staticfiles', - 'django.contrib.messages', # 1.4 - 'django.contrib.sites', - 'django.contrib.admin', - 'gramps.webapp.grampsdb', -# 'django_extensions', -# 'debug_toolbar', -) - -DEBUG_TOOLBAR_PANELS = ( - 'debug_toolbar.panels.version.VersionDebugPanel', - 'debug_toolbar.panels.timer.TimerDebugPanel', - 'debug_toolbar.panels.settings_vars.SettingsVarsDebugPanel', - 'debug_toolbar.panels.headers.HeaderDebugPanel', - 'debug_toolbar.panels.request_vars.RequestVarsDebugPanel', - 'debug_toolbar.panels.template.TemplateDebugPanel', - 'debug_toolbar.panels.sql.SQLDebugPanel', - 'debug_toolbar.panels.signals.SignalDebugPanel', - 'debug_toolbar.panels.logger.LoggingPanel', - ) - -def custom_show_toolbar(request): - return True # Always show toolbar, for example purposes only. - -DEBUG_TOOLBAR_CONFIG = { - 'INTERCEPT_REDIRECTS': False, -# 'SHOW_TOOLBAR_CALLBACK': custom_show_toolbar, -# 'EXTRA_SIGNALS': ['myproject.signals.MySignal'], - 'HIDE_DJANGO_SQL': False, - } - -AUTH_PROFILE_MODULE = "grampsdb.Profile" - -# Had to add these to use settings.configure(): -DATABASE_OPTIONS = '' -URL_VALIDATOR_USER_AGENT = '' -DEFAULT_INDEX_TABLESPACE = '' -DEFAULT_TABLESPACE = '' -CACHE_BACKEND = 'locmem://' -TRANSACTIONS_MANAGED = False -LOCALE_PATHS = tuple() - -# Changes for Django 1.3: -USE_L10N = True -FORMAT_MODULE_PATH = "" -## End Changes for Django 1.3 - -# Changes for Django 1.4: -USE_TZ = False -## End Changes for Django 1.4 - -# Changes for Django 1.5: -CACHES = { - 'default': { - 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', - } - } -DEFAULT_CHARSET = "utf-8" -## End Changes for Django 1.5 - -## Changes for Django 1.5.4: -LOGGING_CONFIG = None -AUTH_USER_MODEL = 'auth.User' -## End Changes for Django 1.5.4 - -LOGIN_URL = "/login/" -LOGOUT_URL = "/logout" -LOGIN_REDIRECT_URL = "/" - -## Changes for Django 1.6: -LOGGING = None - -## Changes for Django 1.7.1: -ABSOLUTE_URL_OVERRIDES = {} diff --git a/gramps/plugins/database/django_support/defaults/sqlite.db b/gramps/plugins/database/django_support/defaults/sqlite.db deleted file mode 100644 index a9ac911f065f752dfb25be75e2916ff5df508451..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 293888 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®`N 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 N%rWbcAX@iQ{{@Gr__6>1 diff --git a/gramps/plugins/database/django_support/libdjango.py b/gramps/plugins/database/django_support/libdjango.py deleted file mode 100644 index fa0a596c8..000000000 --- a/gramps/plugins/database/django_support/libdjango.py +++ /dev/null @@ -1,2063 +0,0 @@ -# Gramps - a GTK+/GNOME based genealogy program -# -# Copyright (C) 2009 Douglas S. Blank -# -# 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. -# - -""" Interface to Django models """ - -#------------------------------------------------------------------------ -# -# Python Modules -# -#------------------------------------------------------------------------ -import time -import sys -import pickle -import base64 -import collections - -#------------------------------------------------------------------------ -# -# Django Modules -# -#------------------------------------------------------------------------ -from django.contrib.contenttypes.models import ContentType -from django.db import transaction - -#------------------------------------------------------------------------ -# -# Gramps Modules -# -#------------------------------------------------------------------------ -import gramps.webapp.grampsdb.models as models -from gramps.gen.lib import Name -from gramps.gen.utils.id import create_id -from gramps.gen.constfunc import conv_to_unicode - -# To get a django person from a django database: -# djperson = dji.Person.get(handle='djhgsdh324hjg234hj24') -# -# To turn the djperson into a Gramps Person: -# tuple = dji.get_person(djperson) -# gperson = lib.gen.Person(tuple) -# OR -# gperson = dbdjango.DbDjango().get_person_from_handle(handle) - -def check_diff(item, raw): - encoded = str(base64.encodebytes(pickle.dumps(raw)), "utf-8") - if item.cache != encoded: - print("Different:", item.__class__.__name__, item.gramps_id) - print("raw :", raw) - print("cache:", item.from_cache()) - # FIXING, TOO: - item.save_cache() - -#------------------------------------------------------------------------- -# -# Import functions -# -#------------------------------------------------------------------------- -def lookup_role_index(role0, event_ref_list): - """ - Find the handle in a unserialized event_ref_list and return code. - """ - if role0 is None: - return -1 - else: - count = 0 - for event_ref in event_ref_list: - (private, note_list, attribute_list, ref, erole) = event_ref - try: - event = models.Event.objects.get(handle=ref) - except: - return -1 - if event.event_type[0] == role0: - return count - count += 1 - return -1 - -def totime(dtime): - if dtime: - return int(time.mktime(dtime.timetuple())) - else: - return 0 - -#------------------------------------------------------------------------- -# -# Export functions -# -#------------------------------------------------------------------------- -def todate(t): - return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(t)) - -def lookup(index, event_ref_list): - """ - Get the unserialized event_ref in an list of them and return it. - """ - if index < 0: - return None - else: - count = 0 - for event_ref in event_ref_list: - (private, note_list, attribute_list, ref, role) = event_ref - if index == count: - return ref - count += 1 - return None - -def get_datamap(grampsclass): - return [x[0] for x in grampsclass._DATAMAP if x[0] != grampsclass.CUSTOM] - -#------------------------------------------------------------------------- -# -# Django Interface -# -#------------------------------------------------------------------------- -class DjangoInterface(object): - """ - DjangoInterface for interoperating between Gramps and Django. - - This interface comes in a number of parts: - get_ITEMS() - add_ITEMS() - - get_ITEM(ITEM) - - Given an ITEM from a Django table, construct a Gramps Raw Data tuple. - - add_ITEM(data) - - Given a Gramps Raw Data tuple, add the data to the Django tables. - - - """ - def __init__(self): - self.debug = 0 - - def __getattr__(self, name): - """ - Django Objects database interface. - - >>> self.Person.all() - >>> self.Person.get(id=1) - >>> self.Person.get(handle='gh71234dhf3746347734') - """ - if hasattr(models, name): - return getattr(models, name).objects - else: - raise AttributeError("no such model: '%s'" % name) - - def get_next_id(self, obj, prefix): - """ - Get next gramps_id - - >>> dji.get_next_id(Person, "P") - 'P0002' - >>> dji.get_next_id(Media, "M") - 'M2349' - """ - ids = [o["gramps_id"] for o in obj.objects.values("gramps_id")] - count = 1 - while "%s%04d" % (prefix, count) in ids: - count += 1 - return "%s%04d" % (prefix, count) - - def get_model(self, name): - if hasattr(models, name): - return getattr(models, name) - elif hasattr(models, name.title()): - return getattr(models, name.title()) - else: - raise AttributeError("no such model: '%s'" % name) - - # ----------------------------------------------- - # Get methods to retrieve list data from the tables - # ----------------------------------------------- - - def clear_tables(self, *args): - return models.clear_tables(*args) - - def get_tag_list(self, obj): - return obj.get_tag_list() - - def get_attribute_list(self, obj): - obj_type = ContentType.objects.get_for_model(obj) - attribute_list = models.Attribute.objects.filter(object_id=obj.id, - object_type=obj_type) - return list(map(self.pack_attribute, attribute_list)) - - def get_primary_name(self, person): - names = person.name_set.filter(preferred=True).order_by("order") - if len(names) > 0: - return Name.create(self.pack_name(names[0])) - else: - return Name() - - def get_alternate_names(self, person): - names = person.name_set.filter(preferred=False).order_by("order") - return [Name.create(self.pack_name(n)) for n in names] - - def get_names(self, person, preferred): - names = person.name_set.filter(preferred=preferred).order_by("order") - if preferred: - if len(names) > 0: - return self.pack_name(names[0]) - else: - return Name().serialize() - else: - return list(map(self.pack_name, names)) - - def get_source_attribute_list(self, source): - return [(map.private, map.key, map.value) for map in source.sourceattribute_set.all().order_by("order")] - - def get_citation_attribute_list(self, citation): - return [(map.private, map.key, map.value) for map in citation.citationattribute_set.all().order_by("order")] - - def get_media_list(self, obj): - obj_type = ContentType.objects.get_for_model(obj) - mediarefs = models.MediaRef.objects.filter(object_id=obj.id, - object_type=obj_type) - return list(map(self.pack_media_ref, mediarefs)) - - def get_note_list(self, obj): - obj_type = ContentType.objects.get_for_model(obj) - noterefs = models.NoteRef.objects.filter(object_id=obj.id, - object_type=obj_type) - return [noteref.ref_object.handle for noteref in noterefs] - - def get_repository_ref_list(self, obj): - obj_type = ContentType.objects.get_for_model(obj) - reporefs = models.RepositoryRef.objects.filter(object_id=obj.id, - object_type=obj_type) - return list(map(self.pack_repository_ref, reporefs)) - - def get_place_ref_list(self, obj): - obj_type = ContentType.objects.get_for_model(obj) - refs = models.PlaceRef.objects.filter(object_id=obj.id, - object_type=obj_type) - return list(map(self.pack_place_ref, refs)) - - def get_url_list(self, obj): - return list(map(self.pack_url, obj.url_set.all().order_by("order"))) - - def get_address_list(self, obj, with_parish): # person or repository - addresses = obj.address_set.all().order_by("order") - return [self.pack_address(address, with_parish) - for address in addresses] - - def get_child_ref_list(self, family): - obj_type = ContentType.objects.get_for_model(family) - childrefs = models.ChildRef.objects.filter(object_id=family.id, - object_type=obj_type).order_by("order") - return list(map(self.pack_child_ref, childrefs)) - - def get_citation_list(self, obj): - obj_type = ContentType.objects.get_for_model(obj) - citationrefs = models.CitationRef.objects.filter(object_id=obj.id, - object_type=obj_type).order_by("order") - return [citationref.citation.handle for citationref in citationrefs] - - def get_event_refs(self, obj, order="order"): - obj_type = ContentType.objects.get_for_model(obj) - eventrefs = models.EventRef.objects.filter(object_id=obj.id, - object_type=obj_type).order_by(order) - return eventrefs - - def get_event_ref_list(self, obj): - obj_type = ContentType.objects.get_for_model(obj) - eventrefs = models.EventRef.objects.filter(object_id=obj.id, - object_type=obj_type).order_by("order") - return list(map(self.pack_event_ref, eventrefs)) - - def get_family_list(self, person): # person has families - return [fam.family.handle for fam in - models.MyFamilies.objects.filter(person=person).order_by("order")] - - def get_parent_family_list(self, person): # person's parents has families - return [fam.family.handle for fam in - models.MyParentFamilies.objects.filter(person=person).order_by("order")] - - def get_person_ref_list(self, person): - obj_type = ContentType.objects.get_for_model(person) - return list(map(self.pack_person_ref, - models.PersonRef.objects.filter(object_id=person.id, - object_type=obj_type))) - - def get_lds_list(self, obj): # person or family - return list(map(self.pack_lds, obj.lds_set.all().order_by("order"))) - - def get_place_handle(self, obj): # obj is event - if obj.place: - return obj.place.handle - return '' - - ## Packers: - - def get_event(self, event): - handle = event.handle - gid = event.gramps_id - the_type = tuple(event.event_type) - description = event.description - change = totime(event.last_changed) - private = event.private - note_list = self.get_note_list(event) - citation_list = self.get_citation_list(event) - media_list = self.get_media_list(event) - attribute_list = self.get_attribute_list(event) - date = self.get_date(event) - place_handle = self.get_place_handle(event) - tag_list = self.get_tag_list(event) - return (str(handle), gid, the_type, date, description, place_handle, - citation_list, note_list, media_list, attribute_list, - change, tag_list, private) - - def get_note_markup(self, note): - retval = [] - markups = models.Markup.objects.filter(note=note).order_by("order") - for markup in markups: - if markup.string and markup.string.isdigit(): - value = int(markup.string) - else: - value = markup.string - start_stop_list = markup.start_stop_list - ss_list = eval(start_stop_list) - retval += [(tuple(markup.styled_text_tag_type), value, ss_list)] - return retval - - def get_tag(self, tag): - changed = totime(tag.last_changed) - return (str(tag.handle), - tag.name, - tag.color, - tag.priority, - changed) - - def get_note(self, note): - styled_text = [note.text, self.get_note_markup(note)] - changed = totime(note.last_changed) - tag_list = self.get_tag_list(note) - return (str(note.handle), - note.gramps_id, - styled_text, - note.preformatted, - tuple(note.note_type), - changed, - tag_list, - note.private) - - def get_family(self, family): - child_ref_list = self.get_child_ref_list(family) - event_ref_list = self.get_event_ref_list(family) - media_list = self.get_media_list(family) - attribute_list = self.get_attribute_list(family) - lds_seal_list = self.get_lds_list(family) - citation_list = self.get_citation_list(family) - note_list = self.get_note_list(family) - tag_list = self.get_tag_list(family) - if family.father: - father_handle = family.father.handle - else: - father_handle = '' - if family.mother: - mother_handle = family.mother.handle - else: - mother_handle = '' - return (str(family.handle), family.gramps_id, - father_handle, mother_handle, - child_ref_list, tuple(family.family_rel_type), - event_ref_list, media_list, - attribute_list, lds_seal_list, - citation_list, note_list, - totime(family.last_changed), - tag_list, - family.private) - - def get_repository(self, repository): - note_list = self.get_note_list(repository) - address_list = self.get_address_list(repository, with_parish=False) - url_list = self.get_url_list(repository) - tag_list = self.get_tag_list(repository) - return (str(repository.handle), - repository.gramps_id, - tuple(repository.repository_type), - repository.name, - note_list, - address_list, - url_list, - totime(repository.last_changed), - tag_list, - repository.private) - - def get_citation(self, citation): - note_list = self.get_note_list(citation) - media_list = self.get_media_list(citation) - attribute_list = self.get_citation_attribute_list(citation) - tag_list = self.get_tag_list(citation) - date = self.get_date(citation) - # I guess citations can have no source - if citation.source: - handle = citation.source.handle - else: - handle = None - return (str(citation.handle), - citation.gramps_id, - date, - citation.page, - citation.confidence, - handle, - note_list, - media_list, - attribute_list, - totime(citation.last_changed), - tag_list, - citation.private) - - def get_source(self, source): - note_list = self.get_note_list(source) - media_list = self.get_media_list(source) - attribute_list = self.get_source_attribute_list(source) - reporef_list = self.get_repository_ref_list(source) - tag_list = self.get_tag_list(source) - return (str(source.handle), - source.gramps_id, - source.title, - source.author, - source.pubinfo, - note_list, - media_list, - source.abbrev, - totime(source.last_changed), - attribute_list, - reporef_list, - tag_list, - source.private) - - def get_media(self, media): - attribute_list = self.get_attribute_list(media) - citation_list = self.get_citation_list(media) - note_list = self.get_note_list(media) - tag_list = self.get_tag_list(media) - date = self.get_date(media) - return (str(media.handle), - media.gramps_id, - conv_to_unicode(media.path, None), - str(media.mime), - str(media.desc), - media.checksum, - attribute_list, - citation_list, - note_list, - totime(media.last_changed), - date, - tag_list, - media.private) - - def get_person(self, person): - primary_name = self.get_names(person, True) # one - alternate_names = self.get_names(person, False) # list - event_ref_list = self.get_event_ref_list(person) - family_list = self.get_family_list(person) - parent_family_list = self.get_parent_family_list(person) - media_list = self.get_media_list(person) - address_list = self.get_address_list(person, with_parish=False) - attribute_list = self.get_attribute_list(person) - url_list = self.get_url_list(person) - lds_ord_list = self.get_lds_list(person) - pcitation_list = self.get_citation_list(person) - pnote_list = self.get_note_list(person) - person_ref_list = self.get_person_ref_list(person) - # This looks up the events for the first EventType given: - death_ref_index = person.death_ref_index - birth_ref_index = person.birth_ref_index - tag_list = self.get_tag_list(person) - - return (str(person.handle), - person.gramps_id, - tuple(person.gender_type)[0], - primary_name, - alternate_names, - death_ref_index, - birth_ref_index, - event_ref_list, - family_list, - parent_family_list, - media_list, - address_list, - attribute_list, - url_list, - lds_ord_list, - pcitation_list, - pnote_list, - totime(person.last_changed), - tag_list, - person.private, - person_ref_list) - - def get_date(self, obj): - if ((obj.calendar == obj.modifier == obj.quality == obj.sortval == obj.newyear == 0) and - obj.text == "" and (not obj.slash1) and (not obj.slash2) and - (obj.day1 == obj.month1 == obj.year1 == 0) and - (obj.day2 == obj.month2 == obj.year2 == 0)): - return None - elif ((not obj.slash1) and (not obj.slash2) and - (obj.day2 == obj.month2 == obj.year2 == 0)): - dateval = (obj.day1, obj.month1, obj.year1, obj.slash1) - else: - dateval = (obj.day1, obj.month1, obj.year1, obj.slash1, - obj.day2, obj.month2, obj.year2, obj.slash2) - return (obj.calendar, obj.modifier, obj.quality, dateval, - obj.text, obj.sortval, obj.newyear) - - def get_place(self, place): - locations = place.location_set.all().order_by("order") - alt_location_list = [self.pack_location(location, True) for location in locations] - url_list = self.get_url_list(place) - media_list = self.get_media_list(place) - citation_list = self.get_citation_list(place) - note_list = self.get_note_list(place) - tag_list = self.get_tag_list(place) - place_ref_list = self.get_place_ref_list(place) - return (str(place.handle), - place.gramps_id, - place.title, - place.long, - place.lat, - place_ref_list, - place.name, - [], ## FIXME: get_alt_names - tuple(place.place_type), - place.code, - alt_location_list, - url_list, - media_list, - citation_list, - note_list, - totime(place.last_changed), - tag_list, - place.private) - - # --------------------------------- - # Packers - # --------------------------------- - - ## The packers build GRAMPS raw unserialized data. - - ## Reference packers - - def pack_child_ref(self, child_ref): - citation_list = self.get_citation_list(child_ref) - note_list = self.get_note_list(child_ref) - return (child_ref.private, citation_list, note_list, child_ref.ref_object.handle, - tuple(child_ref.father_rel_type), tuple(child_ref.mother_rel_type)) - - def pack_person_ref(self, personref): - citation_list = self.get_citation_list(personref) - note_list = self.get_note_list(personref) - return (personref.private, - citation_list, - note_list, - personref.ref_object.handle, - personref.description) - - def pack_media_ref(self, media_ref): - citation_list = self.get_citation_list(media_ref) - note_list = self.get_note_list(media_ref) - attribute_list = self.get_attribute_list(media_ref) - if ((media_ref.x1 == media_ref.y1 == media_ref.x2 == media_ref.y2 == -1) or - (media_ref.x1 == media_ref.y1 == media_ref.x2 == media_ref.y2 == 0)): - role = None - else: - role = (media_ref.x1, media_ref.y1, media_ref.x2, media_ref.y2) - return (media_ref.private, citation_list, note_list, attribute_list, - media_ref.ref_object.handle, role) - - def pack_repository_ref(self, repo_ref): - note_list = self.get_note_list(repo_ref) - return (note_list, - repo_ref.ref_object.handle, - repo_ref.call_number, - tuple(repo_ref.source_media_type), - repo_ref.private) - - def pack_place_ref(self, place_ref): - date = self.get_date(place_ref) - return (place_ref.ref_object.handle, date) - - def pack_media_ref(self, media_ref): - note_list = self.get_note_list(media_ref) - attribute_list = self.get_attribute_list(media_ref) - citation_list = self.get_citation_list(media_ref) - return (media_ref.private, citation_list, note_list, attribute_list, - media_ref.ref_object.handle, (media_ref.x1, - media_ref.y1, - media_ref.x2, - media_ref.y2)) - - def pack_event_ref(self, event_ref): - note_list = self.get_note_list(event_ref) - attribute_list = self.get_attribute_list(event_ref) - return (event_ref.private, note_list, attribute_list, - event_ref.ref_object.handle, tuple(event_ref.role_type)) - - def pack_citation(self, citation): - handle = citation.handle - gid = citation.gramps_id - date = self.get_date(citation) - page = citation.page - confidence = citation.confidence - source_handle = citation.source.handle - note_list = self.get_note_list(citation) - media_list = self.get_media_list(citation) - attribute_list = self.get_citation_attribute_list(citation) - changed = totime(citation.last_changed) - private = citation.private - tag_list = self.get_tag_list(citation) - return (handle, gid, date, page, confidence, source_handle, - note_list, media_list, attribute_list, changed, tag_list, - private) - - def pack_address(self, address, with_parish): - citation_list = self.get_citation_list(address) - date = self.get_date(address) - note_list = self.get_note_list(address) - locations = address.location_set.all().order_by("order") - if len(locations) > 0: - location = self.pack_location(locations[0], with_parish) - else: - if with_parish: - location = (("", "", "", "", "", "", ""), "") - else: - location = ("", "", "", "", "", "", "") - return (address.private, citation_list, note_list, date, location) - - def pack_lds(self, lds): - citation_list = self.get_citation_list(lds) - note_list = self.get_note_list(lds) - date = self.get_date(lds) - if lds.famc: - famc = lds.famc.handle - else: - famc = None - place_handle = self.get_place_handle(lds) - return (citation_list, note_list, date, lds.lds_type[0], place_handle, - famc, lds.temple, lds.status[0], lds.private) - - def pack_source(self, source): - note_list = self.get_note_list(source) - media_list = self.get_media_list(source) - reporef_list = self.get_repository_ref_list(source) - attribute_list = self.get_source_attribute_list(source) - tag_list = self.get_tag_list(source) - return (source.handle, source.gramps_id, source.title, - source.author, source.pubinfo, - note_list, - media_list, - source.abbrev, - totime(last_changed), attribute_list, - reporef_list, - tag_list, - source.private) - - def pack_name(self, name): - citation_list = self.get_citation_list(name) - note_list = self.get_note_list(name) - date = self.get_date(name) - return (name.private, citation_list, note_list, date, - name.first_name, name.make_surname_list(), name.suffix, - name.title, tuple(name.name_type), - name.group_as, name.sort_as.val, - name.display_as.val, name.call, name.nick, - name.famnick) - - def pack_location(self, loc, with_parish): - if with_parish: - return ((loc.street, loc.locality, loc.city, loc.county, loc.state, loc.country, - loc.postal, loc.phone), loc.parish) - else: - return (loc.street, loc.locality, loc.city, loc.county, loc.state, loc.country, - loc.postal, loc.phone) - - def pack_url(self, url): - return (url.private, url.path, url.desc, tuple(url.url_type)) - - def pack_attribute(self, attribute): - citation_list = self.get_citation_list(attribute) - note_list = self.get_note_list(attribute) - return (attribute.private, - citation_list, - note_list, - tuple(attribute.attribute_type), - attribute.value) - - - ## Export lists: - - def add_child_ref_list(self, obj, ref_list): - ## Currently, only Family references children - for child_data in ref_list: - self.add_child_ref(obj, child_data) - - def add_citation_list(self, obj, citation_list): - for citation_handle in citation_list: - self.add_citation_ref(obj, citation_handle) - - def add_event_ref_list(self, obj, event_ref_list): - for event_ref in event_ref_list: - self.add_event_ref(obj, event_ref) - - def add_surname_list(self, name, surname_list): - order = 1 - for data in surname_list: - (surname_text, prefix, primary, origin_type, - connector) = data - surname = models.Surname() - surname.surname = surname_text - surname.prefix = prefix - surname.primary = primary - surname.name_origin_type = models.get_type(models.NameOriginType, - origin_type) - surname.connector = connector - surname.name = name - surname.order = order - surname.save() - order += 1 - - def add_note_list(self, obj, note_list): - for handle in note_list: - # Just the handle - try: - note = models.Note.objects.get(handle=handle) - self.add_note_ref(obj, note) - except: - print(("ERROR: Note does not exist: '%s'" % - str(handle)), file=sys.stderr) - - def add_alternate_name_list(self, person, alternate_names): - for name in alternate_names: - if name: - self.add_name(person, name, False) - - def add_parent_family_list(self, person, parent_family_list): - for parent_family_data in parent_family_list: - self.add_parent_family(person, parent_family_data) - - def add_media_ref_list(self, person, media_list): - for media_data in media_list: - self.add_media_ref(person, media_data) - - def add_attribute_list(self, obj, attribute_list): - for attribute_data in attribute_list: - self.add_attribute(obj, attribute_data) - - def add_tag_list(self, obj, tag_list): - for tag_handle in tag_list: - try: - tag = models.Tag.objects.get(handle=tag_handle) - except: - print(("ERROR: Tag does not exist: '%s'" % - str(tag_handle)), file=sys.stderr) - obj.tags.add(tag) - - def add_url_list(self, field, obj, url_list): - if not url_list: return None - count = 1 - for url_data in url_list: - self.add_url(field, obj, url_data, count) - count += 1 - - def add_person_ref_list(self, obj, person_ref_list): - for person_ref_data in person_ref_list: - self.add_person_ref(obj, person_ref_data) - - def add_address_list(self, field, obj, address_list): - count = 1 - for address_data in address_list: - self.add_address(field, obj, address_data, count) - count += 1 - - def add_lds_list(self, field, obj, lds_ord_list): - count = 1 - for ldsord in lds_ord_list: - lds = self.add_lds(field, obj, ldsord, count) - #obj.lds_list.add(lds) - #obj.save() - count += 1 - - def add_repository_ref_list(self, obj, reporef_list): - for data in reporef_list: - self.add_repository_ref(obj, data) - - def add_place_ref_list(self, obj, placeref_list): - for data in placeref_list: - self.add_place_ref(obj, data) - - def add_family_ref_list(self, person, family_list): - for family_handle in family_list: - self.add_family_ref(person, family_handle) - - def add_alt_name_list(self, place, alt_name_list): - print("FIXME: add alt_name_list!", alt_name_list) - - ## Export reference objects: - - def add_person_ref_default(self, obj, person, private=False, desc=None): - count = person.references.count() - person_ref = models.PersonRef(referenced_by=obj, - ref_object=person, - private=private, - order=count + 1, - description=desc) - person_ref.save() - - def add_person_ref(self, obj, person_ref_data): - (private, - citation_list, - note_list, - handle, - desc) = person_ref_data - try: - person = models.Person.objects.get(handle=handle) - except: - print(("ERROR: Person does not exist: '%s'" % - str(handle)), file=sys.stderr) - return - - count = person.references.count() - person_ref = models.PersonRef(referenced_by=obj, - ref_object=person, - private=private, - order=count + 1, - description=desc) - person_ref.save() - self.add_note_list(person_ref, note_list) - self.add_citation_list(person_ref, citation_list) - - def add_note_ref(self, obj, note): - count = note.references.count() - note_ref = models.NoteRef(referenced_by=obj, - ref_object=note, - private=False, - order=count + 1) - note_ref.save() - - def add_media_ref_default(self, obj, media, private=False, role=None): - count = media.references.count() - if not role: - role = (0,0,0,0) - media_ref = models.MediaRef(referenced_by=obj, - ref_object=media, - x1=role[0], - y1=role[1], - x2=role[2], - y2=role[3], - private=private, - order=count + 1) - media_ref.save() - - def add_media_ref(self, obj, media_ref_data): - (private, citation_list, note_list, attribute_list, - ref, role) = media_ref_data - try: - media = models.Media.objects.get(handle=ref) - except: - print(("ERROR: Media does not exist: '%s'" % - str(ref)), file=sys.stderr) - return - count = media.references.count() - if not role: - role = (0,0,0,0) - media_ref = models.MediaRef(referenced_by=obj, - ref_object=media, - x1=role[0], - y1=role[1], - x2=role[2], - y2=role[3], - private=private, - order=count + 1) - media_ref.save() - self.add_note_list(media_ref, note_list) - self.add_attribute_list(media_ref, attribute_list) - self.add_citation_list(media_ref, citation_list) - - def add_citation_ref_default(self, obj, citation, private=False): - object_type = ContentType.objects.get_for_model(obj) - count = models.CitationRef.objects.filter(object_id=obj.id,object_type=object_type).count() - citation_ref = models.CitationRef(private=private, - referenced_by=obj, - citation=citation, - order=count + 1) - citation_ref.save() - - def add_citation_ref(self, obj, handle): - try: - citation = models.Citation.objects.get(handle=handle) - except: - print(("ERROR: Citation does not exist: '%s'" % - str(handle)), file=sys.stderr) - return - - object_type = ContentType.objects.get_for_model(obj) - count = models.CitationRef.objects.filter(object_id=obj.id,object_type=object_type).count() - citation_ref = models.CitationRef(private=False, - referenced_by=obj, - citation=citation, - order=count + 1) - citation_ref.save() - - def add_citation(self, citation_data): - (handle, gid, date, page, confidence, source_handle, note_list, - media_list, attribute_list, changed, tag_list, private) = citation_data - citation = models.Citation( - handle=handle, - gramps_id=gid, - private=private, - last_changed=todate(changed), - confidence=confidence, - page=page) - citation.save(save_cache=False) - - def add_citation_detail(self, citation_data): - (handle, gid, date, page, confidence, source_handle, note_list, - media_list, attribute_list, change, tag_list, private) = citation_data - try: - citation = models.Citation.objects.get(handle=handle) - except: - print(("ERROR: Citation does not exist: '%s'" % - str(handle)), file=sys.stderr) - return - try: - source = models.Source.objects.get(handle=source_handle) - except: - print(("ERROR: Source does not exist: '%s'" % - str(source_handle)), file=sys.stderr) - return - citation.source = source - self.add_date(citation, date) - citation.save(save_cache=False) - self.add_note_list(citation, note_list) - self.add_media_ref_list(citation, media_list) - self.add_citation_attribute_list(citation, attribute_list) - self.add_tag_list(citation, tag_list) - citation.save_cache() - - def add_child_ref_default(self, obj, child, frel=1, mrel=1, private=False): - object_type = ContentType.objects.get_for_model(obj) # obj is family - count = models.ChildRef.objects.filter(object_id=obj.id,object_type=object_type).count() - child_ref = models.ChildRef(private=private, - referenced_by=obj, - ref_object=child, - order=count + 1, - father_rel_type=models.get_type(models.ChildRefType, frel), # birth - mother_rel_type=models.get_type(models.ChildRefType, mrel)) - child_ref.save() - - def add_child_ref(self, obj, data): - (private, citation_list, note_list, ref, frel, mrel) = data - try: - child = models.Person.objects.get(handle=ref) - except: - print(("ERROR: Person does not exist: '%s'" % - str(ref)), file=sys.stderr) - return - object_type = ContentType.objects.get_for_model(obj) - count = models.ChildRef.objects.filter(object_id=obj.id,object_type=object_type).count() - child_ref = models.ChildRef(private=private, - referenced_by=obj, - ref_object=child, - order=count + 1, - father_rel_type=models.get_type(models.ChildRefType, frel), - mother_rel_type=models.get_type(models.ChildRefType, mrel)) - child_ref.save() - self.add_citation_list(child_ref, citation_list) - self.add_note_list(child_ref, note_list) - - def add_event_ref_default(self, obj, event, private=False, role=models.EventRoleType._DEFAULT): - object_type = ContentType.objects.get_for_model(obj) - count = models.EventRef.objects.filter(object_id=obj.id,object_type=object_type).count() - event_ref = models.EventRef(private=private, - referenced_by=obj, - ref_object=event, - order=count + 1, - role_type = models.get_type(models.EventRoleType, role)) - event_ref.save() - - def add_event_ref(self, obj, event_data): - (private, note_list, attribute_list, ref, role) = event_data - try: - event = models.Event.objects.get(handle=ref) - except: - print(("ERROR: Event does not exist: '%s'" % - str(ref)), file=sys.stderr) - return - object_type = ContentType.objects.get_for_model(obj) - count = models.EventRef.objects.filter(object_id=obj.id,object_type=object_type).count() - event_ref = models.EventRef(private=private, - referenced_by=obj, - ref_object=event, - order=count + 1, - role_type = models.get_type(models.EventRoleType, role)) - event_ref.save() - self.add_note_list(event_ref, note_list) - self.add_attribute_list(event_ref, attribute_list) - - def add_repository_ref_default(self, obj, repository, private=False, call_number="", - source_media_type=models.SourceMediaType._DEFAULT): - object_type = ContentType.objects.get_for_model(obj) - count = models.RepositoryRef.objects.filter(object_id=obj.id,object_type=object_type).count() - repos_ref = models.RepositoryRef(private=private, - referenced_by=obj, - call_number=call_number, - source_media_type=models.get_type(models.SourceMediaType, - source_media_type), - ref_object=repository, - order=count + 1) - repos_ref.save() - - def add_repository_ref(self, obj, reporef_data): - (note_list, - ref, - call_number, - source_media_type, - private) = reporef_data - try: - repository = models.Repository.objects.get(handle=ref) - except: - print(("ERROR: Repository does not exist: '%s'" % - str(ref)), file=sys.stderr) - return - object_type = ContentType.objects.get_for_model(obj) - count = models.RepositoryRef.objects.filter(object_id=obj.id,object_type=object_type).count() - repos_ref = models.RepositoryRef(private=private, - referenced_by=obj, - call_number=call_number, - source_media_type=models.get_type(models.SourceMediaType, - source_media_type), - ref_object=repository, - order=count + 1) - repos_ref.save() - self.add_note_list(repos_ref, note_list) - - def add_family_ref(self, obj, handle): - try: - family = models.Family.objects.get(handle=handle) - except: - print(("ERROR: Family does not exist: '%s'" % - str(handle)), file=sys.stderr) - return - #obj.families.add(family) - pfo = models.MyFamilies(person=obj, family=family, - order=len(models.MyFamilies.objects.filter(person=obj)) + 1) - pfo.save() - obj.save() - - ## Export individual objects: - - def add_source_attribute_list(self, source, attribute_list): - ## FIXME: dict to list - count = 1 - #for key in datamap_dict: - # value = datamap_dict[key] - # datamap = models.SourceDatamap(key=key, value=value, order=count) - # datamap.source = source - # datamap.save() - # count += 1 - - def add_citation_attribute_list(self, citation, attribute_list): - ## FIXME: dict to list - count = 1 - #for key in datamap_dict: - # value = datamap_dict[key] - # datamap = models.CitationDatamap(key=key, value=value, order=count) - # datamap.citation = citation - # datamap.save() - # count += 1 - - def add_lds(self, field, obj, data, order): - (lcitation_list, lnote_list, date, type, place_handle, - famc_handle, temple, status, private) = data - if place_handle: - try: - place = models.Place.objects.get(handle=place_handle) - except: - print(("ERROR: Place does not exist: '%s'" % - str(place_handle)), file=sys.stderr) - place = None - else: - place = None - if famc_handle: - try: - famc = models.Family.objects.get(handle=famc_handle) - except: - print(("ERROR: Family does not exist: '%s'" % - str(famc_handle)), file=sys.stderr) - famc = None - else: - famc = None - lds = models.Lds(lds_type = models.get_type(models.LdsType, type), - temple=temple, - place=place, - famc=famc, - order=order, - status = models.get_type(models.LdsStatus, status), - private=private) - self.add_date(lds, date) - lds.save() - self.add_note_list(lds, lnote_list) - self.add_citation_list(lds, lcitation_list) - if field == "person": - lds.person = obj - elif field == "family": - lds.family = obj - else: - raise AttributeError("invalid field '%s' to attach lds" % - str(field)) - lds.save() - return lds - - def add_address(self, field, obj, address_data, order): - (private, acitation_list, anote_list, date, location) = address_data - address = models.Address(private=private, order=order) - self.add_date(address, date) - address.save() - self.add_location("address", address, location, 1) - self.add_note_list(address, anote_list) - self.add_citation_list(address, acitation_list) - if field == "person": - address.person = obj - elif field == "repository": - address.repository = obj - else: - raise AttributeError("invalid field '%s' to attach address" % - str(field)) - address.save() - #obj.save() - #obj.addresses.add(address) - #obj.save() - - def add_attribute(self, obj, attribute_data): - (private, citation_list, note_list, the_type, value) = attribute_data - attribute_type = models.get_type(models.AttributeType, the_type) - attribute = models.Attribute(private=private, - attribute_of=obj, - attribute_type=attribute_type, - value=value) - attribute.save() - self.add_citation_list(attribute, citation_list) - self.add_note_list(attribute, note_list) - #obj.attributes.add(attribute) - #obj.save() - - def add_url(self, field, obj, url_data, order): - (private, path, desc, type) = url_data - url = models.Url(private=private, - path=path, - desc=desc, - order=order, - url_type=models.get_type(models.UrlType, type)) - if field == "person": - url.person = obj - elif field == "repository": - url.repository = obj - elif field == "place": - url.place = obj - else: - raise AttributeError("invalid field '%s' to attach to url" % - str(field)) - url.save() - #obj.url_list.add(url) - #obj.save() - - def add_place_ref_default(self, obj, place, date=None): - count = place.references.count() - object_type = ContentType.objects.get_for_model(obj) - count = models.PlaceRef.objects.filter(object_id=obj.id, - object_type=object_type).count() - place_ref = models.PlaceRef(referenced_by=obj, - ref_object=place, - order=count + 1) - self.add_date(obj, date) - place_ref.save() - - def add_place_ref(self, obj, data): - place_handle, date = data - if place_handle: - try: - place = models.Place.objects.get(handle=place_handle) - except: - print(("ERROR: Place does not exist: '%s'" % str(place_handle)), file=sys.stderr) - #from gramps.gen.utils.debug import format_exception - #print("".join(format_exception()), file=sys.stderr) - return - object_type = ContentType.objects.get_for_model(obj) - count = models.PlaceRef.objects.filter(object_id=obj.id,object_type=object_type).count() - place_ref = models.PlaceRef(referenced_by=obj, ref_object=place, order=count + 1) - place_ref.save() - self.add_date(place_ref, date) - - def add_parent_family(self, person, parent_family_handle): - try: - family = models.Family.objects.get(handle=parent_family_handle) - except: - print(("ERROR: Family does not exist: '%s'" % - str(parent_family_handle)), file=sys.stderr) - return - #person.parent_families.add(family) - pfo = models.MyParentFamilies( - person=person, - family=family, - order=len(models.MyParentFamilies.objects.filter(person=person)) + 1) - pfo.save() - person.save() - - def add_date(self, obj, date): - if date is None: - (calendar, modifier, quality, text, sortval, newyear) = \ - (0, 0, 0, "", 0, 0) - day1, month1, year1, slash1 = 0, 0, 0, 0 - day2, month2, year2, slash2 = 0, 0, 0, 0 - else: - (calendar, modifier, quality, dateval, text, sortval, newyear) = date - if len(dateval) == 4: - day1, month1, year1, slash1 = dateval - day2, month2, year2, slash2 = 0, 0, 0, 0 - elif len(dateval) == 8: - day1, month1, year1, slash1, day2, month2, year2, slash2 = dateval - else: - raise AttributeError("ERROR: dateval format '%s'" % str(dateval)) - obj.calendar = calendar - obj.modifier = modifier - obj.quality = quality - obj.text = text - obj.sortval = sortval - obj.newyear = newyear - obj.day1 = day1 - obj.month1 = month1 - obj.year1 = year1 - obj.slash1 = slash1 - obj.day2 = day2 - obj.month2 = month2 - obj.year2 = year2 - obj.slash2 = slash2 - - def add_name(self, person, data, preferred): - if data: - (private, citation_list, note_list, date, - first_name, surname_list, suffix, title, - name_type, group_as, sort_as, - display_as, call, nick, famnick) = data - - count = person.name_set.count() - name = models.Name() - name.order = count + 1 - name.preferred = preferred - name.private = private - name.first_name = first_name - name.suffix = suffix - name.title = title - name.name_type = models.get_type(models.NameType, name_type) - name.group_as = group_as - name.sort_as = models.get_type(models.NameFormatType, sort_as) - name.display_as = models.get_type(models.NameFormatType, display_as) - name.call = call - name.nick = nick - name.famnick = famnick - # we know person exists - # needs to have an ID for key - name.person = person - self.add_date(name, date) - name.save() - self.add_surname_list(name, surname_list) - self.add_note_list(name, note_list) - self.add_citation_list(name, citation_list) - #person.save() - - ## Export primary objects: - - def add_person(self, data): - # Unpack from the BSDDB: - (handle, # 0 - gid, # 1 - gender, # 2 - primary_name, # 3 - alternate_names, # 4 - death_ref_index, # 5 - birth_ref_index, # 6 - event_ref_list, # 7 - family_list, # 8 - parent_family_list, # 9 - media_list, # 10 - address_list, # 11 - attribute_list, # 12 - url_list, # 13 - lds_ord_list, # 14 - pcitation_list, # 15 - pnote_list, # 16 - change, # 17 - tag_list, # 18 - private, # 19 - person_ref_list, # 20 - ) = data - - person = models.Person(handle=handle, - gramps_id=gid, - last_changed=todate(change), - private=private, - gender_type=models.get_type(models.GenderType, gender)) - person.save(save_cache=False) - - def add_person_detail(self, data): - # Unpack from the BSDDB: - (handle, # 0 - gid, # 1 - gender, # 2 - primary_name, # 3 - alternate_names, # 4 - death_ref_index, # 5 - birth_ref_index, # 6 - event_ref_list, # 7 - family_list, # 8 - parent_family_list, # 9 - media_list, # 10 - address_list, # 11 - attribute_list, # 12 - url_list, # 13 - lds_ord_list, # 14 - pcitation_list, # 15 - pnote_list, # 16 - change, # 17 - tag_list, # 18 - private, # 19 - person_ref_list, # 20 - ) = data - - try: - person = models.Person.objects.get(handle=handle) - except: - print(("ERROR: Person does not exist: '%s'" % - str(handle)), file=sys.stderr) - return - if primary_name: - self.add_name(person, primary_name, True) - self.add_alternate_name_list(person, alternate_names) - self.add_event_ref_list(person, event_ref_list) - self.add_family_ref_list(person, family_list) - self.add_parent_family_list(person, parent_family_list) - self.add_media_ref_list(person, media_list) - self.add_note_list(person, pnote_list) - self.add_attribute_list(person, attribute_list) - self.add_url_list("person", person, url_list) - self.add_person_ref_list(person, person_ref_list) - self.add_citation_list(person, pcitation_list) - self.add_address_list("person", person, address_list) - self.add_lds_list("person", person, lds_ord_list) - self.add_tag_list(person, tag_list) - # set person.birth and birth.death to correct events: - - obj_type = ContentType.objects.get_for_model(person) - events = models.EventRef.objects.filter( - object_id=person.id, - object_type=obj_type, - ref_object__event_type__val=models.EventType.BIRTH).order_by("order") - - all_events = self.get_event_ref_list(person) - if events: - person.birth = events[0].ref_object - person.birth_ref_index = lookup_role_index(models.EventType.BIRTH, all_events) - - events = models.EventRef.objects.filter( - object_id=person.id, - object_type=obj_type, - ref_object__event_type__val=models.EventType.DEATH).order_by("order") - if events: - person.death = events[0].ref_object - person.death_ref_index = lookup_role_index(models.EventType.DEATH, all_events) - person.save() - return person - - def save_note_markup(self, note, markup_list): - # delete any prexisting markup: - models.Markup.objects.filter(note=note).delete() - count = 1 - for markup in markup_list: - markup_code, value, start_stop_list = markup - m = models.Markup( - note=note, - order=count, - styled_text_tag_type=models.get_type(models.StyledTextTagType, - markup_code, - get_or_create=False), - string=value, - start_stop_list=str(start_stop_list)) - m.save() - - def add_note(self, data): - # Unpack from the BSDDB: - (handle, gid, styled_text, format, note_type, - change, tag_list, private) = data - text, markup_list = styled_text - n = models.Note(handle=handle, - gramps_id=gid, - last_changed=todate(change), - private=private, - preformatted=format, - text=text, - note_type=models.get_type(models.NoteType, note_type)) - n.save(save_cache=False) - self.save_note_markup(n, markup_list) - - def add_note_detail(self, data): - # Unpack from the BSDDB: - (handle, gid, styled_text, format, note_type, - change, tag_list, private) = data - note = models.Note.objects.get(handle=handle) - note.save(save_cache=False) - self.add_tag_list(note, tag_list) - note.save_cache() - - def add_family(self, data): - # Unpack from the BSDDB: - (handle, gid, father_handle, mother_handle, - child_ref_list, the_type, event_ref_list, media_list, - attribute_list, lds_seal_list, citation_list, note_list, - change, tag_list, private) = data - - family = models.Family(handle=handle, gramps_id=gid, - family_rel_type = models.get_type(models.FamilyRelType, the_type), - last_changed=todate(change), - private=private) - family.save(save_cache=False) - - def add_family_detail(self, data): - # Unpack from the BSDDB: - (handle, gid, father_handle, mother_handle, - child_ref_list, the_type, event_ref_list, media_list, - attribute_list, lds_seal_list, citation_list, note_list, - change, tag_list, private) = data - - try: - family = models.Family.objects.get(handle=handle) - except: - print(("ERROR: Family does not exist: '%s'" % - str(handle)), file=sys.stderr) - return - # father_handle and/or mother_handle can be None - if father_handle: - try: - family.father = models.Person.objects.get(handle=father_handle) - except: - print(("ERROR: Father does not exist: '%s'" % - str(father_handle)), file=sys.stderr) - family.father = None - if mother_handle: - try: - family.mother = models.Person.objects.get(handle=mother_handle) - except: - print(("ERROR: Mother does not exist: '%s'" % - str(mother_handle)), file=sys.stderr) - family.mother = None - family.save(save_cache=False) - self.add_child_ref_list(family, child_ref_list) - self.add_note_list(family, note_list) - self.add_attribute_list(family, attribute_list) - self.add_citation_list(family, citation_list) - self.add_media_ref_list(family, media_list) - self.add_event_ref_list(family, event_ref_list) - self.add_lds_list("family", family, lds_seal_list) - self.add_tag_list(family, tag_list) - family.save_cache() - - def add_source(self, data): - (handle, gid, title, - author, pubinfo, - note_list, - media_list, - abbrev, - change, attribute_list, - reporef_list, - tag_list, - private) = data - source = models.Source(handle=handle, gramps_id=gid, title=title, - author=author, pubinfo=pubinfo, abbrev=abbrev, - last_changed=todate(change), private=private) - source.save(save_cache=False) - - def add_source_detail(self, data): - (handle, gid, title, - author, pubinfo, - note_list, - media_list, - abbrev, - change, attribute_list, - reporef_list, - tag_list, - private) = data - try: - source = models.Source.objects.get(handle=handle) - except: - print(("ERROR: Source does not exist: '%s'" % - str(handle)), file=sys.stderr) - return - source.save(save_cache=False) - self.add_note_list(source, note_list) - self.add_media_ref_list(source, media_list) - self.add_source_attribute_list(source, attribute_list) - self.add_repository_ref_list(source, reporef_list) - self.add_tag_list(source, tag_list) - source.save_cache() - - def add_repository(self, data): - (handle, gid, the_type, name, note_list, - address_list, url_list, change, tag_list, private) = data - - repository = models.Repository(handle=handle, - gramps_id=gid, - last_changed=todate(change), - private=private, - repository_type=models.get_type(models.RepositoryType, the_type), - name=name) - repository.save(save_cache=False) - - def add_repository_detail(self, data): - (handle, gid, the_type, name, note_list, - address_list, url_list, change, tag_list, private) = data - try: - repository = models.Repository.objects.get(handle=handle) - except: - print(("ERROR: Repository does not exist: '%s'" % - str(handle)), file=sys.stderr) - return - repository.save(save_cache=False) - self.add_note_list(repository, note_list) - self.add_url_list("repository", repository, url_list) - self.add_address_list("repository", repository, address_list) - self.add_tag_list(repository, tag_list) - repository.save_cache() - - def add_location(self, field, obj, location_data, order): - # location now has 8 items - # street, locality, city, county, state, - # country, postal, phone, parish - - if location_data == None: return - if len(location_data) == 8: - (street, locality, city, county, state, country, postal, phone) = location_data - parish = None - elif len(location_data) == 2: - ((street, locality, city, county, state, country, postal, phone), parish) = location_data - else: - print(("ERROR: unknown location: '%s'" % - str(location_data)), file=sys.stderr) - (street, locality, city, county, state, country, postal, phone, parish) = \ - ("", "", "", "", "", "", "", "", "") - location = models.Location(street = street, - locality = locality, - city = city, - county = county, - state = state, - country = country, - postal = postal, - phone = phone, - parish = parish, - order = order) - if field == "address": - location.address = obj - elif field == "place": - location.place = obj - else: - raise AttributeError("invalid field '%s' to attach to location" % - str(field)) - location.save() - #obj.locations.add(location) - #obj.save() - - def add_place(self, data): - ## ('cef246c95c132bcf6a0255d4d17', 'P0036', 'Santa Clara Co., CA, USA', '', '', [('cef243fb5634559442323368f63', None)], 'Santa Clara Co.', [], (3, ''), '', [], [], [], [], [], 1422124781, [], False) - (handle, gid, title, long, lat, - place_ref_list, - name, - alt_name_list, - place_type, - code, - alt_location_list, - url_list, - media_list, - citation_list, - note_list, - change, - tag_list, - private) = data - place = models.Place( - handle=handle, - gramps_id=gid, - title=title, - long=long, - lat=lat, - name=name, - place_type=models.get_type(models.PlaceType, place_type), - code=code, - last_changed=todate(change), - private=private) - try: - place.save(save_cache=False) - except: - print("FIXME: error in saving place") - - def add_place_detail(self, data): - (handle, gid, title, long, lat, - place_ref_list, - name, - alt_name_list, - place_type, - code, - alt_location_list, - url_list, - media_list, - citation_list, - note_list, - change, - tag_list, - private) = data - try: - place = models.Place.objects.get(handle=handle) - except: - print(("ERROR: Place does not exist: '%s'" % - str(handle)), file=sys.stderr) - return - place.save(save_cache=False) - self.add_url_list("place", place, url_list) - self.add_media_ref_list(place, media_list) - self.add_citation_list(place, citation_list) - self.add_note_list(place, note_list) - self.add_tag_list(place, tag_list) - self.add_place_ref_list(place, place_ref_list) - self.add_alt_name_list(place, alt_name_list) - count = 1 - for loc_data in alt_location_list: - self.add_location("place", place, loc_data, count) - count + 1 - place.save_cache() - - def add_tag(self, data): - (handle, - name, - color, - priority, - change) = data - tag = models.Tag(handle=handle, - gramps_id=create_id(), - name=name, - color=color, - priority=priority, - last_changed=todate(change)) - tag.save(save_cache=False) - - def add_tag_detail(self, data): - (handle, - name, - color, - priority, - change) = data - tag = models.Tag.objects.get(handle=handle) - tag.save() - - def add_media(self, data): - (handle, gid, path, mime, desc, - checksum, - attribute_list, - citation_list, - note_list, - change, - date, - tag_list, - private) = data - media = models.Media(handle=handle, gramps_id=gid, - path=path, mime=mime, checksum=checksum, - desc=desc, last_changed=todate(change), - private=private) - self.add_date(media, date) - media.save(save_cache=False) - - def add_media_detail(self, data): - (handle, gid, path, mime, desc, - checksum, - attribute_list, - citation_list, - note_list, - change, - date, - tag_list, - private) = data - try: - media = models.Media.objects.get(handle=handle) - except: - print(("ERROR: Media does not exist: '%s'" % - str(handle)), file=sys.stderr) - return - media.save(save_cache=False) - self.add_note_list(media, note_list) - self.add_citation_list(media, citation_list) - self.add_attribute_list(media, attribute_list) - self.add_tag_list(media, tag_list) - media.save_cache() - - def add_event(self, data): - (handle, gid, the_type, date, description, place_handle, - citation_list, note_list, media_list, attribute_list, - change, tag_list, private) = data - event = models.Event(handle=handle, - gramps_id=gid, - event_type=models.get_type(models.EventType, the_type), - private=private, - description=description, - last_changed=todate(change)) - self.add_date(event, date) - event.save(save_cache=False) - - def add_event_detail(self, data): - (handle, gid, the_type, date, description, place_handle, - citation_list, note_list, media_list, attribute_list, - change, tag_list, private) = data - try: - event = models.Event.objects.get(handle=handle) - except: - print(("ERROR: Event does not exist: '%s'" % - str(handle)), file=sys.stderr) - return - try: - place = models.Place.objects.get(handle=place_handle) - except: - place = None - print(("ERROR: Place does not exist: '%s'" % - str(place_handle)), file=sys.stderr) - event.place = place - event.save(save_cache=False) - self.add_note_list(event, note_list) - self.add_attribute_list(event, attribute_list) - self.add_media_ref_list(event, media_list) - self.add_citation_list(event, citation_list) - self.add_tag_list(event, tag_list) - event.save_cache() - - def get_raw(self, item): - """ - Build and return the raw, serialized data of an object. - """ - if isinstance(item, models.Person): - raw = self.get_person(item) - elif isinstance(item, models.Family): - raw = self.get_family(item) - elif isinstance(item, models.Place): - raw = self.get_place(item) - elif isinstance(item, models.Media): - raw = self.get_media(item) - elif isinstance(item, models.Source): - raw = self.get_source(item) - elif isinstance(item, models.Citation): - raw = self.get_citation(item) - elif isinstance(item, models.Repository): - raw = self.get_repository(item) - elif isinstance(item, models.Note): - raw = self.get_note(item) - elif isinstance(item, models.Event): - raw = self.get_event(item) - else: - raise Exception("Don't know how to get raw '%s'" % type(item)) - return raw - - def check_caches(self, callback=None): - """ - Call this to check the caches for all primary models. - """ - if not isinstance(callback, collections.Callable): - callback = lambda percent: None # dummy - - callback(0) - count = 0.0 - total = (self.Note.all().count() + - self.Person.all().count() + - self.Event.all().count() + - self.Family.all().count() + - self.Repository.all().count() + - self.Place.all().count() + - self.Media.all().count() + - self.Source.all().count() + - self.Citation.all().count() + - self.Tag.all().count()) - - for item in self.Note.all(): - raw = self.get_note(item) - check_diff(item, raw) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Person.all(): - raw = self.get_person(item) - check_diff(item, raw) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Family.all(): - raw = self.get_family(item) - check_diff(item, raw) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Source.all(): - raw = self.get_source(item) - check_diff(item, raw) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Event.all(): - raw = self.get_event(item) - check_diff(item, raw) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Repository.all(): - raw = self.get_repository(item) - check_diff(item, raw) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Place.all(): - raw = self.get_place(item) - check_diff(item, raw) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Media.all(): - raw = self.get_media(item) - check_diff(item, raw) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Citation.all(): - raw = self.get_citation(item) - check_diff(item, raw) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Tag.all(): - raw = self.get_tag(item) - check_diff(item, raw) - count += 1 - callback(100) - - def check_families(self): - """ - Check family structures. - """ - for family in self.Family.all(): - if family.mother: - if not family in family.mother.families.all(): - print("Mother not in family", mother, family) - if family.father: - if not family in family.father.families.all(): - print("Father not in family", mother, family) - for child in family.get_children(): - if family not in child.parent_families.all(): - print("Child not in family", child, family) - for person in self.Person.all(): - for family in person.families.all(): - if person not in [family.mother, family.father]: - print("Spouse not in family", person, family) - for family in person.parent_families.all(): - if person not in family.get_children(): - print("Child not in family", person, family) - - def is_public(self, obj, objref): - """ - Returns whether or not an item is "public", and the reason - why/why not. - - @param obj - an instance of any Primary object - @param objref - one of the PrimaryRef.objects - @return - a tuple containing a boolean (public?) and reason. - - There are three reasons why an item might not be public: - 1) The item itself is private. - 2) The item is referenced by a living Person. - 3) The item is referenced by some other private item. - """ - # If it is private, then no: - if obj.private: - return (False, "It is marked private.") - elif hasattr(obj, "probably_alive") and obj.probably_alive: - return (False, "It is marked probaby alive.") - elif hasattr(obj, "mother") and obj.mother: - public, reason = self.is_public(obj.mother, self.PersonRef) - if not public: - return public, reason - elif hasattr(obj, "father") and obj.father: - public, reason = self.is_public(obj.father, self.PersonRef) - if not public: - return public, reason - # FIXME: what about Associations... anything else? Check PrivateProxy - if objref: - if hasattr(objref.model, "ref_object"): - obj_ref_list = objref.filter(ref_object=obj) - elif hasattr(objref.model, "citation"): - obj_ref_list = objref.filter(citation=obj) - else: - raise Exception("objref '%s' needs a ref for '%s'" % (objref.model, obj)) - for reference in obj_ref_list: - ref_from_class = reference.object_type.model_class() - item = None - try: - item = ref_from_class.objects.get(id=reference.object_id) - except: - print("Warning: Corrupt reference: %s" % str(reference)) - continue - # If it is linked to by someone alive? public = False - if hasattr(item, "probably_alive") and item.probably_alive: - return (False, "It is referenced by someone who is probaby alive.") - # If it is linked to by something private? public = False - elif item.private: - return (False, "It is referenced by an item which is marked private.") - return (True, "It is visible to the public.") - - def update_public(self, obj, save=True): - """ - >>> dji.update_public(event) - - Given an Event or other instance, update the event's public - status, or any event referenced to by the instance. - - For example, if a person is found to be alive, then the - referenced events should be marked not public (public = False). - - """ - from gramps.webapp.utils import probably_alive - if obj.__class__.__name__ == "Event": - objref = self.EventRef - elif obj.__class__.__name__ == "Person": - objref = self.PersonRef - elif obj.__class__.__name__ == "Note": - objref = self.NoteRef - elif obj.__class__.__name__ == "Repository": - objref = self.RepositoryRef - elif obj.__class__.__name__ == "Citation": - objref = self.CitationRef - elif obj.__class__.__name__ == "Media": - objref = self.MediaRef - elif obj.__class__.__name__ == "Place": # no need for dependency - objref = None - elif obj.__class__.__name__ == "Source": # no need for dependency - objref = None - elif obj.__class__.__name__ == "Family": - objref = self.ChildRef # correct? - else: - raise Exception("Can't compute public of type '%s'" % str(obj)) - public, reason = self.is_public(obj, objref) # correct? - # Ok, update, if needed: - if obj.public != public: - obj.public = public - if save: - print("Updating public:", obj.__class__.__name__, obj.gramps_id) - obj.save() - #log = self.Log() - #log.referenced_by = obj - #log.object_id = obj.id - #log.object_type = obj_type - #log.log_type = "update public status" - #log.reason = reason - #log.order = 0 - #log.save() - - def update_publics(self, callback=None): - """ - Call this to update probably_alive for all primary models. - """ - if not isinstance(callback, collections.Callable): - callback = lambda percent: None # dummy - - callback(0) - count = 0.0 - total = (self.Note.all().count() + - self.Person.all().count() + - self.Event.all().count() + - self.Family.all().count() + - self.Repository.all().count() + - self.Place.all().count() + - self.Media.all().count() + - self.Source.all().count() + - self.Citation.all().count()) - - for item in self.Note.all(): - self.update_public(item) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Person.all(): - self.update_public(item) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Family.all(): - self.update_public(item) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Source.all(): - self.update_public(item) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Event.all(): - self.update_public(item) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Repository.all(): - self.update_public(item) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Place.all(): - self.update_public(item) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Media.all(): - self.update_public(item) - count += 1 - callback(100 * (count/total if total else 0)) - - for item in self.Citation.all(): - self.update_public(item) - count += 1 - callback(100 * (count/total if total else 0)) - - def update_probably_alive(self, callback=None): - """ - Call this to update primary_alive for people. - """ - from gramps.webapp.utils import probably_alive - if not isinstance(callback, collections.Callable): - callback = lambda percent: None # dummy - callback(0) - count = 0.0 - total = self.Person.all().count() - for item in self.Person.all(): - pa = probably_alive(item.handle) - if pa != item.probably_alive: - print("Updating probably_alive") - item.probably_alive = pa - item.save() - count += 1 - callback(100 * (count/total if total else 0)) diff --git a/gramps/plugins/database/djangodb.gpr.py b/gramps/plugins/database/djangodb.gpr.py deleted file mode 100644 index 2d0d0797b..000000000 --- a/gramps/plugins/database/djangodb.gpr.py +++ /dev/null @@ -1,32 +0,0 @@ -# -# Gramps - a GTK+/GNOME based genealogy program -# -# Copyright (C) 2015 Douglas Blank -# -# 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. -# - -plg = newplugin() -plg.id = 'djangodb' -plg.name = _("Django Database Backend") -plg.name_accell = _("_Django Database Backend") -plg.description = _("Django Object Relational Model Database Backend") -plg.version = '1.0' -plg.gramps_target_version = "4.2" -plg.status = STABLE -plg.fname = 'djangodb.py' -plg.ptype = DATABASE -plg.databaseclass = 'DbDjango' -plg.reset_system = True diff --git a/gramps/plugins/database/djangodb.py b/gramps/plugins/database/djangodb.py deleted file mode 100644 index a7f64f13e..000000000 --- a/gramps/plugins/database/djangodb.py +++ /dev/null @@ -1,2150 +0,0 @@ -# Gramps - a GTK+/GNOME based genealogy program -# -# Copyright (C) 2009 Douglas S. Blank -# -# 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. -# - -""" Implements a Db interface """ - -#------------------------------------------------------------------------ -# -# Python Modules -# -#------------------------------------------------------------------------ -import sys -import time -import re -import base64 -import pickle -import os -import logging -import shutil -from django.db import transaction - -#------------------------------------------------------------------------ -# -# Gramps Modules -# -#------------------------------------------------------------------------ -import gramps -from gramps.gen.const import GRAMPS_LOCALE as glocale -_ = glocale.translation.gettext -from gramps.gen.lib import (Person, Family, Event, Place, Repository, - Citation, Source, Note, MediaObject, Tag, - Researcher, GenderStats) -from gramps.gen.db import DbReadBase, DbWriteBase, DbTxn -from gramps.gen.db.undoredo import DbUndo -from gramps.gen.utils.callback import Callback -from gramps.gen.updatecallback import UpdateCallback -from gramps.gen.db import (PERSON_KEY, - FAMILY_KEY, - CITATION_KEY, - SOURCE_KEY, - EVENT_KEY, - MEDIA_KEY, - PLACE_KEY, - REPOSITORY_KEY, - NOTE_KEY) -from gramps.gen.utils.id import create_id -from gramps.gen.db.dbconst import * - -## add this directory to sys path, so we can find django_support later: -sys.path.append(os.path.dirname(os.path.abspath(__file__))) - -_LOG = logging.getLogger(DBLOGNAME) - -def touch(fname, mode=0o666, dir_fd=None, **kwargs): - ## After http://stackoverflow.com/questions/1158076/implement-touch-using-python - flags = os.O_CREAT | os.O_APPEND - with os.fdopen(os.open(fname, flags=flags, mode=mode, dir_fd=dir_fd)) as f: - os.utime(f.fileno() if os.utime in os.supports_fd else fname, - dir_fd=None if os.supports_fd else dir_fd, **kwargs) - -class Environment(object): - """ - Implements the Environment API. - """ - def __init__(self, db): - self.db = db - - def txn_begin(self): - return DjangoTxn("DjangoDb Transaction", self.db) - -class Table(object): - """ - Implements Table interface. - """ - def __init__(self, funcs): - self.funcs = funcs - - def cursor(self): - """ - Returns a Cursor for this Table. - """ - return self.funcs["cursor_func"]() - - def put(self, key, data, txn=None): - ## FIXME: probably needs implementing? - #self[key] = data - pass - -class Map(dict): - """ - Implements the map API for person_map, etc. - - Takes a Table() as argument. - """ - def __init__(self, tbl, *args, **kwargs): - super().__init__(*args, **kwargs) - self.db = tbl - -class MetaCursor(object): - def __init__(self): - pass - def __enter__(self): - return self - def __iter__(self): - return self.__next__() - def __next__(self): - yield None - def __exit__(self, *args, **kwargs): - pass - def iter(self): - yield None - def first(self): - self._iter = self.__iter__() - return self.next() - def next(self): - try: - return next(self._iter) - except: - return None - def close(self): - pass - -class Cursor(object): - def __init__(self, model, func): - self.model = model - self.func = func - self._iter = self.__iter__() - def __enter__(self): - return self - def __iter__(self): - for item in self.model.all(): - yield (bytes(item.handle, "utf-8"), self.func(item.handle)) - def __next__(self): - try: - return self._iter.__next__() - except StopIteration: - return None - def __exit__(self, *args, **kwargs): - pass - def iter(self): - for item in self.model.all(): - yield (bytes(item.handle, "utf-8"), self.func(item.handle)) - yield None - def first(self): - self._iter = self.__iter__() - try: - return next(self._iter) - except: - return - def next(self): - try: - return next(self._iter) - except: - return None - def close(self): - pass - -class Bookmarks(object): - def __init__(self): - self.handles = [] - def get(self): - return self.handles - def append(self, handle): - self.handles.append(handle) - -class DjangoTxn(DbTxn): - def __init__(self, message, db, table=None): - DbTxn.__init__(self, message, db) - self.table = table - - def get(self, key, default=None, txn=None, **kwargs): - """ - Returns the data object associated with key - """ - try: - return self.table.objects(handle=key) - except: - if txn and key in txn: - return txn[key] - else: - return None - - def put(self, handle, new_data, txn): - """ - """ - ## FIXME: probably not correct? - txn[handle] = new_data - - def commit(self): - pass - -class DbDjango(DbWriteBase, DbReadBase, UpdateCallback, Callback): - """ - A Gramps Database Backend. This replicates the grampsdb functions. - """ - # Set up dictionary for callback signal handler - # --------------------------------------------- - # 1. Signals for primary objects - __signals__ = dict((obj+'-'+op, signal) - for obj in - ['person', 'family', 'event', 'place', - 'source', 'citation', 'media', 'note', 'repository', 'tag'] - for op, signal in zip( - ['add', 'update', 'delete', 'rebuild'], - [(list,), (list,), (list,), None] - ) - ) - - # 2. Signals for long operations - __signals__.update(('long-op-'+op, signal) for op, signal in zip( - ['start', 'heartbeat', 'end'], - [(object,), None, None] - )) - - # 3. Special signal for change in home person - __signals__['home-person-changed'] = None - - # 4. Signal for change in person group name, parameters are - __signals__['person-groupname-rebuild'] = (str, str) - - __callback_map = {} - - def __init__(self, directory=None): - DbReadBase.__init__(self) - DbWriteBase.__init__(self) - Callback.__init__(self) - self._tables = { - 'Person': - { - "handle_func": self.get_person_from_handle, - "gramps_id_func": self.get_person_from_gramps_id, - "class_func": gramps.gen.lib.Person, - "cursor_func": self.get_person_cursor, - "handles_func": self.get_person_handles, - "iter_func": self.iter_people, - }, - 'Family': - { - "handle_func": self.get_family_from_handle, - "gramps_id_func": self.get_family_from_gramps_id, - "class_func": gramps.gen.lib.Family, - "cursor_func": self.get_family_cursor, - "handles_func": self.get_family_handles, - "iter_func": self.iter_families, - }, - 'Source': - { - "handle_func": self.get_source_from_handle, - "gramps_id_func": self.get_source_from_gramps_id, - "class_func": gramps.gen.lib.Source, - "cursor_func": self.get_source_cursor, - "handles_func": self.get_source_handles, - "iter_func": self.iter_sources, - }, - 'Citation': - { - "handle_func": self.get_citation_from_handle, - "gramps_id_func": self.get_citation_from_gramps_id, - "class_func": gramps.gen.lib.Citation, - "cursor_func": self.get_citation_cursor, - "handles_func": self.get_citation_handles, - "iter_func": self.iter_citations, - }, - 'Event': - { - "handle_func": self.get_event_from_handle, - "gramps_id_func": self.get_event_from_gramps_id, - "class_func": gramps.gen.lib.Event, - "cursor_func": self.get_event_cursor, - "handles_func": self.get_event_handles, - "iter_func": self.iter_events, - }, - 'Media': - { - "handle_func": self.get_object_from_handle, - "gramps_id_func": self.get_object_from_gramps_id, - "class_func": gramps.gen.lib.MediaObject, - "cursor_func": self.get_media_cursor, - "handles_func": self.get_media_object_handles, - "iter_func": self.iter_media_objects, - }, - 'Place': - { - "handle_func": self.get_place_from_handle, - "gramps_id_func": self.get_place_from_gramps_id, - "class_func": gramps.gen.lib.Place, - "cursor_func": self.get_place_cursor, - "handles_func": self.get_place_handles, - "iter_func": self.iter_places, - }, - 'Repository': - { - "handle_func": self.get_repository_from_handle, - "gramps_id_func": self.get_repository_from_gramps_id, - "class_func": gramps.gen.lib.Repository, - "cursor_func": self.get_repository_cursor, - "handles_func": self.get_repository_handles, - "iter_func": self.iter_repositories, - }, - 'Note': - { - "handle_func": self.get_note_from_handle, - "gramps_id_func": self.get_note_from_gramps_id, - "class_func": gramps.gen.lib.Note, - "cursor_func": self.get_note_cursor, - "handles_func": self.get_note_handles, - "iter_func": self.iter_notes, - }, - 'Tag': - { - "handle_func": self.get_tag_from_handle, - "gramps_id_func": None, - "class_func": gramps.gen.lib.Tag, - "cursor_func": self.get_tag_cursor, - "handles_func": self.get_tag_handles, - "iter_func": self.iter_tags, - }, - } - # skip GEDCOM cross-ref check for now: - self.set_feature("skip-check-xref", True) - self.readonly = False - self.db_is_open = True - self.name_formats = [] - self.bookmarks = Bookmarks() - self.undo_callback = None - self.redo_callback = None - self.undo_history_callback = None - self.modified = 0 - self.txn = DjangoTxn("DbDjango Transaction", self) - self.transaction = None - # Import cache for gedcom import, uses transactions, and - # two step adding of objects. - self.import_cache = {} - self.use_import_cache = False - self.use_db_cache = True - self.undodb = DbUndo(self) - self.abort_possible = False - self._bm_changes = 0 - self._directory = directory - self.full_name = None - self.path = None - self.brief_name = None - self.genderStats = GenderStats() # can pass in loaded stats as dict - self.owner = Researcher() - if directory: - self.load(directory) - - def load(self, directory, callback=None, mode=None, - force_schema_upgrade=False, - force_bsddb_upgrade=False, - force_bsddb_downgrade=False, - force_python_upgrade=False): - _LOG.info("Django loading...") - self._directory = directory - self.full_name = os.path.abspath(self._directory) - self.path = self.full_name - self.brief_name = os.path.basename(self._directory) - from django.conf import settings - default_settings = {"__file__": - os.path.join(directory, "default_settings.py")} - settings_file = os.path.join(directory, "default_settings.py") - with open(settings_file) as f: - code = compile(f.read(), settings_file, 'exec') - exec(code, globals(), default_settings) - - class Module(object): - def __init__(self, dictionary): - self.dictionary = dictionary - def __getattr__(self, item): - return self.dictionary[item] - - _LOG.info("Django loading defaults from: " + directory) - try: - settings.configure(Module(default_settings)) - except RuntimeError: - _LOG.info("Django already configured error! Shouldn't happen!") - # already configured; ignore - pass - - import django - django.setup() - - from django_support.libdjango import DjangoInterface - self.dji = DjangoInterface() - self.family_bookmarks = Bookmarks() - self.event_bookmarks = Bookmarks() - self.place_bookmarks = Bookmarks() - self.citation_bookmarks = Bookmarks() - self.source_bookmarks = Bookmarks() - self.repo_bookmarks = Bookmarks() - self.media_bookmarks = Bookmarks() - self.note_bookmarks = Bookmarks() - self.set_person_id_prefix('I%04d') - self.set_object_id_prefix('O%04d') - self.set_family_id_prefix('F%04d') - self.set_citation_id_prefix('C%04d') - self.set_source_id_prefix('S%04d') - self.set_place_id_prefix('P%04d') - self.set_event_id_prefix('E%04d') - self.set_repository_id_prefix('R%04d') - self.set_note_id_prefix('N%04d') - # ---------------------------------- - self.id_trans = DjangoTxn("ID Transaction", self, self.dji.Person) - self.fid_trans = DjangoTxn("FID Transaction", self, self.dji.Family) - self.pid_trans = DjangoTxn("PID Transaction", self, self.dji.Place) - self.cid_trans = DjangoTxn("CID Transaction", self, self.dji.Citation) - self.sid_trans = DjangoTxn("SID Transaction", self, self.dji.Source) - self.oid_trans = DjangoTxn("OID Transaction", self, self.dji.Media) - self.rid_trans = DjangoTxn("RID Transaction", self, self.dji.Repository) - self.nid_trans = DjangoTxn("NID Transaction", self, self.dji.Note) - self.eid_trans = DjangoTxn("EID Transaction", self, self.dji.Event) - self.cmap_index = 0 - self.smap_index = 0 - self.emap_index = 0 - self.pmap_index = 0 - self.fmap_index = 0 - self.lmap_index = 0 - self.omap_index = 0 - self.rmap_index = 0 - self.nmap_index = 0 - self.env = Environment(self) - self.person_map = Map(Table(self._tables["Person"])) - self.family_map = Map(Table(self._tables["Family"])) - self.place_map = Map(Table(self._tables["Place"])) - self.citation_map = Map(Table(self._tables["Citation"])) - self.source_map = Map(Table(self._tables["Source"])) - self.repository_map = Map(Table(self._tables["Repository"])) - self.note_map = Map(Table(self._tables["Note"])) - self.media_map = Map(Table(self._tables["Media"])) - self.event_map = Map(Table(self._tables["Event"])) - self.tag_map = Map(Table(self._tables["Tag"])) - self.metadata = Map(Table({"cursor_func": lambda: MetaCursor()})) - self.name_group = {} - self.event_names = set() - self.individual_attributes = set() - self.family_attributes = set() - self.source_attributes = set() - self.child_ref_types = set() - self.family_rel_types = set() - self.event_role_names = set() - self.name_types = set() - self.origin_types = set() - self.repository_types = set() - self.note_types = set() - self.source_media_types = set() - self.url_types = set() - self.media_attributes = set() - self.place_types = set() - _LOG.info("Django loading... done!") - - def prepare_import(self): - """ - DbDjango does not commit data on gedcom import, but saves them - for later commit. - """ - self.use_import_cache = True - self.import_cache = {} - - @transaction.atomic - def commit_import(self): - """ - Commits the items that were queued up during the last gedcom - import for two step adding. - """ - # First we add the primary objects: - for key in list(self.import_cache.keys()): - obj = self.import_cache[key] - if isinstance(obj, Person): - self.dji.add_person(obj.serialize()) - elif isinstance(obj, Family): - self.dji.add_family(obj.serialize()) - elif isinstance(obj, Event): - self.dji.add_event(obj.serialize()) - elif isinstance(obj, Place): - self.dji.add_place(obj.serialize()) - elif isinstance(obj, Repository): - self.dji.add_repository(obj.serialize()) - elif isinstance(obj, Citation): - self.dji.add_citation(obj.serialize()) - elif isinstance(obj, Source): - self.dji.add_source(obj.serialize()) - elif isinstance(obj, Note): - self.dji.add_note(obj.serialize()) - elif isinstance(obj, MediaObject): - self.dji.add_media(obj.serialize()) - elif isinstance(obj, Tag): - self.dji.add_tag(obj.serialize()) - # Next we add the links: - for key in list(self.import_cache.keys()): - obj = self.import_cache[key] - if isinstance(obj, Person): - self.dji.add_person_detail(obj.serialize()) - elif isinstance(obj, Family): - self.dji.add_family_detail(obj.serialize()) - elif isinstance(obj, Event): - self.dji.add_event_detail(obj.serialize()) - elif isinstance(obj, Place): - self.dji.add_place_detail(obj.serialize()) - elif isinstance(obj, Repository): - self.dji.add_repository_detail(obj.serialize()) - elif isinstance(obj, Citation): - self.dji.add_citation_detail(obj.serialize()) - elif isinstance(obj, Source): - self.dji.add_source_detail(obj.serialize()) - elif isinstance(obj, Note): - self.dji.add_note_detail(obj.serialize()) - elif isinstance(obj, MediaObject): - self.dji.add_media_detail(obj.serialize()) - elif isinstance(obj, Tag): - self.dji.add_tag_detail(obj.serialize()) - self.use_import_cache = False - self.import_cache = {} - self.request_rebuild() - - def transaction_commit(self, txn): - pass - - def request_rebuild(self): - # caches are ok, but let's compute public's - self.dji.update_publics() - self.emit('person-rebuild') - self.emit('family-rebuild') - self.emit('place-rebuild') - self.emit('source-rebuild') - self.emit('citation-rebuild') - self.emit('media-rebuild') - self.emit('event-rebuild') - self.emit('repository-rebuild') - self.emit('note-rebuild') - self.emit('tag-rebuild') - - def get_undodb(self): - return None - - def transaction_abort(self, txn): - pass - - @staticmethod - def _validated_id_prefix(val, default): - if isinstance(val, str) and val: - try: - str_ = val % 1 - except TypeError: # missing conversion specifier - prefix_var = val + "%d" - except ValueError: # incomplete format - prefix_var = default+"%04d" - else: - prefix_var = val # OK as given - else: - prefix_var = default+"%04d" # not a string or empty string - return prefix_var - - @staticmethod - def __id2user_format(id_pattern): - """ - Return a method that accepts a Gramps ID and adjusts it to the users - format. - """ - pattern_match = re.match(r"(.*)%[0 ](\d+)[diu]$", id_pattern) - if pattern_match: - str_prefix = pattern_match.group(1) - nr_width = pattern_match.group(2) - def closure_func(gramps_id): - if gramps_id and gramps_id.startswith(str_prefix): - id_number = gramps_id[len(str_prefix):] - if id_number.isdigit(): - id_value = int(id_number, 10) - #if len(str(id_value)) > nr_width: - # # The ID to be imported is too large to fit in the - # # users format. For now just create a new ID, - # # because that is also what happens with IDs that - # # are identical to IDs already in the database. If - # # the problem of colliding import and already - # # present IDs is solved the code here also needs - # # some solution. - # gramps_id = id_pattern % 1 - #else: - gramps_id = id_pattern % id_value - return gramps_id - else: - def closure_func(gramps_id): - return gramps_id - return closure_func - - def set_person_id_prefix(self, val): - """ - Set the naming template for GRAMPS Person ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as I%d or I%04d. - """ - self.person_prefix = self._validated_id_prefix(val, "I") - self.id2user_format = self.__id2user_format(self.person_prefix) - - def set_citation_id_prefix(self, val): - """ - Set the naming template for GRAMPS Citation ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as C%d or C%04d. - """ - self.citation_prefix = self._validated_id_prefix(val, "C") - self.cid2user_format = self.__id2user_format(self.citation_prefix) - - def set_source_id_prefix(self, val): - """ - Set the naming template for GRAMPS Source ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as S%d or S%04d. - """ - self.source_prefix = self._validated_id_prefix(val, "S") - self.sid2user_format = self.__id2user_format(self.source_prefix) - - def set_object_id_prefix(self, val): - """ - Set the naming template for GRAMPS MediaObject ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as O%d or O%04d. - """ - self.mediaobject_prefix = self._validated_id_prefix(val, "O") - self.oid2user_format = self.__id2user_format(self.mediaobject_prefix) - - def set_place_id_prefix(self, val): - """ - Set the naming template for GRAMPS Place ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as P%d or P%04d. - """ - self.place_prefix = self._validated_id_prefix(val, "P") - self.pid2user_format = self.__id2user_format(self.place_prefix) - - def set_family_id_prefix(self, val): - """ - Set the naming template for GRAMPS Family ID values. The string is - expected to be in the form of a simple text string, or in a format - that contains a C/Python style format string using %d, such as F%d - or F%04d. - """ - self.family_prefix = self._validated_id_prefix(val, "F") - self.fid2user_format = self.__id2user_format(self.family_prefix) - - def set_event_id_prefix(self, val): - """ - Set the naming template for GRAMPS Event ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as E%d or E%04d. - """ - self.event_prefix = self._validated_id_prefix(val, "E") - self.eid2user_format = self.__id2user_format(self.event_prefix) - - def set_repository_id_prefix(self, val): - """ - Set the naming template for GRAMPS Repository ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as R%d or R%04d. - """ - self.repository_prefix = self._validated_id_prefix(val, "R") - self.rid2user_format = self.__id2user_format(self.repository_prefix) - - def set_note_id_prefix(self, val): - """ - Set the naming template for GRAMPS Note ID values. - - The string is expected to be in the form of a simple text string, or - in a format that contains a C/Python style format string using %d, - such as N%d or N%04d. - """ - self.note_prefix = self._validated_id_prefix(val, "N") - self.nid2user_format = self.__id2user_format(self.note_prefix) - - def __find_next_gramps_id(self, prefix, map_index, trans): - """ - Helper function for find_next__gramps_id methods - """ - index = prefix % map_index - while trans.get(str(index), txn=self.txn) is not None: - map_index += 1 - index = prefix % map_index - map_index += 1 - return (map_index, index) - - def find_next_person_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Person object based off the - person ID prefix. - """ - self.pmap_index, gid = self.__find_next_gramps_id(self.person_prefix, - self.pmap_index, self.id_trans) - return gid - - def find_next_place_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Place object based off the - place ID prefix. - """ - self.lmap_index, gid = self.__find_next_gramps_id(self.place_prefix, - self.lmap_index, self.pid_trans) - return gid - - def find_next_event_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Event object based off the - event ID prefix. - """ - self.emap_index, gid = self.__find_next_gramps_id(self.event_prefix, - self.emap_index, self.eid_trans) - return gid - - def find_next_object_gramps_id(self): - """ - Return the next available GRAMPS' ID for a MediaObject object based - off the media object ID prefix. - """ - self.omap_index, gid = self.__find_next_gramps_id(self.mediaobject_prefix, - self.omap_index, self.oid_trans) - return gid - - def find_next_citation_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Citation object based off the - citation ID prefix. - """ - self.cmap_index, gid = self.__find_next_gramps_id(self.citation_prefix, - self.cmap_index, self.cid_trans) - return gid - - def find_next_source_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Source object based off the - source ID prefix. - """ - self.smap_index, gid = self.__find_next_gramps_id(self.source_prefix, - self.smap_index, self.sid_trans) - return gid - - def find_next_family_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Family object based off the - family ID prefix. - """ - self.fmap_index, gid = self.__find_next_gramps_id(self.family_prefix, - self.fmap_index, self.fid_trans) - return gid - - def find_next_repository_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Respository object based - off the repository ID prefix. - """ - self.rmap_index, gid = self.__find_next_gramps_id(self.repository_prefix, - self.rmap_index, self.rid_trans) - return gid - - def find_next_note_gramps_id(self): - """ - Return the next available GRAMPS' ID for a Note object based off the - note ID prefix. - """ - self.nmap_index, gid = self.__find_next_gramps_id(self.note_prefix, - self.nmap_index, self.nid_trans) - return gid - - def get_mediapath(self): - return None - - def get_name_group_keys(self): - return [] - - def get_name_group_mapping(self, key): - return None - - def get_researcher(self): - return self.owner - - def get_tag_handles(self, sort_handles=False): - if sort_handles: - return [item.handle for item in self.dji.Tag.all().order_by("handle")] - else: - return [item.handle for item in self.dji.Tag.all()] - - def get_person_handles(self, sort_handles=False): - if sort_handles: - return [item.handle for item in self.dji.Person.all().order_by("handle")] - else: - return [item.handle for item in self.dji.Person.all()] - - def get_family_handles(self, sort_handles=False): - if sort_handles: - return [item.handle for item in self.dji.Family.all().order_by("handle")] - else: - return [item.handle for item in self.dji.Family.all()] - - def get_event_handles(self, sort_handles=False): - if sort_handles: - return [item.handle for item in self.dji.Event.all().order_by("handle")] - else: - return [item.handle for item in self.dji.Event.all()] - - def get_citation_handles(self, sort_handles=False): - if sort_handles: - return [item.handle for item in self.dji.Citation.all().order_by("handle")] - else: - return [item.handle for item in self.dji.Citation.all()] - - def get_source_handles(self, sort_handles=False): - if sort_handles: - return [item.handle for item in self.dji.Source.all().order_by("handle")] - else: - return [item.handle for item in self.dji.Source.all()] - - def get_place_handles(self, sort_handles=False): - if sort_handles: - return [item.handle for item in self.dji.Place.all().order_by("handle")] - else: - return [item.handle for item in self.dji.Place.all()] - - def get_repository_handles(self, sort_handles=False): - if sort_handles: - return [item.handle for item in self.dji.Repository.all().order_by("handle")] - else: - return [item.handle for item in self.dji.Repository.all()] - - def get_media_object_handles(self, sort_handles=False): - if sort_handles: - return [item.handle for item in self.dji.Media.all().order_by("handle")] - else: - return [item.handle for item in self.dji.Media.all()] - - def get_note_handles(self, sort_handles=False): - if sort_handles: - return [item.handle for item in self.dji.Note.all().order_by("handle")] - else: - return [item.handle for item in self.dji.Note.all()] - - def get_media_from_handle(self, handle): - if handle in self.import_cache: - return self.import_cache[handle] - try: - media = self.dji.Media.get(handle=handle) - except: - return None - return self.make_media(media) - - def get_event_from_handle(self, handle): - if handle in self.import_cache: - return self.import_cache[handle] - try: - event = self.dji.Event.get(handle=handle) - except: - return None - return self.make_event(event) - - def get_family_from_handle(self, handle): - if handle in self.import_cache: - return self.import_cache[handle] - try: - family = self.dji.Family.get(handle=handle) - except: - return None - return self.make_family(family) - - def get_repository_from_handle(self, handle): - if handle in self.import_cache: - return self.import_cache[handle] - try: - repository = self.dji.Repository.get(handle=handle) - except: - return None - return self.make_repository(repository) - - def get_person_from_handle(self, handle): - if handle in self.import_cache: - return self.import_cache[handle] - try: - person = self.dji.Person.get(handle=handle) - except: - return None - return self.make_person(person) - - def get_tag_from_handle(self, handle): - if handle in self.import_cache: - return self.import_cache[handle] - try: - tag = self.dji.Tag.get(handle=handle) - except: - return None - return self.make_tag(tag) - - def make_repository(self, repository): - if self.use_db_cache and repository.cache: - data = repository.from_cache() - else: - data = self.dji.get_repository(repository) - return Repository.create(data) - - def make_citation(self, citation): - if self.use_db_cache and citation.cache: - data = citation.from_cache() - else: - data = self.dji.get_citation(citation) - return Citation.create(data) - - def make_source(self, source): - if self.use_db_cache and source.cache: - data = source.from_cache() - else: - data = self.dji.get_source(source) - return Source.create(data) - - def make_family(self, family): - if self.use_db_cache and family.cache: - data = family.from_cache() - else: - data = self.dji.get_family(family) - return Family.create(data) - - def make_person(self, person): - if self.use_db_cache and person.cache: - data = person.from_cache() - else: - data = self.dji.get_person(person) - return Person.create(data) - - def make_event(self, event): - if self.use_db_cache and event.cache: - data = event.from_cache() - else: - data = self.dji.get_event(event) - return Event.create(data) - - def make_note(self, note): - if self.use_db_cache and note.cache: - data = note.from_cache() - else: - data = self.dji.get_note(note) - return Note.create(data) - - def make_tag(self, tag): - data = self.dji.get_tag(tag) - return Tag.create(data) - - def make_place(self, place): - if self.use_db_cache and place.cache: - data = place.from_cache() - else: - data = self.dji.get_place(place) - return Place.create(data) - - def make_media(self, media): - if self.use_db_cache and media.cache: - data = media.from_cache() - else: - data = self.dji.get_media(media) - return MediaObject.create(data) - - def get_place_from_handle(self, handle): - if handle in self.import_cache: - return self.import_cache[handle] - try: - place = self.dji.Place.get(handle=handle) - except: - return None - return self.make_place(place) - - def get_citation_from_handle(self, handle): - if handle in self.import_cache: - return self.import_cache[handle] - try: - citation = self.dji.Citation.get(handle=handle) - except: - return None - return self.make_citation(citation) - - def get_source_from_handle(self, handle): - if handle in self.import_cache: - return self.import_cache[handle] - try: - source = self.dji.Source.get(handle=handle) - except: - return None - return self.make_source(source) - - def get_note_from_handle(self, handle): - if handle in self.import_cache: - return self.import_cache[handle] - try: - note = self.dji.Note.get(handle=handle) - except: - return None - return self.make_note(note) - - def get_object_from_handle(self, handle): - if handle in self.import_cache: - return self.import_cache[handle] - try: - media = self.dji.Media.get(handle=handle) - except: - return None - return self.make_media(media) - - def get_default_person(self): - people = self.dji.Person.all() - if people.count() > 0: - return self.make_person(people[0]) - return None - - def iter_people(self): - return (self.get_person_from_handle(person.handle) - for person in self.dji.Person.all()) - - def iter_person_handles(self): - return (person.handle for person in self.dji.Person.all()) - - def iter_families(self): - return (self.get_family_from_handle(family.handle) - for family in self.dji.Family.all()) - - def iter_family_handles(self): - return (family.handle for family in self.dji.Family.all()) - - def iter_notes(self): - return (self.get_note_from_handle(note.handle) - for note in self.dji.Note.all()) - - def iter_note_handles(self): - return (note.handle for note in self.dji.Note.all()) - - def iter_events(self): - return (self.get_event_from_handle(event.handle) - for event in self.dji.Event.all()) - - def iter_event_handles(self): - return (event.handle for event in self.dji.Event.all()) - - def iter_places(self): - return (self.get_place_from_handle(place.handle) - for place in self.dji.Place.all()) - - def iter_place_handles(self): - return (place.handle for place in self.dji.Place.all()) - - def iter_repositories(self): - return (self.get_repository_from_handle(repository.handle) - for repository in self.dji.Repository.all()) - - def iter_repository_handles(self): - return (repository.handle for repository in self.dji.Repository.all()) - - def iter_sources(self): - return (self.get_source_from_handle(source.handle) - for source in self.dji.Source.all()) - - def iter_source_handles(self): - return (source.handle for source in self.dji.Source.all()) - - def iter_citations(self): - return (self.get_citation_from_handle(citation.handle) - for citation in self.dji.Citation.all()) - - def iter_citation_handles(self): - return (citation.handle for citation in self.dji.Citation.all()) - - def iter_tags(self): - return (self.get_tag_from_handle(tag.handle) - for tag in self.dji.Tag.all()) - - def iter_tag_handles(self): - return (tag.handle for tag in self.dji.Tag.all()) - - def iter_media_objects(self): - return (self.get_media_from_handle(media.handle) - for media in self.dji.Media.all()) - - def get_tag_from_name(self, name): - try: - tag = self.dji.Tag.filter(name=name) - return self.make_tag(tag[0]) - except: - return None - - def get_person_from_gramps_id(self, gramps_id): - if self.import_cache: - for handle in self.import_cache: - if self.import_cache[handle].gramps_id == gramps_id: - return self.import_cache[handle] - match_list = self.dji.Person.filter(gramps_id=gramps_id) - if match_list.count() > 0: - return self.make_person(match_list[0]) - else: - return None - - def get_family_from_gramps_id(self, gramps_id): - if self.import_cache: - for handle in self.import_cache: - if self.import_cache[handle].gramps_id == gramps_id: - return self.import_cache[handle] - try: - family = self.dji.Family.get(gramps_id=gramps_id) - except: - return None - return self.make_family(family) - - def get_source_from_gramps_id(self, gramps_id): - if self.import_cache: - for handle in self.import_cache: - if self.import_cache[handle].gramps_id == gramps_id: - return self.import_cache[handle] - match_list = self.dji.Source.filter(gramps_id=gramps_id) - if match_list.count() > 0: - return self.make_source(match_list[0]) - else: - return None - - def get_citation_from_gramps_id(self, gramps_id): - if self.import_cache: - for handle in self.import_cache: - if self.import_cache[handle].gramps_id == gramps_id: - return self.import_cache[handle] - match_list = self.dji.Citation.filter(gramps_id=gramps_id) - if match_list.count() > 0: - return self.make_citation(match_list[0]) - else: - return None - - def get_event_from_gramps_id(self, gramps_id): - if self.import_cache: - for handle in self.import_cache: - if self.import_cache[handle].gramps_id == gramps_id: - return self.import_cache[handle] - match_list = self.dji.Event.filter(gramps_id=gramps_id) - if match_list.count() > 0: - return self.make_event(match_list[0]) - else: - return None - - def get_object_from_gramps_id(self, gramps_id): - if self.import_cache: - for handle in self.import_cache: - if self.import_cache[handle].gramps_id == gramps_id: - return self.import_cache[handle] - match_list = self.dji.Media.filter(gramps_id=gramps_id) - if match_list.count() > 0: - return self.make_media(match_list[0]) - else: - return None - - def get_place_from_gramps_id(self, gramps_id): - if self.import_cache: - for handle in self.import_cache: - if self.import_cache[handle].gramps_id == gramps_id: - return self.import_cache[handle] - match_list = self.dji.Place.filter(gramps_id=gramps_id) - if match_list.count() > 0: - return self.make_place(match_list[0]) - else: - return None - - def get_repository_from_gramps_id(self, gramps_id): - if self.import_cache: - for handle in self.import_cache: - if self.import_cache[handle].gramps_id == gramps_id: - return self.import_cache[handle] - match_list = self.dji.Repsoitory.filter(gramps_id=gramps_id) - if match_list.count() > 0: - return self.make_repository(match_list[0]) - else: - return None - - def get_note_from_gramps_id(self, gramps_id): - if self.import_cache: - for handle in self.import_cache: - if self.import_cache[handle].gramps_id == gramps_id: - return self.import_cache[handle] - match_list = self.dji.Note.filter(gramps_id=gramps_id) - if match_list.count() > 0: - return self.make_note(match_list[0]) - else: - return None - - def get_number_of_people(self): - return self.dji.Person.count() - - def get_number_of_events(self): - return self.dji.Event.count() - - def get_number_of_places(self): - return self.dji.Place.count() - - def get_number_of_tags(self): - return self.dji.Tag.count() - - def get_number_of_families(self): - return self.dji.Family.count() - - def get_number_of_notes(self): - return self.dji.Note.count() - - def get_number_of_citations(self): - return self.dji.Citation.count() - - def get_number_of_sources(self): - return self.dji.Source.count() - - def get_number_of_media_objects(self): - return self.dji.Media.count() - - def get_number_of_repositories(self): - return self.dji.Repository.count() - - def get_place_cursor(self): - return Cursor(self.dji.Place, self.get_raw_place_data) - - def get_person_cursor(self): - return Cursor(self.dji.Person, self.get_raw_person_data) - - def get_family_cursor(self): - return Cursor(self.dji.Family, self.get_raw_family_data) - - def get_event_cursor(self): - return Cursor(self.dji.Event, self.get_raw_event_data) - - def get_citation_cursor(self): - return Cursor(self.dji.Citation, self.get_raw_citation_data) - - def get_source_cursor(self): - return Cursor(self.dji.Source, self.get_raw_source_data) - - def get_note_cursor(self): - return Cursor(self.dji.Note, self.get_raw_note_data) - - def get_tag_cursor(self): - return Cursor(self.dji.Tag, self.get_raw_tag_data) - - def get_repository_cursor(self): - return Cursor(self.dji.Repository, self.get_raw_repository_data) - - def get_media_cursor(self): - return Cursor(self.dji.Media, self.get_raw_object_data) - - def has_gramps_id(self, obj_key, gramps_id): - key2table = { - PERSON_KEY: self.dji.Person, - FAMILY_KEY: self.dji.Family, - SOURCE_KEY: self.dji.Source, - CITATION_KEY: self.dji.Citation, - EVENT_KEY: self.dji.Event, - MEDIA_KEY: self.dji.Media, - PLACE_KEY: self.dji.Place, - REPOSITORY_KEY: self.dji.Repository, - NOTE_KEY: self.dji.Note, - } - table = key2table[obj_key] - return table.filter(gramps_id=gramps_id).count() > 0 - - def has_person_handle(self, handle): - if handle in self.import_cache: - return True - return self.dji.Person.filter(handle=handle).count() == 1 - - def has_family_handle(self, handle): - if handle in self.import_cache: - return True - return self.dji.Family.filter(handle=handle).count() == 1 - - def has_citation_handle(self, handle): - if handle in self.import_cache: - return True - return self.dji.Citation.filter(handle=handle).count() == 1 - - def has_source_handle(self, handle): - if handle in self.import_cache: - return True - return self.dji.Source.filter(handle=handle).count() == 1 - - def has_repository_handle(self, handle): - if handle in self.import_cache: - return True - return self.dji.Repository.filter(handle=handle).count() == 1 - - def has_note_handle(self, handle): - if handle in self.import_cache: - return True - return self.dji.Note.filter(handle=handle).count() == 1 - - def has_place_handle(self, handle): - if handle in self.import_cache: - return True - return self.dji.Place.filter(handle=handle).count() == 1 - - def has_event_handle(self, handle): - if handle in self.import_cache: - return True - return self.dji.Event.filter(handle=handle).count() == 1 - - def has_tag_handle(self, handle): - if handle in self.import_cache: - return True - return self.dji.Tag.filter(handle=handle).count() == 1 - - def has_object_handle(self, handle): - if handle in self.import_cache: - return True - return self.dji.Media.filter(handle=handle).count() == 1 - - def has_name_group_key(self, key): - # FIXME: - return False - - def set_name_group_mapping(self, key, value): - # FIXME: - pass - - def set_default_person_handle(self, handle): - pass - - def set_mediapath(self, mediapath): - pass - - def get_raw_person_data(self, handle): - try: - return self.dji.get_person(self.dji.Person.get(handle=handle)) - except: - if handle in self.import_cache: - return self.import_cache[handle].serialize() - else: - return None - - def get_raw_family_data(self, handle): - try: - return self.dji.get_family(self.dji.Family.get(handle=handle)) - except: - if handle in self.import_cache: - return self.import_cache[handle].serialize() - else: - return None - - def get_raw_citation_data(self, handle): - try: - return self.dji.get_citation(self.dji.Citation.get(handle=handle)) - except: - if handle in self.import_cache: - return self.import_cache[handle].serialize() - else: - return None - - def get_raw_source_data(self, handle): - try: - return self.dji.get_source(self.dji.Source.get(handle=handle)) - except: - if handle in self.import_cache: - return self.import_cache[handle].serialize() - else: - return None - - def get_raw_repository_data(self, handle): - try: - return self.dji.get_repository(self.dji.Repository.get(handle=handle)) - except: - if handle in self.import_cache: - return self.import_cache[handle].serialize() - else: - return None - - def get_raw_note_data(self, handle): - try: - return self.dji.get_note(self.dji.Note.get(handle=handle)) - except: - if handle in self.import_cache: - return self.import_cache[handle].serialize() - else: - return None - - def get_raw_place_data(self, handle): - try: - return self.dji.get_place(self.dji.Place.get(handle=handle)) - except: - if handle in self.import_cache: - return self.import_cache[handle].serialize() - else: - return None - - def get_raw_object_data(self, handle): - try: - return self.dji.get_media(self.dji.Media.get(handle=handle)) - except: - if handle in self.import_cache: - return self.import_cache[handle].serialize() - else: - return None - - def get_raw_tag_data(self, handle): - try: - return self.dji.get_tag(self.dji.Tag.get(handle=handle)) - except: - if handle in self.import_cache: - return self.import_cache[handle].serialize() - else: - return None - - def get_raw_event_data(self, handle): - try: - return self.dji.get_event(self.dji.Event.get(handle=handle)) - except: - if handle in self.import_cache: - return self.import_cache[handle].serialize() - else: - return None - - def add_person(self, person, trans, set_gid=True): - if not person.handle: - person.handle = create_id() - if not person.gramps_id: - person.gramps_id = self.find_next_person_gramps_id() - self.commit_person(person, trans) - return person.handle - - def add_family(self, family, trans, set_gid=True): - if not family.handle: - family.handle = create_id() - if not family.gramps_id: - family.gramps_id = self.find_next_family_gramps_id() - self.commit_family(family, trans) - return family.handle - - def add_citation(self, citation, trans, set_gid=True): - if not citation.handle: - citation.handle = create_id() - if not citation.gramps_id: - citation.gramps_id = self.find_next_citation_gramps_id() - self.commit_citation(citation, trans) - return citation.handle - - def add_source(self, source, trans, set_gid=True): - if not source.handle: - source.handle = create_id() - if not source.gramps_id: - source.gramps_id = self.find_next_source_gramps_id() - self.commit_source(source, trans) - return source.handle - - def add_repository(self, repository, trans, set_gid=True): - if not repository.handle: - repository.handle = create_id() - if not repository.gramps_id: - repository.gramps_id = self.find_next_repository_gramps_id() - self.commit_repository(repository, trans) - return repository.handle - - def add_note(self, note, trans, set_gid=True): - if not note.handle: - note.handle = create_id() - if not note.gramps_id: - note.gramps_id = self.find_next_note_gramps_id() - self.commit_note(note, trans) - return note.handle - - def add_place(self, place, trans, set_gid=True): - if not place.handle: - place.handle = create_id() - if not place.gramps_id: - place.gramps_id = self.find_next_place_gramps_id() - self.commit_place(place, trans) - return place.handle - - def add_event(self, event, trans, set_gid=True): - if not event.handle: - event.handle = create_id() - if not event.gramps_id: - event.gramps_id = self.find_next_event_gramps_id() - self.commit_event(event, trans) - return event.handle - - def add_tag(self, tag, trans): - if not tag.handle: - tag.handle = create_id() - self.commit_tag(tag, trans) - return tag.handle - - def add_object(self, obj, transaction, set_gid=True): - """ - Add a MediaObject to the database, assigning internal IDs if they have - not already been defined. - - If not set_gid, then gramps_id is not set. - """ - if not obj.handle: - obj.handle = create_id() - if not obj.gramps_id: - obj.gramps_id = self.find_next_object_gramps_id() - self.commit_media_object(obj, transaction) - return obj.handle - - def commit_person(self, person, trans, change_time=None): - if self.use_import_cache: - self.import_cache[person.handle] = person - else: - raw = person.serialize() - items = self.dji.Person.filter(handle=person.handle) - count = items.count() - if count > 0: - # Hack, for the moment: delete and re-add - items[0].delete() - self.dji.add_person(person.serialize()) - self.dji.add_person_detail(person.serialize()) - if not trans.batch: - if count > 0: - self.emit("person-update", ([person.handle],)) - else: - self.emit("person-add", ([person.handle],)) - - def commit_family(self, family, trans, change_time=None): - if self.use_import_cache: - self.import_cache[family.handle] = family - else: - raw = family.serialize() - items = self.dji.Family.filter(handle=family.handle) - count = items.count() - if count > 0: - items[0].delete() - self.dji.add_family(family.serialize()) - self.dji.add_family_detail(family.serialize()) - if not trans.batch: - if count > 0: - self.emit("family-update", ([family.handle],)) - else: - self.emit("family-add", ([family.handle],)) - - def commit_citation(self, citation, trans, change_time=None): - if self.use_import_cache: - self.import_cache[citation.handle] = citation - else: - raw = citation.serialize() - items = self.dji.Citation.filter(handle=citation.handle) - count = items.count() - if count > 0: - items[0].delete() - self.dji.add_citation(citation.serialize()) - self.dji.add_citation_detail(citation.serialize()) - if not trans.batch: - if count > 0: - self.emit("citation-update", ([citation.handle],)) - else: - self.emit("citation-add", ([citation.handle],)) - - def commit_source(self, source, trans, change_time=None): - if self.use_import_cache: - self.import_cache[source.handle] = source - else: - raw = source.serialize() - items = self.dji.Source.filter(handle=source.handle) - count = items.count() - if count > 0: - items[0].delete() - self.dji.add_source(source.serialize()) - self.dji.add_source_detail(source.serialize()) - if not trans.batch: - if count > 0: - self.emit("source-update", ([source.handle],)) - else: - self.emit("source-add", ([source.handle],)) - - def commit_repository(self, repository, trans, change_time=None): - if self.use_import_cache: - self.import_cache[repository.handle] = repository - else: - raw = repository.serialize() - items = self.dji.Repository.filter(handle=repository.handle) - count = items.count() - if count > 0: - items[0].delete() - self.dji.add_repository(repository.serialize()) - self.dji.add_repository_detail(repository.serialize()) - if not trans.batch: - if count > 0: - self.emit("repository-update", ([repository.handle],)) - else: - self.emit("repository-add", ([repository.handle],)) - - def commit_note(self, note, trans, change_time=None): - if self.use_import_cache: - self.import_cache[note.handle] = note - else: - raw = note.serialize() - items = self.dji.Note.filter(handle=note.handle) - count = items.count() - if count > 0: - items[0].delete() - self.dji.add_note(note.serialize()) - self.dji.add_note_detail(note.serialize()) - if not trans.batch: - if count > 0: - self.emit("note-update", ([note.handle],)) - else: - self.emit("note-add", ([note.handle],)) - - def commit_place(self, place, trans, change_time=None): - if self.use_import_cache: - self.import_cache[place.handle] = place - else: - raw = place.serialize() - items = self.dji.Place.filter(handle=place.handle) - count = items.count() - if count > 0: - items[0].delete() - self.dji.add_place(place.serialize()) - self.dji.add_place_detail(place.serialize()) - if not trans.batch: - if count > 0: - self.emit("place-update", ([place.handle],)) - else: - self.emit("place-add", ([place.handle],)) - - def commit_event(self, event, trans, change_time=None): - if self.use_import_cache: - self.import_cache[event.handle] = event - else: - raw = event.serialize() - items = self.dji.Event.filter(handle=event.handle) - count = items.count() - if count > 0: - items[0].delete() - self.dji.add_event(event.serialize()) - self.dji.add_event_detail(event.serialize()) - if not trans.batch: - if count > 0: - self.emit("event-update", ([event.handle],)) - else: - self.emit("event-add", ([event.handle],)) - - def commit_tag(self, tag, trans, change_time=None): - if self.use_import_cache: - self.import_cache[tag.handle] = tag - else: - raw = tag.serialize() - items = self.dji.Tag.filter(handle=tag.handle) - count = items.count() - if count > 0: - items[0].delete() - self.dji.add_tag(tag.serialize()) - self.dji.add_tag_detail(tag.serialize()) - if not trans.batch: - if count > 0: - self.emit("tag-update", ([tag.handle],)) - else: - self.emit("tag-add", ([tag.handle],)) - - def commit_media_object(self, media, trans, change_time=None): - """ - Commit the specified MediaObject to the database, storing the changes - as part of the transaction. - """ - if self.use_import_cache: - self.import_cache[media.handle] = media - else: - raw = media.serialize() - items = self.dji.Media.filter(handle=media.handle) - count = items.count() - if count > 0: - items[0].delete() - self.dji.add_media(media.serialize()) - self.dji.add_media_detail(media.serialize()) - if not trans.batch: - if count > 0: - self.emit("media-update", ([media.handle],)) - else: - self.emit("media-add", ([media.handle],)) - - def get_gramps_ids(self, obj_key): - key2table = { - PERSON_KEY: self.id_trans, - FAMILY_KEY: self.fid_trans, - CITATION_KEY: self.cid_trans, - SOURCE_KEY: self.sid_trans, - EVENT_KEY: self.eid_trans, - MEDIA_KEY: self.oid_trans, - PLACE_KEY: self.pid_trans, - REPOSITORY_KEY: self.rid_trans, - NOTE_KEY: self.nid_trans, - } - - table = key2table[obj_key] - return list(table.keys()) - - def transaction_begin(self, transaction): - return - - def set_researcher(self, owner): - self.owner.set_from(owner) - - def copy_from_db(self, db): - """ - A (possibily) implementation-specific method to get data from - db into this database. - """ - # First we add the primary objects: - for key in db._tables.keys(): - cursor = db._tables[key]["cursor_func"] - for (handle, data) in cursor(): - if key == "Person": - self.dji.add_person(data) - elif key == "Family": - self.dji.add_family(data) - elif key == "Event": - self.dji.add_event(data) - elif key == "Place": - self.dji.add_place(data) - elif key == "Repository": - self.dji.add_repository(data) - elif key == "Citation": - self.dji.add_citation(data) - elif key == "Source": - self.dji.add_source(data) - elif key == "Note": - self.dji.add_note(data) - elif key == "Media": - self.dji.add_media(data) - elif key == "Tag": - self.dji.add_tag(data) - for key in db._tables.keys(): - cursor = db._tables[key]["cursor_func"] - for (handle, data) in cursor(): - if key == "Person": - self.dji.add_person_detail(data) - elif key == "Family": - self.dji.add_family_detail(data) - elif key == "Event": - self.dji.add_event_detail(data) - elif key == "Place": - self.dji.add_place_detail(data) - elif key == "Repository": - self.dji.add_repository_detail(data) - elif key == "Citation": - self.dji.add_citation_detail(data) - elif key == "Source": - self.dji.add_source_detail(data) - elif key == "Note": - self.dji.add_note_detail(data) - elif key == "Media": - self.dji.add_media_detail(data) - elif key == "Tag": - self.dji.add_tag_detail(data) - # Next we add the links: - self.dji.update_publics() - - def get_from_name_and_handle(self, table_name, handle): - """ - Returns a gen.lib object (or None) given table_name and - handle. - - Examples: - - >>> self.get_from_name_and_handle("Person", "a7ad62365bc652387008") - >>> self.get_from_name_and_handle("Media", "c3434653675bcd736f23") - """ - if table_name in self._tables: - return self._tables[table_name]["handle_func"](handle) - return None - - def is_empty(self): - """ - Is the database empty? - """ - return (self.get_number_of_people() == 0 and - self.get_number_of_events() == 0 and - self.get_number_of_places() == 0 and - self.get_number_of_tags() == 0 and - self.get_number_of_families() == 0 and - self.get_number_of_notes() == 0 and - self.get_number_of_citations() == 0 and - self.get_number_of_sources() == 0 and - self.get_number_of_media_objects() == 0 and - self.get_number_of_repositories() == 0) - - def set_prefixes(self, person, media, family, source, citation, - place, event, repository, note): - self.set_person_id_prefix(person) - self.set_object_id_prefix(media) - self.set_family_id_prefix(family) - self.set_source_id_prefix(source) - self.set_citation_id_prefix(citation) - self.set_place_id_prefix(place) - self.set_event_id_prefix(event) - self.set_repository_id_prefix(repository) - self.set_note_id_prefix(note) - - def has_changed(self): - return False - - def find_backlink_handles(self, handle, include_classes=None): - ## FIXME: figure out how to get objects that refer - ## to this handle - return [] - - def get_note_bookmarks(self): - return self.note_bookmarks - - def get_media_bookmarks(self): - return self.media_bookmarks - - def get_repo_bookmarks(self): - return self.repo_bookmarks - - def get_citation_bookmarks(self): - return self.citation_bookmarks - - def get_source_bookmarks(self): - return self.source_bookmarks - - def get_place_bookmarks(self): - return self.place_bookmarks - - def get_event_bookmarks(self): - return self.event_bookmarks - - def get_bookmarks(self): - return self.bookmarks - - def get_family_bookmarks(self): - return self.family_bookmarks - - def get_save_path(self): - return self._directory - - def set_save_path(self, directory): - self._directory = directory - self.full_name = os.path.abspath(self._directory) - self.path = self.full_name - self.brief_name = os.path.basename(self._directory) - - ## Get types: - def get_event_attribute_types(self): - """ - Return a list of all Attribute types assocated with Event instances - in the database. - """ - return list(self.event_attributes) - - def get_event_types(self): - """ - Return a list of all event types in the database. - """ - return list(self.event_names) - - def get_person_event_types(self): - """ - Deprecated: Use get_event_types - """ - return list(self.event_names) - - def get_person_attribute_types(self): - """ - Return a list of all Attribute types assocated with Person instances - in the database. - """ - return list(self.individual_attributes) - - def get_family_attribute_types(self): - """ - Return a list of all Attribute types assocated with Family instances - in the database. - """ - return list(self.family_attributes) - - def get_family_event_types(self): - """ - Deprecated: Use get_event_types - """ - return list(self.event_names) - - def get_media_attribute_types(self): - """ - Return a list of all Attribute types assocated with Media and MediaRef - instances in the database. - """ - return list(self.media_attributes) - - def get_family_relation_types(self): - """ - Return a list of all relationship types assocated with Family - instances in the database. - """ - return list(self.family_rel_types) - - def get_child_reference_types(self): - """ - Return a list of all child reference types assocated with Family - instances in the database. - """ - return list(self.child_ref_types) - - def get_event_roles(self): - """ - Return a list of all custom event role names assocated with Event - instances in the database. - """ - return list(self.event_role_names) - - def get_name_types(self): - """ - Return a list of all custom names types assocated with Person - instances in the database. - """ - return list(self.name_types) - - def get_origin_types(self): - """ - Return a list of all custom origin types assocated with Person/Surname - instances in the database. - """ - return list(self.origin_types) - - def get_repository_types(self): - """ - Return a list of all custom repository types assocated with Repository - instances in the database. - """ - return list(self.repository_types) - - def get_note_types(self): - """ - Return a list of all custom note types assocated with Note instances - in the database. - """ - return list(self.note_types) - - def get_source_attribute_types(self): - """ - Return a list of all Attribute types assocated with Source/Citation - instances in the database. - """ - return list(self.source_attributes) - - def get_source_media_types(self): - """ - Return a list of all custom source media types assocated with Source - instances in the database. - """ - return list(self.source_media_types) - - def get_url_types(self): - """ - Return a list of all custom names types assocated with Url instances - in the database. - """ - return list(self.url_types) - - def get_place_types(self): - """ - Return a list of all custom place types assocated with Place instances - in the database. - """ - return list(self.place_types) - - def get_default_handle(self): - people = self.dji.Person.all() - if people.count() > 0: - return people[0].handle - return None - - def close(self): - if self._directory: - filename = os.path.join(self._directory, "meta_data.db") - touch(filename) - - def get_surname_list(self): - return [] - - def is_open(self): - return True - - def get_table_names(self): - """Return a list of valid table names.""" - return list(self._tables.keys()) - - def find_initial_person(self): - return self.get_default_person() - - # Removals: - def remove_person(self, handle, txn): - self.dji.Person.filter(handle=handle)[0].delete() - self.emit("person-delete", ([handle],)) - - def remove_source(self, handle, transaction): - self.dji.Source.filter(handle=handle)[0].delete() - self.emit("source-delete", ([handle],)) - - def remove_citation(self, handle, transaction): - self.dji.Citation.filter(handle=handle)[0].delete() - self.emit("citation-delete", ([handle],)) - - def remove_event(self, handle, transaction): - self.dji.Event.filter(handle=handle)[0].delete() - self.emit("event-delete", ([handle],)) - - def remove_object(self, handle, transaction): - self.dji.Media.filter(handle=handle)[0].delete() - self.emit("media-delete", ([handle],)) - - def remove_place(self, handle, transaction): - self.dji.Place.filter(handle=handle)[0].delete() - self.emit("place-delete", ([handle],)) - - def remove_family(self, handle, transaction): - self.dji.Family.filter(handle=handle)[0].delete() - self.emit("family-delete", ([handle],)) - - def remove_repository(self, handle, transaction): - self.dji.Repository.filter(handle=handle)[0].delete() - self.emit("repository-delete", ([handle],)) - - def remove_note(self, handle, transaction): - self.dji.Note.filter(handle=handle)[0].delete() - self.emit("note-delete", ([handle],)) - - def remove_tag(self, handle, transaction): - self.dji.Tag.filter(handle=handle)[0].delete() - self.emit("tag-delete", ([handle],)) - - def remove_from_surname_list(self, person): - ## FIXME - ## called by a complete commit_person - pass - - ## was missing - - def find_place_child_handles(self, handle): - pass - - def get_cursor(self, table, txn=None, update=False, commit=False): - pass - - def get_number_of_records(self, table): - pass - - def get_place_parent_cursor(self): - pass - - def get_place_tree_cursor(self): - pass - - def get_table_metadata(self, table_name): - """Return the metadata for a valid table name.""" - if table_name in self._tables: - return self._tables[table_name] - return None - - def get_transaction_class(self): - pass - - def undo(self, update_history=True): - # FIXME: - return self.undodb.undo(update_history) - - def redo(self, update_history=True): - # FIXME: - return self.undodb.redo(update_history) - - def backup(self): - pass - - def restore(self): - pass - - def write_version(self, directory): - """Write files for a newly created DB.""" - versionpath = os.path.join(directory, str(DBBACKEND)) - _LOG.debug("Write database backend file to 'djangodb'") - with open(versionpath, "w") as version_file: - version_file.write("djangodb") - # Write default_settings, sqlite.db - defaults = os.path.join(os.path.dirname(os.path.abspath(__file__)), - "django_support", "defaults") - _LOG.debug("Copy defaults from: " + defaults) - for filename in os.listdir(defaults): - fullpath = os.path.abspath(os.path.join(defaults, filename)) - shutil.copy2(fullpath, directory) - # force load, to get all modules loaded because of reset issue - self.load(directory) - - def report_bm_change(self): - """ - Add 1 to the number of bookmark changes during this session. - """ - self._bm_changes += 1 - - def db_has_bm_changes(self): - """ - Return whethere there were bookmark changes during the session. - """ - return self._bm_changes > 0 - - def get_summary(self): - """ - Returns dictionary of summary item. - Should include, if possible: - - _("Number of people") - _("Version") - _("Schema version") - """ - return { - _("Number of people"): self.get_number_of_people(), - } - - def get_dbname(self): - """ - In Django, the database is in a text file at the path - """ - filepath = os.path.join(self._directory, "name.txt") - try: - name_file = open(filepath, "r") - name = name_file.readline().strip() - name_file.close() - except (OSError, IOError) as msg: - _LOG.error(str(msg)) - name = None - return name - - def reindex_reference_map(self): - pass - - def rebuild_secondary(self, update): - pass