diff --git a/gramps/cli/grampscli.py b/gramps/cli/grampscli.py
index fb7e2454d..03565f3d2 100644
--- a/gramps/cli/grampscli.py
+++ b/gramps/cli/grampscli.py
@@ -52,14 +52,9 @@ from gramps.gen.db.utils import make_database
from gramps.gen.errors import DbError
from gramps.gen.dbstate import DbState
from gramps.gen.db.exceptions import (DbUpgradeRequiredError,
- BsddbDowngradeError,
+ DbSupportedError,
DbVersionError,
DbPythonError,
- DbEnvironmentError,
- BsddbUpgradeRequiredError,
- BsddbDowngradeRequiredError,
- PythonUpgradeRequiredError,
- PythonDowngradeError,
DbConnectionError)
from gramps.gen.plug import BasePluginManager
from gramps.gen.utils.config import get_researcher
@@ -176,34 +171,8 @@ class CLIDbLoader:
try:
self.dbstate.db.load(filename, self._pulse_progress, mode,
username=username, password=password)
- except DbEnvironmentError as msg:
- self.dbstate.no_database()
- self._errordialog(_("Cannot open database"), str(msg))
- except BsddbUpgradeRequiredError as msg:
- self.dbstate.no_database()
- self._errordialog(_("Cannot open database"), str(msg))
- except BsddbDowngradeRequiredError as msg:
- self.dbstate.no_database()
- self._errordialog(_("Cannot open database"), str(msg))
- except BsddbDowngradeError as msg:
- self.dbstate.no_database()
- self._errordialog(_("Cannot open database"), str(msg))
- except DbUpgradeRequiredError as msg:
- self.dbstate.no_database()
- self._errordialog(_("Cannot open database"), str(msg))
- except PythonDowngradeError as msg:
- self.dbstate.no_database()
- self._errordialog(_("Cannot open database"), str(msg))
- except PythonUpgradeRequiredError as msg:
- self.dbstate.no_database()
- self._errordialog(_("Cannot open database"), str(msg))
- except DbVersionError as msg:
- self.dbstate.no_database()
- self._errordialog(_("Cannot open database"), str(msg))
- except DbPythonError as msg:
- self.dbstate.no_database()
- self._errordialog(_("Cannot open database"), str(msg))
- except DbConnectionError as msg:
+ except (DbConnectionError, DbSupportedError, DbUpgradeRequiredError,
+ DbVersionError, DbPythonError, DbConnectionError) as msg:
self.dbstate.no_database()
self._errordialog(_("Cannot open database"), str(msg))
except OSError as msg:
diff --git a/gramps/gen/db/exceptions.py b/gramps/gen/db/exceptions.py
index 9fb2ee346..ab23ca9d7 100644
--- a/gramps/gen/db/exceptions.py
+++ b/gramps/gen/db/exceptions.py
@@ -122,121 +122,6 @@ class DbPythonError(Exception):
'min_vers': self.min_vers,
'max_vers': self.max_vers}
-class BsddbDowngradeError(Exception):
- """
- Error used to report that the Berkeley database used to create the family
- tree is of a version that is too new to be supported by the current version.
- """
- def __init__(self, env_version, bdb_version):
- Exception.__init__(self)
- self.env_version = str(env_version)
- self.bdb_version = str(bdb_version)
-
- def __str__(self):
- return _('The Family Tree you are trying to load is in the Bsddb '
- 'version %(env_version)s format. This version of Gramps uses '
- 'Bsddb version %(bdb_version)s. So you are trying to load '
- 'data created in a newer format into an older program, and '
- 'this is bound to fail.\n\n'
- 'You should start your '
- '%(bold_start)snewer%(bold_end)s version of Gramps and '
- '%(wiki_backup_html_start)smake a backup%(html_end)s '
- 'of your Family Tree. You can then import '
- 'this backup into this version of Gramps.') % {
- 'wiki_backup_html_start' : URL_BACKUP1_START ,
- 'html_end' : '' ,
- 'bold_start' : '' ,
- 'bold_end' : '' ,
- 'env_version' : self.env_version,
- 'bdb_version' : self.bdb_version }
-
-class BsddbDowngradeRequiredError(Exception):
- """
- Error used to report that the Berkeley database used to create the family
- tree is of a version that is newer than the current version, but it may be
- possible to open the tree, because the difference is only a point upgrade
- (i.e. a difference in the last digit of the version tuple).
- """
- def __init__(self, env_version, bdb_version):
- Exception.__init__(self)
- self.env_version = str(env_version)
- self.bdb_version = str(bdb_version)
-
- def __str__(self):
- return _('The Family Tree you are trying to load is in the Bsddb '
- 'version %(env_version)s format. This version of Gramps uses '
- 'Bsddb version %(bdb_version)s. So you are trying to load '
- 'data created in a newer format into an older program. In '
- 'this particular case, the difference is very small, so it '
- 'may work.\n\n'
- 'If you have not already made a backup of your Family Tree, '
- 'then you should start your '
- '%(bold_start)snewer%(bold_end)s version of Gramps and '
- '%(wiki_backup_html_start)smake a backup%(html_end)s '
- 'of your Family Tree.') % {
- 'wiki_backup_html_start' : URL_BACKUP1_START ,
- 'html_end' : '' ,
- 'bold_start' : '' ,
- 'bold_end' : '' ,
- 'env_version' : self.env_version,
- 'bdb_version' : self.bdb_version }
-
-class BsddbUpgradeRequiredError(Exception):
- """
- Error used to report that the Berkeley database used to create the family
- tree is of a version that is too new to be supported by the current version.
- """
- def __init__(self, env_version, bsddb_version):
- Exception.__init__(self)
- self.env_version = str(env_version)
- self.bsddb_version = str(bsddb_version)
-
- def __str__(self):
- return _('The Family Tree you are trying to load is in the Bsddb '
- 'version %(env_version)s format. This version of Gramps uses '
- 'Bsddb version %(bdb_version)s. Therefore you cannot load '
- 'this Family Tree without upgrading the Bsddb version of the '
- 'Family Tree.\n\n'
- 'Opening the Family Tree with this version of Gramps might '
- 'irretrievably corrupt your Family Tree. You are strongly '
- 'advised to backup your Family Tree.\n\n'
- 'If you have not already made a backup of your Family Tree, '
- 'then you should start your %(bold_start)sold%(bold_end)s '
- 'version of Gramps and '
- '%(wiki_backup_html_start)smake a backup%(html_end)s '
- 'of your Family Tree.') % {
- 'wiki_backup_html_start' : URL_BACKUP1_START ,
- 'html_end' : '' ,
- 'bold_start' : '' ,
- 'bold_end' : '' ,
- 'env_version' : self.env_version,
- 'bdb_version' : self.bsddb_version }
-
-class DbEnvironmentError(Exception):
- """
- Error used to report that the database 'environment' could not be opened.
- Most likely, the database was created by a different version of the underlying database engine.
- """
- def __init__(self, msg):
- Exception.__init__(self)
- self.msg = msg
-
- def __str__(self):
- return (_("Gramps has detected a problem in opening the 'environment' "
- "of the underlying Berkeley database used to store this "
- "Family Tree. The most likely cause "
- "is that the database was created with an old version "
- "of the Berkeley database program, "
- "and you are now using a new version. "
- "It is quite likely that your database has not been "
- "changed by Gramps.\nIf possible, you should revert to your "
- "old version of Gramps and its support software; export "
- "your database to XML; close the database; "
- "then upgrade again "
- "to this version of Gramps and import the XML file "
- "in an empty Family Tree. Alternatively, it may be possible "
- "to use the Berkeley database recovery tools.")
- + '\n\n' + str(self.msg))
class DbUpgradeRequiredError(Exception):
"""
@@ -275,73 +160,6 @@ class DbUpgradeRequiredError(Exception):
'oldschema' : self.oldschema,
'newschema' : self.newschema }
-class PythonDowngradeError(Exception):
- """
- Error used to report that the Python version used to create the family tree
- (i.e. Python3) is a version that is newer than the current version
- (i.e. Python2), so the Family Tree cannot be opened
- """
- def __init__(self, db_python_version, current_python_version):
- Exception.__init__(self)
- self.db_python_version = str(db_python_version)
- self.current_python_version = str(current_python_version)
-
- def __str__(self):
- return _('The Family Tree you are trying to load was created with '
- 'Python version %(db_python_version)s. This version of Gramps '
- 'uses Python version %(current_python_version)s. So you are '
- 'trying to load '
- 'data created in a newer format into an older program, and '
- 'this is bound to fail.\n\n'
- 'You should start your '
- '%(bold_start)snewer%(bold_end)s version of Gramps and '
- '%(wiki_backup_html_start)smake a backup%(html_end)s '
- 'of your Family Tree. You can then import '
- 'this backup into this version of Gramps.') % {
- 'wiki_backup_html_start' : URL_BACKUP1_START ,
- 'html_end' : '' ,
- 'bold_start' : '' ,
- 'bold_end' : '' ,
- 'db_python_version': self.db_python_version,
- 'current_python_version': self.current_python_version }
-
-class PythonUpgradeRequiredError(Exception):
- """
- Error used to report that the Python version used to create the family tree
- (i.e. Python2) is earlier than the current Python version (i.e. Python3), so
- the Family Tree needs to be upgraded.
- """
- def __init__(self, db_python_version, current_python_version):
- Exception.__init__(self)
- self.db_python_version = str(db_python_version)
- self.current_python_version = str(current_python_version)
-
- def __str__(self):
- return _('The Family Tree you are trying to load is in the Python '
- 'version %(db_python_version)s format. This version of Gramps '
- 'uses Python version %(current_python_version)s. Therefore '
- 'you cannot load this Family Tree without upgrading the '
- 'Python version of the Family Tree.\n\n'
- 'If you upgrade then you won\'t be able to use the previous '
- 'version of Gramps, even if you subsequently '
- '%(wiki_manual_backup_html_start)sbackup%(html_end)s or '
- '%(wiki_manual_export_html_start)sexport%(html_end)s '
- 'your upgraded Family Tree.\n\n'
- 'Upgrading is a difficult task which could irretrievably '
- 'corrupt your Family Tree if it is interrupted or fails.\n\n'
- 'If you have not already made a backup of your Family Tree, '
- 'then you should start your %(bold_start)sold%(bold_end)s '
- 'version of Gramps and '
- '%(wiki_backup_html_start)smake a backup%(html_end)s '
- 'of your Family Tree.') % {
- 'wiki_backup_html_start' : URL_BACKUP1_START ,
- 'wiki_manual_backup_html_start' : URL_BACKUP2_START ,
- 'wiki_manual_export_html_start' : URL_EXPORT_START ,
- 'html_end' : '' ,
- 'bold_start' : '' ,
- 'bold_end' : '' ,
- 'db_python_version': self.db_python_version,
- 'current_python_version': self.current_python_version }
class DbConnectionError(Exception):
"""
@@ -360,6 +178,35 @@ class DbConnectionError(Exception):
'message': self.msg,
'settings_file': self.settings_file}
+
+class DbSupportedError(Exception):
+ """
+ Error used to report that a database is no longer supported.
+ """
+ def __init__(self, msg):
+ Exception.__init__(self)
+ self.msg = msg
+
+ def __str__(self):
+ return _('The Family Tree you are trying to load is in the %(dbtype)s '
+ 'database, which is no longer supported.\nTherefore you '
+ 'cannot load this Family Tree without upgrading.\n\n'
+ 'If you upgrade then you won\'t be able to use the previous '
+ 'version of Gramps, even if you subsequently '
+ '%(wiki_manual_backup_html_start)sbackup%(html_end)s or '
+ '%(wiki_manual_export_html_start)sexport%(html_end)s '
+ 'your upgraded Family Tree.\n\n'
+ 'You are strongly advised to backup your Family Tree.\n\n'
+ 'If you have not already made a backup of your Family Tree, '
+ 'then you should start your previous version of Gramps and '
+ '%(wiki_backup_html_start)smake a backup%(html_end)s '
+ 'of your Family Tree.') % {
+ 'dbtype' : self.msg,
+ 'wiki_manual_backup_html_start' : URL_BACKUP2_START ,
+ 'wiki_manual_export_html_start' : URL_EXPORT_START ,
+ 'wiki_backup_html_start' : URL_BACKUP1_START ,
+ 'html_end' : ''}
+
if __name__ == "__main__":
"""
Call this from the CLI (in order to find the imported modules):
@@ -370,20 +217,8 @@ if __name__ == "__main__":
print("\nDbVersionError:\n",
DbVersionError('1.6.0', '1.5.0', '1.5.1'))
- print("\nBsddbDowngradeError:\n",
- BsddbDowngradeError('4.8.30', '4.8.29'))
- print("\nBsddbDowngradeRequiredError:\n",
- BsddbDowngradeRequiredError('4.8.30', '4.8.29'))
- print("\nBsddbUpgradeRequiredError:\n",
- BsddbUpgradeRequiredError('4.8.29', '4.8.30'))
- print("\nDbEnvironmentError:\n",
- DbEnvironmentError('test message'))
print("\nDbUpgradeRequiredError:\n",
DbUpgradeRequiredError('1.5.1', '1.6.0'))
- print("\nPythonDowngradeError:\n",
- PythonDowngradeError('3', '2'))
- print("\nPythonUpgradeRequiredError:\n",
- PythonUpgradeRequiredError('2', '3'))
sys.exit(0)
print("\nxxx:\n",
diff --git a/gramps/gen/db/generic.py b/gramps/gen/db/generic.py
index ba445c9d8..da6b0e97a 100644
--- a/gramps/gen/db/generic.py
+++ b/gramps/gen/db/generic.py
@@ -47,6 +47,7 @@ from . import (DbReadBase, DbWriteBase, DbUndo, DBLOGNAME, DBUNDOFN,
REPOSITORY_KEY, NOTE_KEY, TAG_KEY, TXNADD, TXNUPD, TXNDEL,
KEY_TO_NAME_MAP, DBMODE_R, DBMODE_W)
from .utils import write_lock_file, clear_lock_file
+from .exceptions import DbVersionError, DbUpgradeRequiredError
from ..errors import HandleError
from ..utils.callback import Callback
from ..updatecallback import UpdateCallback
@@ -311,7 +312,7 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
__callback_map = {}
- VERSION = (18, 0, 0)
+ VERSION = (20, 0, 0)
def __init__(self, directory=None):
DbReadBase.__init__(self)
@@ -659,6 +660,21 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
self.db_is_open = True
+ # Check on db version to see if we need upgrade or too new
+ dbversion = int(self._get_metadata('version', default='0'))
+ if dbversion > self.VERSION[0]:
+ self.close()
+ raise DbVersionError(dbversion, 18, self.VERSION[0])
+
+ if not self.readonly and dbversion < self.VERSION[0]:
+ LOG.debug("Schema upgrade required from %s to %s",
+ dbversion, self.VERSION[0])
+ if force_schema_upgrade:
+ self._gramps_upgrade(dbversion, directory, callback)
+ else:
+ self.close()
+ raise DbUpgradeRequiredError(dbversion, self.VERSION[0])
+
def _close(self):
"""
Close database backend.
@@ -2463,3 +2479,47 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
enclosed_by = placeref.ref
break
return enclosed_by
+
+ def _gramps_upgrade(self, version, directory, callback=None):
+ """
+ Here we do the calls for stepwise schema upgrades.
+ We assume that we need to rebuild secondary and reference maps.
+ """
+ UpdateCallback.__init__(self, callback)
+
+ start = time.time()
+
+ from gramps.gen.db.upgrade import (
+ gramps_upgrade_14, gramps_upgrade_15, gramps_upgrade_16,
+ gramps_upgrade_17, gramps_upgrade_18, gramps_upgrade_19,
+ gramps_upgrade_20)
+
+ if version < 14:
+ gramps_upgrade_14(self)
+ if version < 15:
+ gramps_upgrade_15(self)
+ if version < 16:
+ gramps_upgrade_16(self)
+ if version < 17:
+ gramps_upgrade_17(self)
+ if version < 18:
+ gramps_upgrade_18(self)
+ if version < 19:
+ gramps_upgrade_19(self)
+ if version < 20:
+ gramps_upgrade_20(self)
+
+ self.rebuild_secondary()
+ self.reindex_reference_map(self.update)
+ self.reset()
+
+ self.set_schema_version(self.VERSION[0])
+ LOG.debug("Upgrade time: %d seconds" % int(time.time() - start))
+
+ def get_schema_version(self):
+ """ Return current schema version as an int """
+ return int(self._get_metadata('version', default='0'))
+
+ def set_schema_version(self, value):
+ """ set the current schema version """
+ self._set_metadata('version', str(value))
diff --git a/gramps/plugins/db/bsddb/upgrade.py b/gramps/gen/db/upgrade.py
similarity index 60%
rename from gramps/plugins/db/bsddb/upgrade.py
rename to gramps/gen/db/upgrade.py
index 48fd189dd..24464e5b9 100644
--- a/gramps/plugins/db/bsddb/upgrade.py
+++ b/gramps/gen/db/upgrade.py
@@ -1,8 +1,8 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
-# Copyright (C) 2004-2006 Donald N. Allingham
-# Copyright (C) 2011 Tim G L Lyons
+# Copyright (C) 2020-2016 Gramps Development Team
+# Copyright (C) 2020 Paul Culley
#
# 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
@@ -18,89 +18,72 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
-
-"""
-methods to upgrade a database from version 13 to current version
-"""
-
-#-------------------------------------------------------------------------
+""" Generic upgrade module for dbapi dbs """
+#------------------------------------------------------------------------
#
-# Standard python modules
+# Python Modules
#
-#-------------------------------------------------------------------------
+#------------------------------------------------------------------------
import os
import re
import time
import logging
-from bsddb3 import db
-
-#-------------------------------------------------------------------------
+#------------------------------------------------------------------------
#
-# Gramps modules
+# Gramps Modules
#
-#-------------------------------------------------------------------------
-from gramps.gen.const import GRAMPS_LOCALE as glocale
-_ = glocale.translation.gettext
-from gramps.gen.lib.markertype import MarkerType
-from gramps.gen.lib.nameorigintype import NameOriginType
-from gramps.gen.lib.eventtype import EventType
-from gramps.gen.lib.tag import Tag
+#------------------------------------------------------------------------
+from gramps.cli.clidbman import NAME_FILE
+from gramps.gen.lib import EventType, NameOriginType, Tag, MarkerType
from gramps.gen.utils.file import create_checksum
from gramps.gen.utils.id import create_id
-from . import BSDDBTxn
-from .write import _mkname, SURNAMES
-from gramps.gen.db.dbconst import (PERSON_KEY, FAMILY_KEY, EVENT_KEY,
- MEDIA_KEY, PLACE_KEY, REPOSITORY_KEY,
- SOURCE_KEY)
from gramps.gui.dialog import (InfoDialog)
+from .dbconst import (PERSON_KEY, FAMILY_KEY, EVENT_KEY, MEDIA_KEY, PLACE_KEY,
+ REPOSITORY_KEY, CITATION_KEY, SOURCE_KEY, NOTE_KEY,
+ TAG_KEY)
+from ..const import GRAMPS_LOCALE as glocale
+_ = glocale.translation.gettext
LOG = logging.getLogger(".upgrade")
-def gramps_upgrade_pickle(self):
- """
- Upgrade to python3 pickle protocol.
- """
- import pickle
- tables = (self.person_map, self.event_map, self.family_map, self.place_map,
- self.repository_map, self.source_map, self.citation_map,
- self.media_map, self.note_map, self.tag_map, self.metadata,
- self.reference_map)
- self.set_total(sum(map(len, tables)))
- for data_map in tables:
- for handle in data_map.keys():
- raw = data_map.db.get(handle)
- data = pickle.loads(raw, encoding='utf-8')
- with BSDDBTxn(self.env, data_map) as txn:
- txn.put(handle, data)
- self.update()
- with BSDDBTxn(self.env, self.metadata) as txn:
- txn.put(b'upgraded', 'Yes')
+def gramps_upgrade_20(self):
+ """
+ Placeholder update.
+ """
+ length = 0
+ self.set_total(length)
+ self._txn_begin()
+
+ # uid and place upgrade code goes here
+
+ self._txn_commit()
+ # Bump up database version. Separate transaction to save metadata.
+ self._set_metadata('version', 20)
+
def gramps_upgrade_19(self):
"""
Upgrade database from version 18 to 19.
"""
- default_handle = self.metadata.get(b'default')
- with BSDDBTxn(self.env, self.metadata) as txn:
- if isinstance(default_handle, bytes):
- default_handle = default_handle.decode('utf-8')
- txn.put(b'default', default_handle)
- txn.put(b'version', 19)
+ # This is done in the conversion from bsddb, so just say we did it.
+ self._set_metadata('version', 19)
+
def gramps_upgrade_18(self):
"""
Upgrade database from version 17 to 18.
"""
- length = len(self.place_map)
+ length = self.get_number_of_places()
self.set_total(length)
+ self._txn_begin()
# ---------------------------------
# Modify Place
# ---------------------------------
# Convert name fields to use PlaceName.
- for handle in self.place_map.keys():
- place = self.place_map[handle]
+ for handle in self.get_place_handles():
+ place = self.get_raw_place_data(handle)
new_place = list(place)
new_place[6] = (new_place[6], None, '')
alt_names = []
@@ -108,15 +91,13 @@ def gramps_upgrade_18(self):
alt_names.append((name, None, ''))
new_place[7] = alt_names
new_place = tuple(new_place)
- with BSDDBTxn(self.env, self.place_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_place)
+ self._commit_raw(new_place, PLACE_KEY)
self.update()
+ self._txn_commit()
# Bump up database version. Separate transaction to save metadata.
- with BSDDBTxn(self.env, self.metadata) as txn:
- txn.put(b'version', 18)
+ self._set_metadata('version', 18)
+
def gramps_upgrade_17(self):
"""
@@ -129,18 +110,19 @@ def gramps_upgrade_17(self):
4. Add checksum field to media objects.
5. Rebuild list of custom events.
"""
- length = (len(self.event_map) + len(self.place_map) +
- len(self.repository_map) + len(self.source_map) +
- len(self.citation_map) + len(self.media_map))
+ length = (self.get_number_of_events() + self.get_number_of_places() +
+ self.get_number_of_citations() + self.get_number_of_sources() +
+ self.get_number_of_repositories() + self.get_number_of_media())
self.set_total(length)
+ self._txn_begin()
# ---------------------------------
# Modify Event
# ---------------------------------
# Add new tag_list field.
self.event_names = set()
- for handle in self.event_map.keys():
- event = self.event_map[handle]
+ for handle in self.get_event_handles():
+ event = self.get_raw_event_data(handle)
new_event = list(event)
event_type = EventType()
event_type.unserialize(new_event[2])
@@ -148,10 +130,7 @@ def gramps_upgrade_17(self):
self.event_names.add(str(event_type))
new_event = new_event[:11] + [[]] + new_event[11:]
new_event = tuple(new_event)
- with BSDDBTxn(self.env, self.event_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_event)
+ self._commit_raw(new_event, EVENT_KEY)
self.update()
# ---------------------------------
@@ -161,8 +140,8 @@ def gramps_upgrade_17(self):
locations = {}
self.max_id = 0
index = re.compile('[0-9]+')
- for handle in self.place_map.keys():
- place = self.place_map[handle]
+ for handle in self.get_place_handles():
+ place = self.get_raw_place_data(handle)
match = index.search(place[1])
if match:
if self.max_id <= int(match.group(0)):
@@ -170,8 +149,8 @@ def gramps_upgrade_17(self):
if place[5] is not None:
locations[get_location(place[5])] = handle
- for handle in list(self.place_map.keys()):
- place = self.place_map[handle]
+ for handle in list(self.get_place_handles()):
+ place = self.get_raw_place_data(handle)
new_place = list(place)
zip_code = ''
@@ -203,7 +182,8 @@ def gramps_upgrade_17(self):
if loc[n]:
# TODO for Arabic, should the next line's comma be translated?
title = ', '.join([item for item in loc[n:] if item])
- parent_handle = add_place(self, loc[n], n, parent_handle, title)
+ parent_handle = add_place(
+ self, loc[n], n, parent_handle, title)
locations[tuple([''] * n + loc[n:])] = parent_handle
n -= 1
@@ -217,102 +197,85 @@ def gramps_upgrade_17(self):
else:
name = new_place[2]
type_num = -1
- new_place = new_place[:5] + [placeref_list, name, [],
- (type_num, ''), zip_code] + \
- new_place[6:12] + [[]] + new_place[12:]
+ new_place = (new_place[:5] + [
+ placeref_list, name, [], (type_num, ''), zip_code] +
+ new_place[6:12] + [[]] + new_place[12:])
new_place = tuple(new_place)
- with BSDDBTxn(self.env, self.place_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_place)
+ self._commit_raw(new_place, PLACE_KEY)
self.update()
# ---------------------------------
# Modify Repository
# ---------------------------------
# Add new tag_list field.
- for handle in self.repository_map.keys():
- repository = self.repository_map[handle]
+ for handle in self.get_repository_handles():
+ repository = self.get_raw_repository_data(handle)
new_repository = list(repository)
new_repository = new_repository[:8] + [[]] + new_repository[8:]
new_repository = tuple(new_repository)
- with BSDDBTxn(self.env, self.repository_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_repository)
+ self._commit_raw(new_repository, REPOSITORY_KEY)
self.update()
# ---------------------------------
# Modify Source
# ---------------------------------
# Add new tag_list field.
- for handle in self.source_map.keys():
- source = self.source_map[handle]
+ for handle in self.get_source_handles():
+ source = self.get_raw_source_data(handle)
new_source = list(source)
new_source = new_source[:11] + [[]] + new_source[11:]
new_source = tuple(new_source)
- with BSDDBTxn(self.env, self.source_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_source)
+ self._commit_raw(new_source, SOURCE_KEY)
self.update()
# ---------------------------------
# Modify Citation
# ---------------------------------
# Add new tag_list field.
- for handle in self.citation_map.keys():
- citation = self.citation_map[handle]
+ for handle in self.get_citation_handles():
+ citation = self.get_raw_citation_data(handle)
new_citation = list(citation)
new_citation = new_citation[:10] + [[]] + new_citation[10:]
new_citation = tuple(new_citation)
- with BSDDBTxn(self.env, self.citation_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_citation)
+ self._commit_raw(new_citation, CITATION_KEY)
self.update()
# -------------------------------------------------------
# Upgrade Source and Citation datamap to SrcAttributeBase
# -------------------------------------------------------
- for handle in self.source_map.keys():
- source = self.source_map[handle]
+ for handle in self.get_source_handles():
+ source = self.get_raw_source_data(handle)
(handle, gramps_id, title, author, pubinfo,
notelist, medialist, abbrev, change, datamap, reporef_list,
taglist, private) = source
srcattributelist = upgrade_datamap_17(datamap)
new_source = (handle, gramps_id, title, author, pubinfo,
- notelist, medialist, abbrev, change, srcattributelist, reporef_list,
- taglist, private)
- with BSDDBTxn(self.env, self.source_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_source)
+ notelist, medialist, abbrev, change, srcattributelist,
+ reporef_list, taglist, private)
+ self._commit_raw(new_source, SOURCE_KEY)
self.update()
- for handle in self.citation_map.keys():
- citation = self.citation_map[handle]
+ for handle in self.get_citation_handles():
+ citation = self.get_raw_citation_data(handle)
(handle, gramps_id, datelist, page, confidence, source_handle,
notelist, medialist, datamap, change, taglist, private) = citation
srcattributelist = upgrade_datamap_17(datamap)
- new_citation = (handle, gramps_id, datelist, page, confidence, source_handle,
- notelist, medialist, srcattributelist, change, taglist, private)
- with BSDDBTxn(self.env, self.citation_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_citation)
+ new_citation = (handle, gramps_id, datelist, page, confidence,
+ source_handle, notelist, medialist, srcattributelist,
+ change, taglist, private)
+ self._commit_raw(new_citation, CITATION_KEY)
self.update()
# ---------------------------------
# Modify Media
# ---------------------------------
# Add new checksum field.
- base_path = self.metadata.get(b'mediapath')
- if base_path is None:
+ base_path = self._get_metadata('media-path')
+ if not base_path:
# Check that the mediapath is not set to None (bug #7844).
base_path = ''
- for handle in self.media_map.keys():
- media = self.media_map[handle]
+ for handle in self.get_media_handles():
+ media = self.get_raw_media_data(handle)
new_media = list(media)
if os.path.isabs(new_media[2]):
full_path = new_media[2]
@@ -321,15 +284,13 @@ def gramps_upgrade_17(self):
checksum = create_checksum(full_path)
new_media = new_media[:5] + [checksum] + new_media[5:]
new_media = tuple(new_media)
- with BSDDBTxn(self.env, self.media_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_media)
+ self._commit_raw(new_media, MEDIA_KEY)
self.update()
+ self._txn_commit()
# Bump up database version. Separate transaction to save metadata.
- with BSDDBTxn(self.env, self.metadata) as txn:
- txn.put(b'version', 17)
+ self._set_metadata('version', 17)
+
def get_location(loc):
# (street, locality, parish, city, county, state, country)
@@ -339,27 +300,26 @@ def get_location(loc):
location = loc[0][:2] + (loc[1],) + loc[0][2:6]
return location
+
def add_place(self, name, level, parent, title):
handle = create_id()
self.max_id += 1
gid = self.place_prefix % self.max_id
- placetype = (7-level, '')
+ placetype = (7 - level, '')
if parent is not None:
placeref_list = [(parent.decode('utf-8'), None)]
else:
placeref_list = []
place = (handle, gid, title, '', '', placeref_list, name, [], placetype,
'', [], [], [], [], [], 0, [], False)
- with BSDDBTxn(self.env, self.place_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, place)
+ self._commit_raw(place, PLACE_KEY)
return handle
+
def upgrade_datamap_17(datamap):
"""
- In version 16 key value pairs are stored in source and citation. These become
- SrcAttribute
+ In version 16 key value pairs are stored in source and citation.
+ These become SrcAttribute
"""
new_srcattr_list = []
private = False
@@ -369,6 +329,7 @@ def upgrade_datamap_17(datamap):
new_srcattr_list.append((private, the_type, value))
return new_srcattr_list
+
def gramps_upgrade_16(self):
"""
Upgrade database from version 15 to 16. This upgrade converts all
@@ -388,33 +349,41 @@ def gramps_upgrade_16(self):
# Only People, Families, Events, Media Objects, Places, Sources and
# Repositories need to be updated, because these are the only primary
# objects that can have source citations.
- length = (len(self.person_map) +
- len(self.event_map) + len(self.family_map) +
- len(self.repository_map) + len(self.media_map) +
- len(self.place_map) + len(self.source_map))
+ length = (self.get_number_of_people() +
+ self.get_number_of_events() + self.get_number_of_families() +
+ self.get_number_of_repositories() + self.get_number_of_media() +
+ self.get_number_of_places() + self.get_number_of_sources())
self.set_total(length)
+ self._txn_begin()
# Setup data for upgrade statistics information dialogue
keyorder = [PERSON_KEY, FAMILY_KEY, EVENT_KEY, MEDIA_KEY,
PLACE_KEY, REPOSITORY_KEY, SOURCE_KEY]
key2data = {
- PERSON_KEY : 0,
- FAMILY_KEY : 1,
- EVENT_KEY: 2,
- MEDIA_KEY: 3,
- PLACE_KEY: 4,
- REPOSITORY_KEY: 5,
- SOURCE_KEY : 6,
- }
+ PERSON_KEY : 0,
+ FAMILY_KEY : 1,
+ EVENT_KEY: 2,
+ MEDIA_KEY: 3,
+ PLACE_KEY: 4,
+ REPOSITORY_KEY: 5,
+ SOURCE_KEY : 6,
+ }
key2string = {
- PERSON_KEY : _('%(n1)6d People upgraded with %(n2)6d citations in %(n3)6d secs\n'),
- FAMILY_KEY : _('%(n1)6d Families upgraded with %(n2)6d citations in %(n3)6d secs\n'),
- EVENT_KEY : _('%(n1)6d Events upgraded with %(n2)6d citations in %(n3)6d secs\n'),
- MEDIA_KEY : _('%(n1)6d Media Objects upgraded with %(n2)6d citations in %(n3)6d secs\n'),
- PLACE_KEY : _('%(n1)6d Places upgraded with %(n2)6d citations in %(n3)6d secs\n'),
- REPOSITORY_KEY : _('%(n1)6d Repositories upgraded with %(n2)6d citations in %(n3)6d secs\n'),
- SOURCE_KEY : _('%(n1)6d Sources upgraded with %(n2)6d citations in %(n3)6d secs\n'),
- }
+ PERSON_KEY : _('%(n1)6d People upgraded with '
+ '%(n2)6d citations in %(n3)6d secs\n'),
+ FAMILY_KEY : _('%(n1)6d Families upgraded with '
+ '%(n2)6d citations in %(n3)6d secs\n'),
+ EVENT_KEY : _('%(n1)6d Events upgraded with '
+ '%(n2)6d citations in %(n3)6d secs\n'),
+ MEDIA_KEY : _('%(n1)6d Media Objects upgraded with '
+ '%(n2)6d citations in %(n3)6d secs\n'),
+ PLACE_KEY : _('%(n1)6d Places upgraded with '
+ '%(n2)6d citations in %(n3)6d secs\n'),
+ REPOSITORY_KEY : _('%(n1)6d Repositories upgraded with '
+ '%(n2)6d citations in %(n3)6d secs\n'),
+ SOURCE_KEY : _('%(n1)6d Sources upgraded with '
+ '%(n2)6d citations in %(n3)6d secs\n'),
+ }
data_upgradeobject = [0] * 7
# Initialise the citation gramps ID number
@@ -425,12 +394,12 @@ def gramps_upgrade_16(self):
# ---------------------------------
start_num_citations = self.cmap_index
start_time = time.time()
- for person_handle in self.person_map.keys():
- person = self.person_map[person_handle]
+ for person_handle in self.get_person_handles():
+ person = self.get_raw_person_data(person_handle)
try:
- # The parameters are evaluated before deciding whether logging is on
- # or not. Since the retrieval of names is so complex, I think it is
- # safer to protect this with a try except block, even though it
+ # The parameters are evaluated before deciding whether logging is
+ # on or not. Since the retrieval of names is so complex, I think it
+ # is safer to protect this with a try except block, even though it
# seems to work for names being present and not.
LOG.debug("upgrade person %s %s" % (person[3][4],
" ".join([name[0] for name in person[3][5]])))
@@ -444,33 +413,27 @@ def gramps_upgrade_16(self):
if primary_name:
primary_name = upgrade_name_16(self, primary_name)
if alternate_names:
- alternate_names = upgrade_name_list_16(
- self, alternate_names)
+ alternate_names = upgrade_name_list_16(self, alternate_names)
if address_list:
- address_list = upgrade_address_list_16(
- self, address_list)
+ address_list = upgrade_address_list_16(self, address_list)
if media_list:
- media_list = upgrade_media_list_16(
- self, media_list)
+ media_list = upgrade_media_list_16(self, media_list)
if attribute_list:
- attribute_list = upgrade_attribute_list_16(
- self, attribute_list)
+ attribute_list = upgrade_attribute_list_16(self, attribute_list)
if lds_seal_list:
- lds_seal_list = upgrade_lds_seal_list_16(
- self, lds_seal_list)
+ lds_seal_list = upgrade_lds_seal_list_16(self, lds_seal_list)
if source_list:
new_citation_list = convert_source_list_to_citation_list_16(
- self, source_list)
+ self, source_list)
else:
new_citation_list = []
if person_ref_list:
- person_ref_list = upgrade_person_ref_list_16(
- self, person_ref_list)
+ person_ref_list = upgrade_person_ref_list_16(self, person_ref_list)
if event_ref_list:
event_ref_list = upgrade_event_ref_list_16(self, event_ref_list)
- if primary_name or alternate_names or address_list or \
- media_list or attribute_list or lds_seal_list or source_list or \
- person_ref_list or event_ref_list:
+ if(primary_name or alternate_names or address_list or media_list or
+ attribute_list or lds_seal_list or source_list or
+ person_ref_list or event_ref_list):
new_person = (handle, gramps_id, gender, primary_name,
alternate_names, death_ref_index,
birth_ref_index, event_ref_list, family_list,
@@ -479,100 +442,89 @@ def gramps_upgrade_16(self):
new_citation_list, note_list, change, tag_list,
private, person_ref_list)
LOG.debug(" upgrade new_person %s" % [new_person])
- with BSDDBTxn(self.env, self.person_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_person)
+ self._commit_raw(new_person, PERSON_KEY)
self.update()
LOG.debug("%d persons upgraded with %d citations in %d seconds. " %
- (len(list(self.person_map.keys())),
+ (self.get_number_of_people(),
self.cmap_index - start_num_citations,
time.time() - start_time))
- data_upgradeobject[key2data[PERSON_KEY]] = (len(list(self.person_map.keys())),
- self.cmap_index - start_num_citations,
- time.time() - start_time)
+ data_upgradeobject[key2data[PERSON_KEY]] = (
+ self.get_number_of_people(), self.cmap_index - start_num_citations,
+ time.time() - start_time)
# ---------------------------------
# Modify Media
# ---------------------------------
start_num_citations = self.cmap_index
start_time = time.time()
- for media_handle in self.media_map.keys():
- media = self.media_map[media_handle]
+ for media_handle in self.get_media_handles():
+ media = self.get_raw_media_data(media_handle)
LOG.debug("upgrade media object %s" % media[4])
(handle, gramps_id, path, mime, desc,
attribute_list, source_list, note_list, change,
date, tag_list, private) = media
new_citation_list = convert_source_list_to_citation_list_16(
- self, source_list)
- new_attribute_list = upgrade_attribute_list_16(
- self, attribute_list)
+ self, source_list)
+ new_attribute_list = upgrade_attribute_list_16(self, attribute_list)
new_media = (handle, gramps_id, path, mime, desc,
new_attribute_list, new_citation_list, note_list,
change, date, tag_list, private)
LOG.debug(" upgrade new_media %s" % [new_media])
- with BSDDBTxn(self.env, self.media_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_media)
+ self._commit_raw(new_media, MEDIA_KEY)
self.update()
LOG.debug("%d media objects upgraded with %d citations in %d seconds" %
- (len(self.media_map.keys()),
+ (self.get_number_of_media(),
self.cmap_index - start_num_citations,
int(time.time() - start_time)))
- data_upgradeobject[key2data[MEDIA_KEY]] = (len(list(self.media_map.keys())),
- self.cmap_index - start_num_citations,
- time.time() - start_time)
+ data_upgradeobject[key2data[MEDIA_KEY]] = (
+ self.get_number_of_media(), self.cmap_index - start_num_citations,
+ time.time() - start_time)
# ---------------------------------
# Modify Places
# ---------------------------------
start_num_citations = self.cmap_index
start_time = time.time()
- for place_handle in self.place_map.keys():
- place = self.place_map[place_handle]
+ for place_handle in self.get_place_handles():
+ place = self.get_raw_place_data(place_handle)
LOG.debug("upgrade place %s" % place[2])
(handle, gramps_id, title, longi, lat,
main_loc, alt_loc, urls, media_list, source_list, note_list,
change, private) = place
if source_list:
new_citation_list = convert_source_list_to_citation_list_16(
- self, source_list)
+ self, source_list)
else:
new_citation_list = []
if media_list:
- media_list = upgrade_media_list_16(
- self, media_list)
+ media_list = upgrade_media_list_16(self, media_list)
if source_list or media_list:
new_place = (handle, gramps_id, title,
longi, lat, main_loc, alt_loc, urls,
media_list, new_citation_list, note_list,
change, private)
LOG.debug(" upgrade new_place %s" % [new_place])
- with BSDDBTxn(self.env, self.place_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_place)
+ self._commit_raw(new_place, PLACE_KEY)
self.update()
LOG.debug("%d places upgraded with %d citations in %d seconds. " %
- (len(list(self.place_map.keys())),
+ (self.get_number_of_places(),
self.cmap_index - start_num_citations,
time.time() - start_time))
- data_upgradeobject[key2data[PLACE_KEY]] = (len(list(self.place_map.keys())),
- self.cmap_index - start_num_citations,
- time.time() - start_time)
+ data_upgradeobject[key2data[PLACE_KEY]] = (
+ self.get_number_of_places(), self.cmap_index - start_num_citations,
+ time.time() - start_time)
# ---------------------------------
# Modify Families
# ---------------------------------
start_num_citations = self.cmap_index
start_time = time.time()
- for family_handle in self.family_map.keys():
- family = self.family_map[family_handle]
+ for family_handle in self.get_family_handles():
+ family = self.get_raw_family_data(family_handle)
LOG.debug("upgrade family (gramps_id) %s" % family[1])
(handle, gramps_id, father_handle, mother_handle,
child_ref_list, the_type, event_ref_list, media_list,
@@ -580,166 +532,144 @@ def gramps_upgrade_16(self):
change, tag_list, private) = family
if source_list:
new_citation_list = convert_source_list_to_citation_list_16(
- self, source_list)
+ self, source_list)
else:
new_citation_list = []
if child_ref_list:
- child_ref_list = upgrade_child_ref_list_16(
- self, child_ref_list)
+ child_ref_list = upgrade_child_ref_list_16(self, child_ref_list)
if lds_seal_list:
- lds_seal_list = upgrade_lds_seal_list_16(
- self, lds_seal_list)
+ lds_seal_list = upgrade_lds_seal_list_16(self, lds_seal_list)
if media_list:
- media_list = upgrade_media_list_16(
- self, media_list)
+ media_list = upgrade_media_list_16(self, media_list)
if attribute_list:
- attribute_list = upgrade_attribute_list_16(
- self, attribute_list)
+ attribute_list = upgrade_attribute_list_16(self, attribute_list)
if event_ref_list:
event_ref_list = upgrade_event_ref_list_16(self, event_ref_list)
- if source_list or media_list or child_ref_list or \
- attribute_list or lds_seal_list or event_ref_list:
+ if(source_list or media_list or child_ref_list or
+ attribute_list or lds_seal_list or event_ref_list):
new_family = (handle, gramps_id, father_handle, mother_handle,
child_ref_list, the_type, event_ref_list, media_list,
attribute_list, lds_seal_list, new_citation_list,
note_list, change, tag_list, private)
LOG.debug(" upgrade new_family %s" % [new_family])
- with BSDDBTxn(self.env, self.family_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_family)
+ self._commit_raw(new_family, FAMILY_KEY)
self.update()
LOG.debug("%d families upgraded with %d citations in %d seconds. " %
- (len(list(self.family_map.keys())),
+ (self.get_number_of_families(),
self.cmap_index - start_num_citations,
time.time() - start_time))
- data_upgradeobject[key2data[FAMILY_KEY]] = (len(list(self.family_map.keys())),
- self.cmap_index - start_num_citations,
- time.time() - start_time)
+ data_upgradeobject[key2data[FAMILY_KEY]] = (
+ self.get_number_of_families(), self.cmap_index - start_num_citations,
+ time.time() - start_time)
# ---------------------------------
# Modify Events
# ---------------------------------
start_num_citations = self.cmap_index
start_time = time.time()
- for event_handle in self.event_map.keys():
- event = self.event_map[event_handle]
+ for event_handle in self.get_event_handles():
+ event = self.get_raw_event_data(event_handle)
LOG.debug("upgrade event %s" % event[4])
(handle, gramps_id, the_type, date, description, place,
source_list, note_list, media_list, attribute_list,
change, private) = event
if source_list:
new_citation_list = convert_source_list_to_citation_list_16(
- self, source_list)
+ self, source_list)
else:
new_citation_list = []
if attribute_list:
- attribute_list = upgrade_attribute_list_16(
- self, attribute_list)
+ attribute_list = upgrade_attribute_list_16(self, attribute_list)
if media_list:
- media_list = upgrade_media_list_16(
- self, media_list)
+ media_list = upgrade_media_list_16(self, media_list)
if source_list or attribute_list or media_list:
new_event = (handle, gramps_id, the_type, date, description, place,
new_citation_list, note_list, media_list,
attribute_list,
change, private)
LOG.debug(" upgrade new_event %s" % [new_event])
- with BSDDBTxn(self.env, self.event_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_event)
+ self._commit_raw(new_event, EVENT_KEY)
self.update()
LOG.debug("%d events upgraded with %d citations in %d seconds. " %
- (len(self.event_map.keys()),
+ (self.get_number_of_events(),
self.cmap_index - start_num_citations,
time.time() - start_time))
- data_upgradeobject[key2data[EVENT_KEY]] = (len(list(self.event_map.keys())),
- self.cmap_index - start_num_citations,
- time.time() - start_time)
+ data_upgradeobject[key2data[EVENT_KEY]] = (
+ self.get_number_of_events(), self.cmap_index - start_num_citations,
+ time.time() - start_time)
# ---------------------------------
# Modify Repositories
# ---------------------------------
start_num_citations = self.cmap_index
start_time = time.time()
- for repository_handle in self.repository_map.keys():
- repository = self.repository_map[repository_handle]
+ for repository_handle in self.get_repository_handles():
+ repository = self.get_raw_repository_data(repository_handle)
LOG.debug("upgrade repository %s" % repository[3])
(handle, gramps_id, the_type, name, note_list,
address_list, urls, change, private) = repository
if address_list:
- address_list = upgrade_address_list_16(
- self, address_list)
+ address_list = upgrade_address_list_16(self, address_list)
if address_list:
new_repository = (handle, gramps_id, the_type, name, note_list,
address_list, urls, change, private)
LOG.debug(" upgrade new_repository %s" % [new_repository])
- with BSDDBTxn(self.env, self.repository_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_repository)
+ self._commit_raw(new_repository, REPOSITORY_KEY)
self.update()
LOG.debug("%d repositories upgraded with %d citations in %d seconds. " %
- (len(list(self.repository_map.keys())),
+ (self.get_number_of_repositories(),
self.cmap_index - start_num_citations,
time.time() - start_time))
- data_upgradeobject[key2data[REPOSITORY_KEY]] = (len(list(self.repository_map.keys())),
- self.cmap_index - start_num_citations,
- time.time() - start_time)
+ data_upgradeobject[key2data[REPOSITORY_KEY]] = (
+ self.get_number_of_repositories(),
+ self.cmap_index - start_num_citations,
+ time.time() - start_time)
# ---------------------------------
# Modify Source
# ---------------------------------
start_num_citations = self.cmap_index
start_time = time.time()
- for source_handle in self.source_map.keys():
- source = self.source_map[source_handle]
+ for source_handle in self.get_source_handles():
+ source = self.get_raw_source_data(source_handle)
LOG.debug("upgrade source %s" % source[2])
(handle, gramps_id, title, author,
pubinfo, note_list, media_list,
abbrev, change, datamap, reporef_list,
private) = source
if media_list:
- media_list = upgrade_media_list_16(
- self, media_list)
+ media_list = upgrade_media_list_16(self, media_list)
new_source = (handle, gramps_id, title, author,
pubinfo, note_list, media_list,
abbrev, change, datamap, reporef_list,
private)
LOG.debug(" upgrade new_source %s" % [new_source])
- with BSDDBTxn(self.env, self.source_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_source)
+ self._commit_raw(new_source, SOURCE_KEY)
self.update()
LOG.debug("%d sources upgraded with %d citations in %d seconds" %
- (len(self.source_map.keys()),
+ (self.get_number_of_sources(),
self.cmap_index - start_num_citations,
int(time.time() - start_time)))
- data_upgradeobject[key2data[SOURCE_KEY]] = (len(self.source_map.keys()),
- self.cmap_index - start_num_citations,
- time.time() - start_time)
+ data_upgradeobject[key2data[SOURCE_KEY]] = (
+ self.get_number_of_sources(), self.cmap_index - start_num_citations,
+ time.time() - start_time)
- # ---------------------------------
+# ---------------------------------
+# Example database from repository took:
+# 3403 events upgraded with 8 citations in 23 seconds. Backlinks took 1071 secs
+# actually 4 of these citations were from:
+# Media upgrade 4 citations upgraded in 4 seconds
+# by only doing the backlinks when there might be something to do,
+# improved to:
+# 3403 events upgraded with 8 citations in 19 seconds. Backlinks took 1348 secs
+# further improved by skipping debug logging:
+# 3403 events upgraded with 8 citations in 2 seconds. Backlinks took 167 secs
-
- # ---------------------------------
- # Example database from repository took:
- # 3403 events upgraded with 8 citations in 23 seconds. Backlinks took 1071 seconds
- # actually 4 of these citations were from:
- # Media upgrade 4 citations upgraded in 4 seconds
- # by only doing the backlinks when there might be something to do,
- # improved to:
- # 3403 events upgraded with 8 citations in 19 seconds. Backlinks took 1348 seconds
- # further improved by skipping debug logging:
- # 3403 events upgraded with 8 citations in 2 seconds. Backlinks took 167 seconds
-
- #Number of new objects upgraded:
+#Number of new objects upgraded:
# 2090 People upgraded with 2092 citations in 2148 secs
# 734 Families upgraded with 735 citations in 768 secs
# 3403 Events upgraded with 4 citations in 212 secs
@@ -778,7 +708,7 @@ def gramps_upgrade_16(self):
# 7 Media Objects upgraded with 4 citations in 2 secs
# 852 Places upgraded with 0 citations in 1 secs
-# without incorrect nestetd tranaction structure:
+# without incorrect nested tranaction structure:
#Number of new objects upgraded:
# 73 People upgraded with 76 citations in 0 secs
# 35 Families upgraded with 36 citations in 0 secs
@@ -786,90 +716,89 @@ def gramps_upgrade_16(self):
# 7 Media Objects upgraded with 4 citations in 0 secs
# 852 Places upgraded with 0 citations in 0 secs
-#[[(73, 76, 0.12430405616760254), (35, 36, 0.042523860931396484), (3403, 4, 0.52303886413574219), (7, 4, 0.058229923248291016), (852, 0, 0.14816904067993164)]]
-
-
-
-
-
-
+ self._txn_commit()
# Bump up database version. Separate transaction to save metadata.
- with BSDDBTxn(self.env, self.metadata) as txn:
- txn.put(b'version', 16)
+ self._set_metadata('version', 16)
LOG.debug([data_upgradeobject])
txt = _("Number of new objects upgraded:\n")
for key in keyorder:
try:
txt += key2string[key] % {
- 'n1' : data_upgradeobject[key2data[key]][0],
- 'n2' : data_upgradeobject[key2data[key]][1],
- 'n3' : data_upgradeobject[key2data[key]][2] }
+ 'n1' : data_upgradeobject[key2data[key]][0],
+ 'n2' : data_upgradeobject[key2data[key]][1],
+ 'n3' : data_upgradeobject[key2data[key]][2]}
except:
txt += key2string[key]
txt += _("\n\nYou may want to run\n"
"Tools -> Family Tree Processing -> Merge\n"
"in order to merge citations that contain similar\n"
"information")
- InfoDialog(_('Upgrade Statistics'), txt, monospaced=True) # TODO no-parent
+ InfoDialog(_('Upgrade Statistics'), txt, monospaced=True) # TODO no-parent
+
def upgrade_media_list_16(self, media_list):
new_media_list = []
for media in media_list:
(privacy, source_list, note_list, attribute_list, ref, rect) = media
new_citation_list = convert_source_list_to_citation_list_16(
- self, source_list)
- new_attribute_list = upgrade_attribute_list_16(
- self, attribute_list)
+ self, source_list)
+ new_attribute_list = upgrade_attribute_list_16(self, attribute_list)
new_media = (privacy, new_citation_list, note_list, new_attribute_list,
ref, rect)
new_media_list.append((new_media))
return new_media_list
+
def upgrade_attribute_list_16(self, attribute_list):
new_attribute_list = []
for attribute in attribute_list:
(privacy, source_list, note_list, the_type,
value) = attribute
new_citation_list = convert_source_list_to_citation_list_16(
- self, source_list)
+ self, source_list)
new_attribute = (privacy, new_citation_list, note_list,
the_type, value)
new_attribute_list.append((new_attribute))
return new_attribute_list
+
def upgrade_child_ref_list_16(self, child_ref_list):
new_child_ref_list = []
for child_ref in child_ref_list:
(privacy, source_list, note_list, ref, frel, mrel) = child_ref
new_citation_list = convert_source_list_to_citation_list_16(
- self, source_list)
- new_child_ref = (privacy, new_citation_list, note_list, ref, frel, mrel)
+ self, source_list)
+ new_child_ref = (privacy, new_citation_list, note_list, ref,
+ frel, mrel)
new_child_ref_list.append((new_child_ref))
return new_child_ref_list
+
def upgrade_lds_seal_list_16(self, lds_seal_list):
new_lds_seal_list = []
for lds_seal in lds_seal_list:
- (source_list, note_list, date, type, place,
+ (source_list, note_list, date, type_, place,
famc, temple, status, private) = lds_seal
new_citation_list = convert_source_list_to_citation_list_16(
- self, source_list)
- new_lds_seal = (new_citation_list, note_list, date, type, place,
+ self, source_list)
+ new_lds_seal = (new_citation_list, note_list, date, type_, place,
famc, temple, status, private)
new_lds_seal_list.append((new_lds_seal))
return new_lds_seal_list
+
def upgrade_address_list_16(self, address_list):
new_address_list = []
for address in address_list:
(privacy, source_list, note_list, date, location) = address
new_citation_list = convert_source_list_to_citation_list_16(
- self, source_list)
+ self, source_list)
new_address = (privacy, new_citation_list, note_list, date, location)
new_address_list.append((new_address))
return new_address_list
+
def upgrade_name_list_16(self, name_list):
new_name_list = []
for name in name_list:
@@ -877,37 +806,40 @@ def upgrade_name_list_16(self, name_list):
new_name_list.append((new_name))
return new_name_list
+
def upgrade_name_16(self, name):
(privacy, source_list, note, date, first_name, surname_list, suffix,
title, name_type, group_as, sort_as, display_as, call, nick,
famnick) = name
new_citation_list = convert_source_list_to_citation_list_16(
- self, source_list)
+ self, source_list)
new_name = (privacy, new_citation_list, note, date, first_name,
surname_list, suffix, title, name_type, group_as, sort_as,
display_as, call, nick, famnick)
return new_name
+
def upgrade_person_ref_list_16(self, person_ref_list):
new_person_ref_list = []
for person_ref in person_ref_list:
(privacy, source_list, note_list, ref, rel) = person_ref
new_citation_list = convert_source_list_to_citation_list_16(
- self, source_list)
+ self, source_list)
new_person_ref = (privacy, new_citation_list, note_list, ref, rel)
new_person_ref_list.append((new_person_ref))
return new_person_ref_list
+
def upgrade_event_ref_list_16(self, event_ref_list):
new_event_ref_list = []
for event_ref in event_ref_list:
(privacy, note_list, attribute_list, ref, role) = event_ref
- new_attribute_list = upgrade_attribute_list_16(
- self, attribute_list)
+ new_attribute_list = upgrade_attribute_list_16(self, attribute_list)
new_event_ref = (privacy, note_list, new_attribute_list, ref, role)
new_event_ref_list.append((new_event_ref))
return new_event_ref_list
+
def convert_source_list_to_citation_list_16(self, source_list):
citation_list = []
for source in source_list:
@@ -921,13 +853,11 @@ def convert_source_list_to_citation_list_16(self, source_list):
date, page, confidence, ref, note_list, new_media_list,
new_data_map, new_change, private)
citation_list.append((new_handle))
- with BSDDBTxn(self.env, self.citation_map) as txn:
- if isinstance(new_handle, str):
- new_handle = new_handle.encode('utf-8')
- txn.put(new_handle, new_citation)
+ self._commit_raw(new_citation, CITATION_KEY)
self.cmap_index += 1
return citation_list
+
def gramps_upgrade_15(self):
"""
Upgrade database from version 14 to 15. This upgrade adds:
@@ -936,41 +866,42 @@ def gramps_upgrade_15(self):
* surname list
* remove marker
"""
- length = (len(self.note_map) + len(self.person_map) +
- len(self.event_map) + len(self.family_map) +
- len(self.repository_map) + len(self.media_map) +
- len(self.place_map) + len(self.source_map)) + 10
+ length = (self.get_number_of_notes() + self.get_number_of_people() +
+ self.get_number_of_events() + self.get_number_of_families() +
+ self.get_number_of_repositories() + self.get_number_of_media() +
+ self.get_number_of_places() + self.get_number_of_sources()) + 10
self.set_total(length)
+ self._txn_begin()
self.tags = {}
# ---------------------------------
# Modify Person
# ---------------------------------
# Replace the old marker field with the new tag list field.
- for handle in self.person_map.keys():
- person = self.person_map[handle]
+ for handle in self.get_person_handles():
+ person = self.get_raw_person_data(handle)
- (junk_handle, # 0
- gramps_id, # 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
- urls, # 13
- ord_list, # 14
- psource_list, # 15
- pnote_list, # 16
- change, # 17
- marker, # 18
- pprivate, # 19
- person_ref_list, # 20
+ (junk_handle, # 0
+ gramps_id, # 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
+ urls, # 13
+ ord_list, # 14
+ psource_list, # 15
+ pnote_list, # 16
+ change, # 17
+ marker, # 18
+ pprivate, # 19
+ person_ref_list, # 20
) = person
tag_handle = convert_marker(self, marker)
@@ -981,47 +912,38 @@ def gramps_upgrade_15(self):
address_list = list(map(convert_address, address_list))
new_primary_name = convert_name_15(primary_name)
new_alternate_names = list(map(convert_name_15, alternate_names))
- new_person = (junk_handle, # 0
- gramps_id, # 1
- gender, # 2
- new_primary_name, # 3
- new_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
- urls, # 13
- ord_list, # 14
- psource_list, # 15
- pnote_list, # 16
- change, # 17
- tags, # 18
- pprivate, # 19
- person_ref_list # 20
+ new_person = (junk_handle, # 0
+ gramps_id, # 1
+ gender, # 2
+ new_primary_name, # 3
+ new_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
+ urls, # 13
+ ord_list, # 14
+ psource_list, # 15
+ pnote_list, # 16
+ change, # 17
+ tags, # 18
+ pprivate, # 19
+ person_ref_list # 20
)
- with BSDDBTxn(self.env, self.person_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_person)
+ self._commit_raw(new_person, PERSON_KEY)
self.update()
- #surname is now different, remove secondary index with names
- _db = db.DB(self.env)
- try:
- _db.remove(_mkname(self.full_name, SURNAMES), SURNAMES)
- except db.DBNoSuchFileError:
- pass
# ---------------------------------
# Modify Family
# ---------------------------------
# Replace the old marker field with the new tag list field.
- for handle in self.family_map.keys():
- family = self.family_map[handle]
+ for handle in self.get_family_handles():
+ family = self.get_raw_family_data(handle)
new_family = list(family)
tag_handle = convert_marker(self, new_family[13])
if tag_handle:
@@ -1029,18 +951,15 @@ def gramps_upgrade_15(self):
else:
new_family[13] = []
new_family = tuple(new_family)
- with BSDDBTxn(self.env, self.family_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_family)
+ self._commit_raw(new_family, FAMILY_KEY)
self.update()
# ---------------------------------
# Modify Note
# ---------------------------------
# Replace the old marker field with the new tag list field.
- for handle in self.note_map.keys():
- note = self.note_map[handle]
+ for handle in self.get_note_handles():
+ note = self.get_raw_note_data(handle)
new_note = list(note)
tag_handle = convert_marker(self, new_note[6])
if tag_handle:
@@ -1048,95 +967,78 @@ def gramps_upgrade_15(self):
else:
new_note[6] = []
new_note = tuple(new_note)
- with BSDDBTxn(self.env, self.note_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_note)
+ self._commit_raw(new_note, NOTE_KEY)
self.update()
# ---------------------------------
# Modify Media object
# ---------------------------------
# Replace the old marker field with the new tag list field.
- for handle in self.media_map.keys():
- media = self.media_map[handle]
+ for handle in self.get_media_handles():
+ media = self.get_raw_media_data(handle)
new_media = list(media)
new_media[10] = []
new_media = tuple(new_media)
- with BSDDBTxn(self.env, self.media_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_media)
+ self._commit_raw(new_media, MEDIA_KEY)
self.update()
# ---------------------------------
# Modify Event
# ---------------------------------
# Replace the old marker field with the new tag list field.
- for handle in self.event_map.keys():
- event = self.event_map[handle]
+ for handle in self.get_event_handles():
+ event = self.get_raw_event_data(handle)
new_event = list(event)
new_event = new_event[:11] + new_event[12:]
#new_event[11] = []
new_event = tuple(new_event)
- with BSDDBTxn(self.env, self.event_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_event)
+ self._commit_raw(new_event, EVENT_KEY)
self.update()
# ---------------------------------
# Modify Place
# ---------------------------------
# Remove the old marker field, set new locality.
- for handle in self.place_map.keys():
- place = self.place_map[handle]
+ for handle in self.get_place_handles():
+ place = self.get_raw_place_data(handle)
new_place = list(place)
if new_place[5] is not None:
new_place[5] = convert_location(new_place[5])
new_place[6] = list(map(convert_location, new_place[6]))
new_place = new_place[:12] + new_place[13:]
new_place = tuple(new_place)
- with BSDDBTxn(self.env, self.place_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_place)
+ self._commit_raw(new_place, PLACE_KEY)
self.update()
# ---------------------------------
# Modify Source
# ---------------------------------
# Remove the old marker field.
- for handle in self.source_map.keys():
- source = self.source_map[handle]
+ for handle in self.get_source_handles():
+ source = self.get_raw_source_data(handle)
new_source = list(source)
new_source = new_source[:11] + new_source[12:]
new_source = tuple(new_source)
- with BSDDBTxn(self.env, self.source_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_source)
+ self._commit_raw(new_source, SOURCE_KEY)
self.update()
# ---------------------------------
# Modify Repository
# ---------------------------------
# Remove the old marker field, set new locality.
- for handle in self.repository_map.keys():
- repository = self.repository_map[handle]
+ for handle in self.get_repository_handles():
+ repository = self.get_raw_repository_data(handle)
new_repository = list(repository)
new_repository = new_repository[:8] + new_repository[9:]
new_repository[5] = list(map(convert_address, new_repository[5]))
new_repository = tuple(new_repository)
- with BSDDBTxn(self.env, self.repository_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_repository)
+ self._commit_raw(new_repository, REPOSITORY_KEY)
self.update()
+ self._txn_commit()
# Bump up database version. Separate transaction to save metadata.
- with BSDDBTxn(self.env, self.metadata) as txn:
- txn.put(b'version', 15)
+ self._set_metadata('version', 15)
+
def convert_marker(self, marker_field):
"""Convert a marker into a tag."""
@@ -1152,27 +1054,28 @@ def convert_marker(self, marker_field):
tag.set_change_time(time.time())
tag.set_name(tag_name)
tag.set_priority(len(self.tags))
- with BSDDBTxn(self.env, self.tag_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, tag.serialize())
+ self._commit_raw(tag.serialize(), TAG_KEY)
self.tags[tag_name] = handle
return self.tags[tag_name]
else:
return None
+
def convert_locbase(loc):
"""Convert location base to include an empty locality field."""
return tuple([loc[0], ''] + list(loc[1:]))
+
def convert_location(loc):
"""Convert a location into the new format."""
return (convert_locbase(loc[0]), loc[1])
+
def convert_address(addr):
"""Convert an address into the new format."""
return (addr[0], addr[1], addr[2], addr[3], convert_locbase(addr[4]))
+
def convert_name_15(name):
(privacy, source_list, note_list, date,
first_name, surname, suffix, title,
@@ -1189,7 +1092,8 @@ def convert_name_15(name):
else:
#a patronymic, if no surname or equal as patronymic, a single surname
if (surname.strip() == "") or (surname == patronymic and prefix == ""):
- surname_list = [(patronymic, prefix, True, patorigintype, connector)]
+ surname_list = [
+ (patronymic, prefix, True, patorigintype, connector)]
else:
#two surnames, first patronymic, then surname which is primary
surname_list = [(patronymic, "", False, patorigintype, ""),
@@ -1197,41 +1101,40 @@ def convert_name_15(name):
#return new value, add two empty strings for nick and family nick
return (privacy, source_list, note_list, date,
- first_name, surname_list, suffix, title, name_type,
- group_as, sort_as, display_as, call, "", "")
+ first_name, surname_list, suffix, title, name_type,
+ group_as, sort_as, display_as, call, "", "")
+
def gramps_upgrade_14(self):
"""Upgrade database from version 13 to 14."""
# This upgrade modifies notes and dates
- length = (len(self.note_map) + len(self.person_map) +
- len(self.event_map) + len(self.family_map) +
- len(self.repository_map) + len(self.media_map) +
- len(self.place_map) + len(self.source_map))
+ length = (self.get_number_of_notes() + self.get_number_of_people() +
+ self.get_number_of_events() + self.get_number_of_families() +
+ self.get_number_of_repositories() + self.get_number_of_media() +
+ self.get_number_of_places() + self.get_number_of_sources())
self.set_total(length)
+ self._txn_begin()
# ---------------------------------
# Modify Notes
# ---------------------------------
# replace clear text with StyledText in Notes
- for handle in self.note_map.keys():
- note = self.note_map[handle]
- (junk_handle, gramps_id, text, format, note_type,
+ for handle in self.get_note_handles():
+ note = self.get_raw_note_data(handle)
+ (junk_handle, gramps_id, text, format_, note_type,
change, marker, private) = note
styled_text = (text, [])
- new_note = (handle, gramps_id, styled_text, format, note_type,
+ new_note = (handle, gramps_id, styled_text, format_, note_type,
change, marker, private)
- with BSDDBTxn(self.env, self.note_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_note)
+ self._commit_raw(new_note, NOTE_KEY)
self.update()
# ---------------------------------
# Modify Event
# ---------------------------------
# update dates with newyear
- for handle in self.event_map.keys():
- event = self.event_map[handle]
+ for handle in self.get_event_handles():
+ event = self.get_raw_event_data(handle)
(junk_handle, gramps_id, the_type, date, description, place,
source_list, note_list, media_list, attribute_list,
change, marker, private) = event
@@ -1239,42 +1142,39 @@ def gramps_upgrade_14(self):
new_source_list = new_source_list_14(source_list)
new_media_list = new_media_list_14(media_list)
new_attribute_list = new_attribute_list_14(attribute_list)
- new_event = (junk_handle, gramps_id, the_type, new_date,
- description, place, new_source_list, note_list,
- new_media_list, new_attribute_list, change,marker,private)
- with BSDDBTxn(self.env, self.event_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_event)
+ new_event = (junk_handle, gramps_id, the_type, new_date, description,
+ place, new_source_list, note_list, new_media_list,
+ new_attribute_list, change, marker, private)
+ self._commit_raw(new_event, EVENT_KEY)
self.update()
# ---------------------------------
# Modify Person
# ---------------------------------
# update dates with newyear
- for handle in self.person_map.keys():
- person = self.person_map[handle]
- (junk_handle, # 0
- gramps_id, # 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
- urls, # 13
- lds_ord_list, # 14
- psource_list, # 15
- pnote_list, # 16
- change, # 17
- marker, # 18
- pprivate, # 19
- person_ref_list, # 20
+ for handle in self.get_person_handles():
+ person = self.get_raw_person_data(handle)
+ (junk_handle, # 0
+ gramps_id, # 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
+ urls, # 13
+ lds_ord_list, # 14
+ psource_list, # 15
+ pnote_list, # 16
+ change, # 17
+ marker, # 18
+ pprivate, # 19
+ person_ref_list, # 20
) = person
new_address_list = []
@@ -1286,12 +1186,12 @@ def gramps_upgrade_14(self):
new_date, location))
new_ord_list = []
for ldsord in lds_ord_list:
- (lsource_list, lnote_list, date, type, place,
+ (lsource_list, lnote_list, date, type_, place,
famc, temple, status, lprivate) = ldsord
new_date = convert_date_14(date)
new_lsource_list = new_source_list_14(lsource_list)
- new_ord_list.append( (new_lsource_list, lnote_list, new_date, type,
- place, famc, temple, status, lprivate))
+ new_ord_list.append((new_lsource_list, lnote_list, new_date, type_,
+ place, famc, temple, status, lprivate))
new_primary_name = convert_name_14(primary_name)
@@ -1303,41 +1203,38 @@ def gramps_upgrade_14(self):
new_attribute_list = new_attribute_list_14(attribute_list)
new_person_ref_list = new_person_ref_list_14(person_ref_list)
- new_person = (junk_handle, # 0
- gramps_id, # 1
- gender, # 2
- new_primary_name, # 3
- new_alternate_names, # 4
- death_ref_index, # 5
- birth_ref_index, # 6
- event_ref_list, # 7
- family_list, # 8
- parent_family_list, # 9
- new_media_list, # 10
- new_address_list, # 11
- new_attribute_list, # 12
- urls, # 13
- new_ord_list, # 14
- new_psource_list, # 15
- pnote_list, # 16
- change, # 17
- marker, # 18
- pprivate, # 19
- new_person_ref_list, # 20
+ new_person = (junk_handle, # 0
+ gramps_id, # 1
+ gender, # 2
+ new_primary_name, # 3
+ new_alternate_names, # 4
+ death_ref_index, # 5
+ birth_ref_index, # 6
+ event_ref_list, # 7
+ family_list, # 8
+ parent_family_list, # 9
+ new_media_list, # 10
+ new_address_list, # 11
+ new_attribute_list, # 12
+ urls, # 13
+ new_ord_list, # 14
+ new_psource_list, # 15
+ pnote_list, # 16
+ change, # 17
+ marker, # 18
+ pprivate, # 19
+ new_person_ref_list, # 20
)
- with BSDDBTxn(self.env, self.person_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_person)
+ self._commit_raw(new_person, PERSON_KEY)
self.update()
# ---------------------------------
# Modify Family
# ---------------------------------
# update dates with newyear
- for handle in self.family_map.keys():
- family = self.family_map[handle]
+ for handle in self.get_family_handles():
+ family = self.get_raw_family_data(handle)
(junk_handle, gramps_id, father_handle, mother_handle,
child_ref_list, the_type, event_ref_list, media_list,
attribute_list, lds_seal_list, source_list, note_list,
@@ -1348,30 +1245,28 @@ def gramps_upgrade_14(self):
new_attribute_list = new_attribute_list_14(attribute_list)
new_seal_list = []
for ldsord in lds_seal_list:
- (lsource_list, lnote_list, date, type, place,
+ (lsource_list, lnote_list, date, type_, place,
famc, temple, status, lprivate) = ldsord
new_date = convert_date_14(date)
new_lsource_list = new_source_list_14(lsource_list)
- new_seal_list.append( (new_lsource_list, lnote_list, new_date, type,
- place, famc, temple, status, lprivate))
+ new_seal_list.append((new_lsource_list, lnote_list, new_date,
+ type_, place, famc, temple, status,
+ lprivate))
new_family = (junk_handle, gramps_id, father_handle, mother_handle,
- new_child_ref_list, the_type, event_ref_list, new_media_list,
- new_attribute_list, new_seal_list, new_source_list, note_list,
- change, marker, private)
+ new_child_ref_list, the_type, event_ref_list,
+ new_media_list, new_attribute_list, new_seal_list,
+ new_source_list, note_list, change, marker, private)
- with BSDDBTxn(self.env, self.family_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_family)
+ self._commit_raw(new_family, FAMILY_KEY)
self.update()
# ---------------------------------
# Modify Repository
# ---------------------------------
# update dates with newyear
- for handle in self.repository_map.keys():
- repository = self.repository_map[handle]
+ for handle in self.get_repository_handles():
+ repository = self.get_raw_repository_data(handle)
# address
(junk_handle, gramps_id, the_type, name, note_list,
address_list, urls, change, marker, private) = repository
@@ -1387,17 +1282,14 @@ def gramps_upgrade_14(self):
new_repository = (junk_handle, gramps_id, the_type, name, note_list,
new_address_list, urls, change, marker, private)
- with BSDDBTxn(self.env, self.repository_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_repository)
+ self._commit_raw(new_repository, REPOSITORY_KEY)
self.update()
# ---------------------------------
# Modify Media
# ---------------------------------
- for media_handle in self.media_map.keys():
- media = self.media_map[media_handle]
+ for media_handle in self.get_media_handles():
+ media = self.get_raw_media_data(media_handle)
(handle, gramps_id, path, mime, desc,
attribute_list, source_list, note_list, change,
date, marker, private) = media
@@ -1407,17 +1299,14 @@ def gramps_upgrade_14(self):
attribute_list, new_source_list, note_list, change,
new_date, marker, private)
- with BSDDBTxn(self.env, self.media_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_media)
+ self._commit_raw(new_media, MEDIA_KEY)
self.update()
# ---------------------------------
# Modify Place
# ---------------------------------
- for place_handle in self.place_map.keys():
- place = self.place_map[place_handle]
+ for place_handle in self.get_place_handles():
+ place = self.get_raw_place_data(place_handle)
(handle, gramps_id, title, longi, lat,
main_loc, alt_loc, urls, media_list, source_list, note_list,
change, marker, private) = place
@@ -1427,17 +1316,14 @@ def gramps_upgrade_14(self):
main_loc, alt_loc, urls, new_media_list,
new_source_list, note_list, change, marker, private)
- with BSDDBTxn(self.env, self.place_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_place)
+ self._commit_raw(new_place, PLACE_KEY)
self.update()
# ---------------------------------
# Modify Source
# ---------------------------------
- for source_handle in self.source_map.keys():
- source = self.source_map[source_handle]
+ for source_handle in self.get_source_handles():
+ source = self.get_raw_source_data(source_handle)
(handle, gramps_id, title, author,
pubinfo, note_list, media_list,
abbrev, change, datamap, reporef_list,
@@ -1448,60 +1334,68 @@ def gramps_upgrade_14(self):
abbrev, change, datamap, reporef_list,
marker, private)
- with BSDDBTxn(self.env, self.source_map) as txn:
- if isinstance(handle, str):
- handle = handle.encode('utf-8')
- txn.put(handle, new_source)
+ self._commit_raw(new_source, SOURCE_KEY)
self.update()
+ self._txn_commit()
# Bump up database version. Separate transaction to save metadata.
- with BSDDBTxn(self.env, self.metadata) as txn:
- txn.put(b'version', 14)
+ self._set_metadata('version', 14)
+
def new_source_list_14(source_list):
new_source_list = []
for source in source_list:
(date, private, note_list, confidence, ref, page) = source
new_date = convert_date_14(date)
- new_source_list.append((new_date, private, note_list, confidence, ref, page))
+ new_source_list.append((new_date, private, note_list, confidence, ref,
+ page))
return new_source_list
+
def new_attribute_list_14(attribute_list):
new_attribute_list = []
for attribute in attribute_list:
(private, asource_list, note_list, the_type, value) = attribute
new_asource_list = new_source_list_14(asource_list)
- new_attribute_list.append((private, new_asource_list, note_list, the_type, value))
+ new_attribute_list.append((private, new_asource_list, note_list,
+ the_type, value))
return new_attribute_list
+
def new_media_list_14(media_list):
# ---------------------------------
# Event Media list
# ---------------------------------
new_media_list = []
for media in media_list:
- (private, source_list, note_list,attribute_list,ref,role) = media
+ (private, source_list, note_list, attribute_list, ref, role) = media
new_source_list = new_source_list_14(source_list)
new_attribute_list = new_attribute_list_14(attribute_list)
- new_media_list.append((private, new_source_list, note_list, new_attribute_list, ref, role))
+ new_media_list.append((private, new_source_list, note_list,
+ new_attribute_list, ref, role))
return new_media_list
+
def new_person_ref_list_14(person_ref_list):
new_person_ref_list = []
for person_ref in person_ref_list:
(private, source_list, note_list, ref, rel) = person_ref
new_source_list = new_source_list_14(source_list)
- new_person_ref_list.append((private, new_source_list, note_list, ref, rel))
+ new_person_ref_list.append((private, new_source_list, note_list, ref,
+ rel))
return new_person_ref_list
+
def new_child_ref_list_14(child_ref_list):
new_child_ref_list = []
for data in child_ref_list:
(private, source_list, note_list, ref, frel, mrel) = data
new_source_list = new_source_list_14(source_list)
- new_child_ref_list.append((private, new_source_list, note_list, ref, frel, mrel))
+ new_child_ref_list.append((private, new_source_list, note_list, ref,
+ frel, mrel))
return new_child_ref_list
+
def convert_date_14(date):
if date:
(calendar, modifier, quality, dateval, text, sortval) = date
@@ -1509,6 +1403,7 @@ def convert_date_14(date):
else:
return None
+
def convert_name_14(name):
(privacy, source_list, note_list, date,
first_name, surname, suffix, title,
@@ -1521,3 +1416,32 @@ def convert_name_14(name):
name_type, prefix, patronymic,
group_as, sort_as, display_as, call)
+
+def make_zip_backup(dirname):
+ """
+ This backs up the db files so an upgrade can be (manually) undone.
+ """
+ LOG.debug("Make backup prior to schema upgrade")
+ import zipfile
+ # In Windows reserved characters is "<>:"/\|?*"
+ reserved_char = r':,<>"/\|?* '
+ replace_char = "-__________"
+ filepath = os.path.join(dirname, NAME_FILE)
+ with open(filepath, "r", encoding='utf8') as name_file:
+ title = name_file.readline().strip()
+ trans = title.maketrans(reserved_char, replace_char)
+ title = title.translate(trans)
+
+ if not os.access(dirname, os.W_OK):
+ LOG.warning("Can't write technical DB backup for %s", title)
+ return
+ (grampsdb_path, db_code) = os.path.split(dirname)
+ dotgramps_path = os.path.dirname(grampsdb_path)
+ zipname = title + time.strftime("_%Y-%m-%d_%H-%M-%S") + ".zip"
+ zippath = os.path.join(dotgramps_path, zipname)
+ with zipfile.ZipFile(zippath, 'w') as myzip:
+ for filename in os.listdir(dirname):
+ pathname = os.path.join(dirname, filename)
+ myzip.write(pathname, os.path.join(db_code, filename))
+ LOG.warning("If upgrade and loading the Family Tree works, you can "
+ "delete the zip file at %s", zippath)
diff --git a/gramps/gui/dbloader.py b/gramps/gui/dbloader.py
index 3525cc38f..4f7f6e755 100644
--- a/gramps/gui/dbloader.py
+++ b/gramps/gui/dbloader.py
@@ -54,18 +54,14 @@ from gi.repository import GObject
from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.db.dbconst import DBBACKEND
from gramps.gen.db.utils import make_database
+from gramps.gen.db.upgrade import make_zip_backup
_ = glocale.translation.gettext
from gramps.cli.grampscli import CLIDbLoader
from gramps.gen.config import config
from gramps.gen.db.exceptions import (DbUpgradeRequiredError,
- BsddbDowngradeError,
DbVersionError,
DbPythonError,
- DbEnvironmentError,
- BsddbUpgradeRequiredError,
- BsddbDowngradeRequiredError,
- PythonUpgradeRequiredError,
- PythonDowngradeError,
+ DbSupportedError,
DbConnectionError)
from .pluginmanager import GuiPluginManager
from .dialog import (DBErrorDialog, ErrorDialog, QuestionDialog2,
@@ -163,130 +159,70 @@ class DbLoader(CLIDbLoader):
if not os.access(filename, os.W_OK):
mode = "r"
self._warn(_('Read only database'),
- _('You do not have write access '
- 'to the selected file.'))
+ _('You do not have write access '
+ 'to the selected file.'))
else:
mode = "w"
else:
mode = 'w'
- dbid_path = os.path.join(filename, DBBACKEND)
- if os.path.isfile(dbid_path):
- with open(dbid_path) as fp:
- dbid = fp.read().strip()
- else:
- dbid = "bsddb"
-
- db = make_database(dbid)
- db.disable_signals()
self.dbstate.no_database()
- if db.requires_login() and username is None:
- login = GrampsLoginDialog(self.uistate)
- credentials = login.run()
- if credentials is None:
- return
- username, password = credentials
-
- self._begin_progress()
+ self.uistate.progress.show()
+ self.uistate.pulse_progressbar(0)
force_schema_upgrade = False
- force_bsddb_upgrade = False
- force_bsddb_downgrade = False
- force_python_upgrade = False
try:
while True:
+ dbid_path = os.path.join(filename, DBBACKEND)
+ if os.path.isfile(dbid_path):
+ with open(dbid_path) as fp:
+ dbid = fp.read().strip()
+ else:
+ dbid = "bsddb"
+
+ db = make_database(dbid)
+ db.disable_signals()
+ if db.requires_login() and username is None:
+ login = GrampsLoginDialog(self.uistate)
+ credentials = login.run()
+ if credentials is None:
+ return
+ username, password = credentials
+
try:
- db.load(filename, self._pulse_progress,
+ db.load(filename, self.uistate.pulse_progressbar,
mode, force_schema_upgrade,
- force_bsddb_upgrade,
- force_bsddb_downgrade,
- force_python_upgrade,
username=username,
password=password)
if self.dbstate.is_open():
self.dbstate.db.close(
- user=User(callback=self._pulse_progress,
+ user=User(callback=self.uistate.pulse_progressbar,
uistate=self.uistate,
dbstate=self.dbstate))
self.dbstate.change_database(db)
break
- except DbUpgradeRequiredError as msg:
- if QuestionDialog2(_("Are you sure you want "
+ except (DbSupportedError, DbUpgradeRequiredError) as msg:
+ if(force_schema_upgrade or
+ QuestionDialog2(_("Are you sure you want "
"to upgrade this Family Tree?"),
str(msg),
_("I have made a backup,\n"
"please upgrade my Family Tree"),
_("Cancel"),
- parent=self.uistate.window).run():
+ parent=self.uistate.window).run()):
force_schema_upgrade = True
- force_bsddb_upgrade = False
- force_bsddb_downgrade = False
- force_python_upgrade = False
- else:
- self.dbstate.no_database()
- break
- except BsddbUpgradeRequiredError as msg:
- if QuestionDialog2(_("Are you sure you want "
- "to upgrade this Family Tree?"),
- str(msg),
- _("I have made a backup,\n"
- "please upgrade my Family Tree"),
- _("Cancel"),
- parent=self.uistate.window).run():
- force_schema_upgrade = False
- force_bsddb_upgrade = True
- force_bsddb_downgrade = False
- force_python_upgrade = False
- else:
- self.dbstate.no_database()
- break
- except BsddbDowngradeRequiredError as msg:
- if QuestionDialog2(_("Are you sure you want "
- "to downgrade this Family Tree?"),
- str(msg),
- _("I have made a backup,\n"
- "please downgrade my Family Tree"),
- _("Cancel"),
- parent=self.uistate.window).run():
- force_schema_upgrade = False
- force_bsddb_upgrade = False
- force_bsddb_downgrade = True
- force_python_upgrade = False
- else:
- self.dbstate.no_database()
- break
- except PythonUpgradeRequiredError as msg:
- if QuestionDialog2(_("Are you sure you want "
- "to upgrade this Family Tree?"),
- str(msg),
- _("I have made a backup,\n"
- "please upgrade my Family Tree"),
- _("Cancel"),
- parent=self.uistate.window).run():
- force_schema_upgrade = False
- force_bsddb_upgrade = False
- force_bsddb_downgrade = False
- force_python_upgrade = True
+ make_zip_backup(filename)
else:
self.dbstate.no_database()
break
# Get here is there is an exception the while loop does not handle
- except BsddbDowngradeError as msg:
- self.dbstate.no_database()
- self._warn( _("Cannot open database"), str(msg))
except DbVersionError as msg:
self.dbstate.no_database()
self._errordialog( _("Cannot open database"), str(msg))
except DbPythonError as msg:
self.dbstate.no_database()
self._errordialog( _("Cannot open database"), str(msg))
- except DbEnvironmentError as msg:
- self.dbstate.no_database()
- self._errordialog( _("Cannot open database"), str(msg))
- except PythonDowngradeError as msg:
- self.dbstate.no_database()
- self._warn( _("Cannot open database"), str(msg))
except DbConnectionError as msg:
self.dbstate.no_database()
self._warn(_("Cannot open database"), str(msg))
@@ -300,7 +236,8 @@ class DbLoader(CLIDbLoader):
except Exception as newerror:
self.dbstate.no_database()
self._dberrordialog(str(newerror))
- self._end_progress()
+
+ self.uistate.progress.hide()
return True
#-------------------------------------------------------------------------
diff --git a/gramps/plugins/db/bsddb/__init__.py b/gramps/plugins/db/bsddb/__init__.py
deleted file mode 100644
index ac9b07863..000000000
--- a/gramps/plugins/db/bsddb/__init__.py
+++ /dev/null
@@ -1,75 +0,0 @@
-#
-# Gramps - a GTK+/GNOME based genealogy program
-#
-# Copyright (C) 2000-2007 Donald N. Allingham
-#
-# 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.
-#
-
-"""
-Gramps Database API.
-
-Database Architecture
-=====================
-
-Access to the database is made through Python classes. Exactly
-what functionality you have is dependent on the properties of the
-database. For example, if you are accessing a read-only view, then
-you will only have access to a subset of the methods available.
-
-At the root of any database interface is either :py:class:`.DbReadBase` and/or
-:py:class:`.DbWriteBase`. These define the methods to read and write to a
-database, respectively.
-
-The full database hierarchy is:
-
-- :py:class:`.DbBsddb` - read and write implementation to BSDDB databases
-
- * :py:class:`.DbWriteBase` - virtual and implementation-independent methods
- for reading data
-
- * :py:class:`.DbBsddbRead` - read-only (accessors, getters) implementation
- to BSDDB databases
-
- + :py:class:`.DbReadBase` - virtual and implementation-independent
- methods for reading data
-
- + :py:class:`.Callback` - callback and signal functions
-
- * :py:class:`.UpdateCallback` - callback functionality
-
-DbBsddb
-=======
-
-The :py:class:`.DbBsddb` interface defines a hierarchical database
-(non-relational) written in
-`PyBSDDB `_. There is no
-such thing as a database schema, and the meaning of the data is
-defined in the Python classes above. The data is stored as pickled
-tuples and unserialized into the primary data types (below).
-
-More details can be found in the manual's
-`Using database API `_.
-"""
-
-from gramps.gen.db.base import *
-from gramps.gen.db.dbconst import *
-from .cursor import *
-from .read import *
-from .bsddbtxn import *
-from gramps.gen.db.txn import *
-from .undoredo import *
-from gramps.gen.db.exceptions import *
-from .write import *
diff --git a/gramps/plugins/db/bsddb/bsddb.gpr.py b/gramps/plugins/db/bsddb/bsddb.gpr.py
index 6ce179567..31e655fea 100644
--- a/gramps/plugins/db/bsddb/bsddb.gpr.py
+++ b/gramps/plugins/db/bsddb/bsddb.gpr.py
@@ -26,7 +26,7 @@ plg.id = 'bsddb'
plg.name = _("BSDDB")
plg.name_accell = _("_BSDDB Database")
plg.description = _("Berkeley Software Distribution Database Backend")
-plg.version = '1.0'
+plg.version = '2.0'
plg.gramps_target_version = "5.1"
plg.status = STABLE
plg.fname = 'bsddb.py'
diff --git a/gramps/plugins/db/bsddb/bsddb.py b/gramps/plugins/db/bsddb/bsddb.py
index cfae6c76e..33090c95d 100644
--- a/gramps/plugins/db/bsddb/bsddb.py
+++ b/gramps/plugins/db/bsddb/bsddb.py
@@ -1,7 +1,8 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
-# Copyright (C) 2015-2016 Douglas S. Blank
+# Copyright (C) 2020 Paul Culley
+# Copyright (C) 2020 Nick Hall
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,7 +18,246 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
+""" BSDDB upgrade module """
+#------------------------------------------------------------------------
+#
+# Python Modules
+#
+#------------------------------------------------------------------------
+import os
+import pickle
+import logging
+from bsddb3.db import DB, DB_DUP, DB_HASH, DB_RDONLY
+#-------------------------------------------------------------------------
+#
+# Gramps modules
+#
+#-------------------------------------------------------------------------
+from gramps.plugins.db.dbapi.sqlite import SQLite
+from gramps.cli.clidbman import NAME_FILE, find_next_db_dir
+from gramps.gen.db.dbconst import DBBACKEND, DBMODE_W, SCHVERSFN
+from gramps.gen.db.exceptions import (DbException, DbSupportedError,
+ DbUpgradeRequiredError, DbVersionError)
+from gramps.gen.db.utils import clear_lock_file
+from gramps.gen.lib import Researcher
+from gramps.gen.const import GRAMPS_LOCALE as glocale
+from gramps.gen.updatecallback import UpdateCallback
+_ = glocale.translation.gettext
+
+LOG = logging.getLogger(".upgrade")
+_MINVERSION = 9
+_DBVERSION = 19
-from gramps.plugins.db.bsddb import DbBsddb
+class DbBsddb(SQLite):
+ """
+ Gramps BSDDB Converter
+ """
+ def __init__(self):
+ """Create a new GrampsDB."""
+ super().__init__()
+
+ def load(self, dirname, callback=None, mode=DBMODE_W,
+ force_schema_upgrade=False,
+ update=True,
+ username=None, password=None):
+ """
+ Here we create a sqlite db, and copy the bsddb into it.
+ The new db is initially in a new directory, when we finish the copy
+ we replace the contents of the original directory with the new db.
+
+ We alway raise an exception to complete this, as the new db still
+ needs to be upgraded some more. When we raise the exception, the new
+ db is closed.
+ """
+ if not update:
+ raise DbException("Not Available")
+ if not force_schema_upgrade: # make sure user wants to upgrade
+ raise DbSupportedError(_("BSDDB"))
+
+ UpdateCallback.__init__(self, callback)
+
+ # Here we open the dbapi db (a new one) for writing
+ new_path = find_next_db_dir()
+ os.mkdir(new_path)
+ # store dbid in new dir
+ dbid = 'sqlite'
+ backend_path = os.path.join(new_path, DBBACKEND)
+ with open(backend_path, "w", encoding='utf8') as backend_file:
+ backend_file.write(dbid)
+
+ super().load(new_path, callback=None, mode='w',
+ force_schema_upgrade=False,
+ username=username, password=password)
+
+ # now read in the bsddb and copy to dpapi
+ schema_vers = None
+ total = 0
+ tables = (
+ ('person', 'person'),
+ ('family', 'family'),
+ ('event', 'event'),
+ ('place', 'place'),
+ ('repo', 'repository'),
+ ('source', 'source'),
+ ('citation', 'citation'),
+ ('media', 'media'),
+ ('note', 'note'),
+ ('tag', 'tag'),
+ ('meta_data', 'metadata'))
+
+ # open each dbmap, and get its length for the total
+ file_name = os.path.join(dirname, 'name_group.db')
+ if os.path.isfile(file_name):
+ name_group_dbmap = DB()
+ name_group_dbmap.set_flags(DB_DUP)
+ name_group_dbmap.open(file_name, 'name_group', DB_HASH, DB_RDONLY)
+ total += len(name_group_dbmap)
+ else:
+ name_group_dbmap = None
+
+ table_list = []
+ for old_t, new_t in (tables):
+
+ file_name = os.path.join(dirname, old_t + '.db')
+ if not os.path.isfile(file_name):
+ continue
+ dbmap = DB()
+ dbmap.open(file_name, old_t, DB_HASH, DB_RDONLY)
+ total += len(dbmap)
+ table_list.append((old_t, new_t, dbmap))
+
+ self.set_total(total)
+ # copy data from each dbmap to sqlite table
+ for old_t, new_t, dbmap in table_list:
+ self._txn_begin()
+ if new_t == 'metadata':
+ sql = ("REPLACE INTO metadata (setting, value) VALUES "
+ "(?, ?)")
+ else:
+ sql = ("INSERT INTO %s (handle, blob_data) VALUES "
+ "(?, ?)" % new_t)
+
+ for key in dbmap.keys():
+ self.update()
+ data = pickle.loads(dbmap[key], encoding='utf-8')
+
+ if new_t == 'metadata':
+ if key == b'version':
+ # found a schema version in metadata
+ schema_vers = data
+ elif key == b'researcher':
+ if len(data[0]) == 7: # Pre-3.3 format
+ # Upgrade researcher data to include a locality
+ # field in the address.
+ addr = tuple([data[0][0], ''] + list(data[0][1:]))
+ new_data = (addr, data[1], data[2], data[3])
+ else:
+ new_data = data
+ data = Researcher().unserialize(new_data)
+ elif key == b'name_formats':
+ # upgrade formats if they were saved in the old way
+ for format_ix in range(len(data)):
+ fmat = data[format_ix]
+ if len(fmat) == 3:
+ fmat = fmat + (True,)
+ data[format_ix] = fmat
+ elif key == b'gender_stats':
+ # data is a dict, containing entries (see GenderStats)
+ self.dbapi.execute("DELETE FROM gender_stats")
+ g_sql = ("INSERT INTO gender_stats "
+ "(given_name, female, male, unknown) "
+ "VALUES (?, ?, ?, ?)")
+ for name in data:
+ female, male, unknown = data[name]
+ self.dbapi.execute(g_sql,
+ [name, female, male, unknown])
+ continue # don't need this in metadata anymore
+ elif key == b'default':
+ # convert to string and change key
+ if isinstance(data, bytes):
+ data = data.decode('utf-8')
+ key = b'default-person-handle'
+ elif key == b'mediapath':
+ # change key
+ key = b'media-path'
+ elif key in [b'surname_list', # created by db now
+ b'pevent_names', # obsolete
+ b'fevent_names']: # obsolete
+ continue
+ elif (b'_names' in key or b'refs' in key or
+ b'_roles' in key or b'rels' in key or
+ b'_types' in key):
+ # These are list, but need to be set
+ data = set(data)
+
+ self.dbapi.execute(sql,
+ [key.decode('utf-8'),
+ pickle.dumps(data)])
+
+ # get schema version from file if not in metadata
+ if new_t == 'metadata' and schema_vers is None:
+ versionpath = os.path.join(dirname, str(SCHVERSFN))
+ if os.path.isfile(versionpath):
+ with open(versionpath, "r") as version_file:
+ schema_vers = int(version_file.read().strip())
+ else:
+ schema_vers = 0
+ # and put schema version into metadata
+ self.dbapi.execute(sql, ["version", schema_vers])
+ self._txn_commit()
+ dbmap.close()
+ if new_t == 'metadata' and schema_vers < _MINVERSION:
+ raise DbVersionError(schema_vers, _MINVERSION, _DBVERSION)
+
+ if name_group_dbmap:
+ self._txn_begin()
+ for key in name_group_dbmap.keys():
+ self.update()
+ # name_group data (grouping) is NOT pickled
+ data = name_group_dbmap[key]
+ name = key.decode('utf-8')
+ grouping = data.decode('utf-8')
+ self.dbapi.execute(
+ "INSERT INTO name_group (name, grouping) VALUES (?, ?)",
+ [name, grouping])
+ self._txn_commit()
+ name_group_dbmap.close()
+
+ # done with new sqlite db, close it. Cannot use normal close as it
+ # overwrites the metadata.
+ self._close()
+ try:
+ clear_lock_file(self.get_save_path())
+ except IOError:
+ pass
+ self.db_is_open = False
+ self._directory = None
+
+ # copy tree name to new dir
+ old_db_name = os.path.join(dirname, NAME_FILE)
+ db_name = os.path.join(new_path, NAME_FILE)
+ with open(old_db_name, "r", encoding='utf8') as _file:
+ name = _file.read().strip()
+ with open(db_name, "w", encoding='utf8') as _file:
+ _file.write(name)
+ # remove files from old dir
+ for filename in os.listdir(dirname):
+ file_path = os.path.join(dirname, filename)
+ try:
+ os.unlink(file_path)
+ except Exception as e:
+ LOG.error('Failed to delete %s. Reason: %s' % (file_path, e))
+ # copy new db files to old dir
+ for filename in os.listdir(new_path):
+ old_file_path = os.path.join(new_path, filename)
+ file_path = os.path.join(dirname, filename)
+ try:
+ os.replace(old_file_path, file_path)
+ except Exception as e:
+ LOG.error('Failed to move %s. Reason: %s' % (old_file_path, e))
+ os.rmdir(new_path)
+
+ # done preparing new db, but we still need to finish schema upgrades
+ raise DbUpgradeRequiredError(schema_vers, 'xx')
diff --git a/gramps/plugins/db/bsddb/bsddbtxn.py b/gramps/plugins/db/bsddb/bsddbtxn.py
deleted file mode 100644
index 360c8b7dd..000000000
--- a/gramps/plugins/db/bsddb/bsddbtxn.py
+++ /dev/null
@@ -1,239 +0,0 @@
-#
-# Gramps - a GTK+/GNOME based genealogy program
-#
-# Copyright (C) 2009 Gerald W. Britton
-#
-# 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.
-#
-
-"""
-BSDDBTxn class: Wrapper for BSDDB transaction-oriented methods
-"""
-
-#-------------------------------------------------------------------------
-#
-# Standard python modules
-#
-#-------------------------------------------------------------------------
-import logging
-import inspect
-import os
-
-#-------------------------------------------------------------------------
-#
-# Gramps modules
-#
-#-------------------------------------------------------------------------
-from gramps.gen.db.dbconst import DBLOGNAME
-_LOG = logging.getLogger(DBLOGNAME)
-
-#-------------------------------------------------------------------------
-#
-# BSDDBTxn
-#
-#-------------------------------------------------------------------------
-
-class BSDDBTxn:
- """
- Wrapper for BSDDB methods that set up and manage transactions. Implements
- context management functionality allowing constructs like:
-
- with BSDDBTxn(env) as txn:
- DB.get(txn=txn)
- DB.put(txn=txn)
- DB.delete(txn=txn)
-
- and other transaction-oriented DB access methods, where "env" is a
- BSDDB DBEnv object and "DB" is a BSDDB database object.
-
- Transactions are automatically begun when the "with" statement is executed
- and automatically committed when control flows off the end of the "with"
- statement context, either implicitly by reaching the end of the indentation
- level or explicity if a "return" statement is encountered or an exception
- is raised.
- """
-
- __slots__ = ['env', 'db', 'txn', 'parent']
-
- def __init__(self, env, db=None):
- """
- Initialize transaction instance
- """
- # Conditional on __debug__ because all that frame stuff may be slow
- if __debug__:
- caller_frame = inspect.stack()[1]
- _LOG.debug(" BSDDBTxn %s instantiated. Called from file %s,"
- " line %s, in %s" %
- ((hex(id(self)),)+
- (os.path.split(caller_frame[1])[1],)+
- (tuple(caller_frame[i] for i in range(2, 4)))
- )
- )
- self.env = env
- self.db = db
- self.txn = None
-
- # Context manager methods
-
- def __enter__(self, parent=None, **kwargs):
- """
- Context manager entry method
-
- Begin the transaction
- """
- _LOG.debug(" BSDDBTxn %s entered" % hex(id(self)))
- self.txn = self.begin(parent, **kwargs)
- self.parent = parent
- return self
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- """
- Context manager exit function
-
- Commit the transaction if no exception occurred
- """
- _LOG.debug(" BSDDBTxn %s exited" % hex(id(self)))
- if exc_type is not None:
- return False
- if self.txn:
- self.commit()
- return True
-
- # Methods implementing txn_ methods in DBEnv
-
- def begin(self, *args, **kwargs):
- """
- Create and begin a new transaction. A DBTxn object is returned
- """
- _LOG.debug(" BSDDBTxn %s begin" % hex(id(self)))
- _LOG.debug(" BSDDBTxn %s calls %s %s txn_begin" %
- (hex(id(self)), self.env.__class__.__name__,
- hex(id(self.env)))
- )
- self.txn = self.env.txn_begin(*args, **kwargs)
- return self.txn
-
- def checkpoint(self, *args, **kwargs):
- """
- Flush the underlying memory pool, write a checkpoint record to the
- log and then flush the log
- """
- if self.env:
- self.env.txn_checkpoint(*args, **kwargs)
-
- def stat(self):
- """
- Return a dictionary of transaction statistics
- """
- if self.env:
- return self.env.txn_stat()
-
- def recover(self):
- """
- Returns a list of tuples (GID, TXN) of transactions prepared but
- still unresolved
- """
- if self.env:
- return self.env.txn_recover()
-
- # Methods implementing DBTxn methods
-
- def abort(self):
- """
- Abort the transaction
- """
- if self.txn:
- self.txn.abort()
- self.txn = None
-
- def commit(self, flags=0):
- """
- End the transaction, committing any changes to the databases
- """
- _LOG.debug(" BSDDBTxn %s commit" % hex(id(self)))
- if self.txn:
- self.txn.commit(flags)
- self.txn = None
-
- def id(self):
- """
- Return the unique transaction id associated with the specified
- transaction
- """
- if self.txn:
- return self.txn.id()
-
- def prepare(self, gid):
- """
- Initiate the beginning of a two-phase commit
- """
- if self.txn:
- self.txn.prepare(gid)
-
- def discard(self):
- """
- Release all the per-process resources associated with the specified
- transaction, neither committing nor aborting the transaction
- """
- if self.txn:
- self.txn.discard()
- self.txn = None
-
- # Methods implementing DB methods within the transaction context
-
- def get(self, key, default=None, txn=None, **kwargs):
- """
- Returns the data object associated with key
- """
- return self.db.get(key, default, txn or self.txn, **kwargs)
-
- def pget(self, key, default=None, txn=None, **kwargs):
- """
- Returns the primary key, given the secondary one, and associated data
- """
- return self.db.pget(key, default, txn or self.txn, **kwargs)
-
- def put(self, key, data, txn=None, **kwargs):
- """
- Stores the key/data pair in the database
- """
- return self.db.put(key, data, txn or self.txn, **kwargs)
-
- def delete(self, key, txn=None, **kwargs):
- """
- Removes a key/data pair from the database
- """
- self.db.delete(key, txn or self.txn, **kwargs)
-
-# test code
-if __name__ == "__main__":
- print("1")
- from bsddb3 import db, dbshelve
- print("2")
- x = db.DBEnv()
- print("3")
- x.open('/tmp', db.DB_CREATE | db.DB_PRIVATE |\
- db.DB_INIT_MPOOL |\
- db.DB_INIT_LOG | db.DB_INIT_TXN)
- print("4")
- d = dbshelve.DBShelf(x)
- print("5")
- #from tran import BSDDBTxn as T
- print("6")
- T = BSDDBTxn
- with T(x) as tx:
- print("stat", tx.stat())
- print("id", tx.id())
- tx.checkpoint()
diff --git a/gramps/plugins/db/bsddb/cursor.py b/gramps/plugins/db/bsddb/cursor.py
deleted file mode 100644
index 1eecffc03..000000000
--- a/gramps/plugins/db/bsddb/cursor.py
+++ /dev/null
@@ -1,134 +0,0 @@
-#
-# Gramps - a GTK+/GNOME based genealogy program
-#
-# Copyright (C) 2000-2007 Donald N. Allingham
-#
-# 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.
-#
-# gen/db/cursor.py
-
-#-------------------------------------------------------------------------
-#
-# Standard python modules
-#
-#-------------------------------------------------------------------------
-from pickle import dumps, loads
-
-try:
- from bsddb3 import db
-except:
- # FIXME: make this more abstract to deal with other backends
- class db:
- DB_RMW = 0
- DB_FIRST = 0
- DB_LAST = 0
- DB_CURRENT = 0
- DB_PREV = 0
- DB_NEXT = 0
-
-#-------------------------------------------------------------------------
-#
-# BsddbBaseCursor class
-#
-#-------------------------------------------------------------------------
-
-class BsddbBaseCursor:
- """
- Provide a basic iterator that allows the user to cycle through
- the elements in a particular map.
-
- A cursor should never be directly instantiated. Instead, in should be
- created by the database class.
-
- A cursor should only be used for a single pass through the
- database. If multiple passes are needed, multiple cursors
- should be used.
- """
-
- def __init__(self, txn=None, update=False, commit=False):
- """
- Instantiate the object. Note, this method should be overridden in
- derived classes that properly set self.cursor and self.source
- """
- self.cursor = self.source = None
- self.txn = txn
- self._update = update
- self.commit = commit
-
- def __getattr__(self, name):
- """
- Return a method from the underlying cursor object, if it exists
- """
- return getattr(self.cursor, name)
-
- def __enter__(self):
- """
- Context manager enter method
- """
- return self
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- """
- Context manager exit method
- """
- self.close()
- if self.txn and self.commit:
- self.txn.commit()
- return exc_type is None
-
- def __iter__(self):
- """
- Iterator
- """
-
- data = self.first()
- _n = self.next # Saved attribute lookup in the loop
- while data:
- yield data
- data = _n()
-
- def _get(_flags=0):
- """ Closure that returns a cursor get function """
-
- def get(self, flags=0, **kwargs):
- """
- Issue DBCursor get call (with DB_RMW flag if update requested)
- Return results to caller
- """
- data = self.cursor.get(
- _flags | flags | (db.DB_RMW if self._update else 0),
- **kwargs)
-
- return (data[0].decode('utf-8'), loads(data[1])) if data else None
-
- return get
-
- # Use closure to define access methods
-
- current = _get(db.DB_CURRENT)
- first = _get(db.DB_FIRST)
- ##python2 iterator
- next = _get(db.DB_NEXT)
- ##python3 iterator
- __next__ = _get(db.DB_NEXT)
- last = _get(db.DB_LAST)
- prev = _get(db.DB_PREV)
-
- def update(self, key, data, flags=0, **kwargs):
- """
- Write the current key, data pair to the database.
- """
- self.cursor.put(key, dumps(data), flags=flags | db.DB_CURRENT,
- **kwargs)
diff --git a/gramps/plugins/db/bsddb/read.py b/gramps/plugins/db/bsddb/read.py
deleted file mode 100644
index 57906b795..000000000
--- a/gramps/plugins/db/bsddb/read.py
+++ /dev/null
@@ -1,1948 +0,0 @@
-#
-# Gramps - a GTK+/GNOME based genealogy program
-#
-# Copyright (C) 2000-2007 Donald N. Allingham
-# Copyright (C) 2010 Nick Hall
-# Copyright (C) 2011 Tim G L Lyons
-#
-# 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.
-#
-
-"""
-Read classes for the Gramps databases.
-"""
-
-#-------------------------------------------------------------------------
-#
-# libraries
-#
-#-------------------------------------------------------------------------
-import pickle
-import time
-import random
-import os
-from sys import maxsize
-from operator import itemgetter
-import ast
-from functools import partial
-
-try:
- from bsddb3 import db
-except:
- # FIXME: make this more abstract to deal with other backends
- class db:
- DBRunRecoveryError = 0
- DBAccessError = 0
- DBPageNotFoundError = 0
- DBInvalidArgError = 0
-
-import re
-import logging
-
-#-------------------------------------------------------------------------
-#
-# Gramps libraries
-#
-#-------------------------------------------------------------------------
-from gramps.gen.lib.media import Media
-from gramps.gen.lib.person import Person
-from gramps.gen.lib.family import Family
-from gramps.gen.lib.src import Source
-from gramps.gen.lib.citation import Citation
-from gramps.gen.lib.event import Event
-from gramps.gen.lib.place import Place
-from gramps.gen.lib.repo import Repository
-from gramps.gen.lib.note import Note
-from gramps.gen.lib.tag import Tag
-from gramps.gen.lib.genderstats import GenderStats
-from gramps.gen.lib.researcher import Researcher
-from gramps.gen.lib.nameorigintype import NameOriginType
-
-from gramps.gen.utils.callback import Callback
-from . import BsddbBaseCursor
-from gramps.gen.db.base import DbReadBase
-from gramps.gen.db.bookmarks import DbBookmarks
-from gramps.gen.utils.id import create_id
-from gramps.gen.errors import DbError, HandleError
-from gramps.gen.constfunc import get_env_var
-from gramps.gen.const import GRAMPS_LOCALE as glocale
-_ = glocale.translation.gettext
-
-from gramps.gen.db.dbconst import *
-
-LOG = logging.getLogger(DBLOGNAME)
-LOG = logging.getLogger(".citation")
-#-------------------------------------------------------------------------
-#
-# constants
-#
-#-------------------------------------------------------------------------
-
-_SIGBASE = ('person', 'family', 'source', 'citation',
- 'event', 'media', 'place', 'repository',
- 'reference', 'note', 'tag')
-
-DBERRS = (db.DBRunRecoveryError, db.DBAccessError,
- db.DBPageNotFoundError, db.DBInvalidArgError)
-
-#-------------------------------------------------------------------------
-#
-# Helper functions
-#
-#-------------------------------------------------------------------------
-def find_byte_surname(key, data):
- """
- Creating a surname from raw data of a person, to use for sort and index
- returns a byte string
- """
- surn = __index_surname(data[3][5])
- # in python 3 we work with unicode internally, but need byte function sometimes
- return surn.encode('utf-8')
-
-def find_fullname(key, data):
- """
- Creating a fullname from raw data of a person, to use for sort and index
- """
- # data[3] -> primary_name
- # data[3][4] -> primary given
- # data[3][5] -> surname_list
- # data[3][5][0] -> primary surnameobj
- # data[3][5][0][0] -> primary surname
- # data[3][5][0][1] -> primary surname prefix
- # data[3][5][0][2] -> primary surname primary (bool)
- # data[3][5][0][3] -> primary surname origin type
- # data[3][5][0][4] -> primary surname connector
- # [(surname + ' ' + given,
- # surname prefix,
- # surname primary,
- # surname origin type,
- # surname connector)]
- if data[3][5]: # if Surname available
- fullname_data = [(data[3][5][0][0] + ' ' + data[3][4], # combined
- data[3][5][0][1], data[3][5][0][2],
- data[3][5][0][3], data[3][5][0][4])]
- else: # Some importers don't add any Surname at all
- fullname_data = [(' ' + data[3][4], '', True, (1, ''), '')]
- # ignore if origin type is PATRONYMIC or MATRONYMIC
- return __index_surname(fullname_data)
-
-def find_surname(key, data):
- """
- Creating a surname from raw data of a person, to use for sort and index
- """
- # data[3][5] -> surname_list
- return __index_surname(data[3][5])
-
-def find_surname_name(key, data):
- """
- Creating a surname from raw name, to use for sort and index
- """
- return __index_surname(data[5])
-
-def __index_surname(surn_list):
- """
- All non pa/matronymic surnames are used in indexing.
- pa/matronymic not as they change for every generation!
- """
- if surn_list:
- surn = " ".join([x[0] for x in surn_list if not (x[3][0] in [
- NameOriginType.PATRONYMIC, NameOriginType.MATRONYMIC]) ])
- else:
- surn = ""
- return surn
-
-#-------------------------------------------------------------------------
-#
-# GrampsDBReadCursor
-#
-#-------------------------------------------------------------------------
-class DbReadCursor(BsddbBaseCursor):
-
- def __init__(self, source, txn=None, **kwargs):
- BsddbBaseCursor.__init__(self, txn=txn, **kwargs)
- self.cursor = source.db.cursor(txn)
- self.source = source
-
-#-------------------------------------------------------------------------
-#
-# DbBsddbTreeCursor
-#
-#-------------------------------------------------------------------------
-class DbBsddbTreeCursor(BsddbBaseCursor):
-
- def __init__(self, source, primary, readonly, txn=None, **kwargs):
- BsddbBaseCursor.__init__(self, txn=txn, **kwargs)
- self.cursor = source.cursor(txn)
- self.source = source
- self.primary = primary
- self.readonly = readonly
-
- def __iter__(self):
- """
- Iterator
- """
- _n = self.next_dup
- to_do = ['']
- while to_do:
- key = to_do.pop()
- data = self.set(key.encode('utf-8'))
- while data:
- ### FIXME: this is a dirty hack that works without no
- ### sensible explanation. For some reason, for a readonly
- ### database, secondary index returns a primary table key
- ### corresponding to the data, not the data.
- if self.readonly:
- payload = self.primary.get(data[1], txn=self.txn)
- else:
- payload = pickle.loads(data[1])
- yield (payload[0], payload)
- to_do.append(payload[0])
- data = _n()
-
-class DbBsddbRead(DbReadBase, Callback):
- """
- Read class for the Gramps databases. Implements methods necessary to read
- the various object classes. Currently, there are nine (9) classes:
-
- :py:class:`.Person`, :py:class:`.Family`, :py:class:`.Event`,
- :py:class:`.Place`, :py:class:`.Source`,
- :py:class:`Citation <.lib.citation.Citation>`, :py:class:`.Media`,
- :py:class:`.Repository` and :py:class:`.Note`
-
- For each object class, there are methods to retrieve data in various ways.
- In the methods described below,