From 8f77d6db9f27b030cd603d3353571c293524c057 Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Sat, 30 Apr 2016 10:25:09 -0400 Subject: [PATCH] 1144: Auto backup at exit, but not when opening another database --- gramps/cli/user.py | 5 ++-- gramps/gen/db/base.py | 24 +++++++++++++++++ gramps/gen/db/generic.py | 9 ++++--- gramps/gen/user.py | 5 ++-- gramps/gui/dbloader.py | 8 +++++- gramps/gui/dbman.py | 2 +- gramps/gui/user.py | 5 ++-- gramps/gui/viewmanager.py | 26 +++++-------------- .../plugins/database/bsddb_support/write.py | 3 ++- gramps/plugins/database/inmemorydb.py | 7 +++++ 10 files changed, 60 insertions(+), 34 deletions(-) diff --git a/gramps/cli/user.py b/gramps/cli/user.py index 1db234a55..419c19951 100644 --- a/gramps/cli/user.py +++ b/gramps/cli/user.py @@ -48,14 +48,15 @@ class User(user.User): This class provides a means to interact with the user via CLI. It implements the interface in :class:`.gen.user.User` """ - def __init__(self, callback=None, error=None, auto_accept=False, quiet=False): + def __init__(self, callback=None, error=None, auto_accept=False, quiet=False, + uistate=None, dbstate=None): """ Init. :param error: If given, notify_error delegates to this callback :type error: function(title, error) """ - user.User.__init__(self, callback, error) + user.User.__init__(self, callback, error, uistate, dbstate) self.steps = 0; self.current_step = 0; self._input = input diff --git a/gramps/gen/db/base.py b/gramps/gen/db/base.py index fd0c19dd5..ac1fa7606 100644 --- a/gramps/gen/db/base.py +++ b/gramps/gen/db/base.py @@ -33,12 +33,14 @@ from this class. import re import time from operator import itemgetter +import logging #------------------------------------------------------------------------- # # Gramps libraries # #------------------------------------------------------------------------- +from ..db.dbconst import DBLOGNAME from ..const import GRAMPS_LOCALE as glocale _ = glocale.translation.gettext from ..lib.childreftype import ChildRefType @@ -46,6 +48,8 @@ from ..lib.childref import ChildRef from .txn import DbTxn from .exceptions import DbTransactionCancel +_LOG = logging.getLogger(DBLOGNAME) + def eval_order_by(order_by, obj, db): """ Given a list of [[field, DIRECTION], ...] @@ -2094,6 +2098,26 @@ class DbWriteBase(DbReadBase): """ return getattr(self, table_name) + def autobackup(self, user=None): + """ + Backup the current file as a backup file. + """ + from gramps.cli.user import User + if user is None: + user = User() + if self.is_open() and self.has_changed: + if user.uistate: + user.uistate.set_busy_cursor(True) + user.uistate.progress.show() + user.uistate.push_message(user.dbstate, _("Autobackup...")) + try: + self.backup(user=user) + except DbException as msg: + user.notify_error(_("Error saving backup data"), msg) + if user.uistate: + user.uistate.set_busy_cursor(False) + user.uistate.progress.hide() + class QuerySet(object): """ A container for selection criteria before being actually diff --git a/gramps/gen/db/generic.py b/gramps/gen/db/generic.py index 3f2de01f9..2eba8e2f1 100644 --- a/gramps/gen/db/generic.py +++ b/gramps/gen/db/generic.py @@ -1696,16 +1696,17 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback): return False return True - def close(self, update=True): + def close(self, update=True, user=None): """ Close the database. if update is False, don't change access times, etc. """ if self._directory: - # This is just a dummy file to indicate last modified time of the - # database for gramps.cli.clidbman: - filename = os.path.join(self._directory, "meta_data.db") if update: + self.autobackup(user) + # This is just a dummy file to indicate last modified time of the + # database for gramps.cli.clidbman: + filename = os.path.join(self._directory, "meta_data.db") touch(filename) # Save metadata self.set_metadata('name_formats', self.name_formats) diff --git a/gramps/gen/user.py b/gramps/gen/user.py index c5ce1e237..e37d48ed0 100644 --- a/gramps/gen/user.py +++ b/gramps/gen/user.py @@ -32,11 +32,12 @@ class User(): provide the appropriate interaction (eg. dialogs for GTK, prompts for CLI). """ - def __init__(self, callback=None, error=None): + def __init__(self, callback=None, error=None, uistate=None, dbstate=None): self.callback_function = callback self.error_function = error self._fileout = sys.stderr # redirected to mocks by unit tests - self.uistate = None + self.uistate = uistate + self.dbstate = dbstate def begin_progress(self, title, message, steps): """ diff --git a/gramps/gui/dbloader.py b/gramps/gui/dbloader.py index b64512e44..b556ddbf8 100644 --- a/gramps/gui/dbloader.py +++ b/gramps/gui/dbloader.py @@ -254,7 +254,8 @@ class DbLoader(CLIDbLoader): #returns that info. Otherwise None is set to import_info self.import_info = importer(self.dbstate.db, filename, User(callback=self._pulse_progress, - uistate=self.uistate)) + uistate=self.uistate, + dbstate=self.dbstate)) dirname = os.path.dirname(filename) + os.path.sep config.set('paths.recent-import-dir', dirname) except UnicodeError as msg: @@ -330,6 +331,11 @@ class DbLoader(CLIDbLoader): force_bsddb_downgrade, force_python_upgrade) db.set_save_path(filename) + if self.dbstate.db.is_open(): + self.dbstate.db.close( + user=User(callback=self._pulse_progress, + uistate=self.uistate, + dbstate=self.dbstate)) self.dbstate.change_database(db) break except DbUpgradeRequiredError as msg: diff --git a/gramps/gui/dbman.py b/gramps/gui/dbman.py index 43d0da236..48304a46f 100644 --- a/gramps/gui/dbman.py +++ b/gramps/gui/dbman.py @@ -639,7 +639,7 @@ class DbManager(CLIDbManager): self.__start_cursor(_("Extracting archive...")) dbase = self.dbstate.make_database("bsddb") - dbase.load(new_path, None) + dbase.load(new_path) self.__start_cursor(_("Importing archive...")) check_out(dbase, revision, db_path, self.user) diff --git a/gramps/gui/user.py b/gramps/gui/user.py index 09772975e..3ec447072 100644 --- a/gramps/gui/user.py +++ b/gramps/gui/user.py @@ -48,10 +48,9 @@ class User(user.User): This class provides a means to interact with the user via GTK. It implements the interface in :class:`.gen.user.User` """ - def __init__(self, callback=None, error=None, uistate=None): - user.User.__init__(self, callback, error) + def __init__(self, callback=None, error=None, uistate=None, dbstate=None): + user.User.__init__(self, callback, error, uistate, dbstate) self._progress = None - self.uistate = uistate def begin_progress(self, title, message, steps): """ diff --git a/gramps/gui/viewmanager.py b/gramps/gui/viewmanager.py index 8f47be937..d0b9fabbb 100644 --- a/gramps/gui/viewmanager.py +++ b/gramps/gui/viewmanager.py @@ -297,8 +297,9 @@ class ViewManager(CLIManager): self.__build_main_window() # sets self.uistate if self.user is None: self.user = User(error=ErrorDialog, - callback=self.uistate.pulse_progressbar, - uistate=self.uistate) + callback=self.uistate.pulse_progressbar, + uistate=self.uistate, + dbstate=self.dbstate) self.__connect_signals() if _GTKOSXAPPLICATION: self.macapp.ready() @@ -739,8 +740,7 @@ class ViewManager(CLIManager): self.uistate.set_sensitive(False) # backup data, and close the database - self.__backup() - self.dbstate.db.close() + self.dbstate.db.close(user=self.user) # have each page save anything, if they need to: self.__delete_pages() @@ -752,22 +752,6 @@ class ViewManager(CLIManager): config.save() Gtk.main_quit() - def __backup(self): - """ - Backup the current file as a backup file. - """ - if self.dbstate.db.is_open() and self.dbstate.db.has_changed: - self.uistate.set_busy_cursor(True) - self.uistate.progress.show() - self.uistate.push_message(self.dbstate, _("Autobackup...")) - try: - self.dbstate.db.backup(user=self.user) - except DbException as msg: - ErrorDialog(_("Error saving backup data"), msg, - parent=self.uistate.window) - self.uistate.set_busy_cursor(False) - self.uistate.progress.hide() - def abort(self, obj=None): """ Abandon changes and quit. @@ -1097,6 +1081,8 @@ class ViewManager(CLIManager): dialog = DbManager(self.uistate, self.dbstate, self.window) value = dialog.run() if value: + if self.dbstate.db.is_open(): + self.dbstate.db.close(user=self.user) (filename, title) = value self.db_loader.read_file(filename) self._post_load_newdb(filename, 'x-directory/normal', title) diff --git a/gramps/plugins/database/bsddb_support/write.py b/gramps/plugins/database/bsddb_support/write.py index 5049d684f..ef2afd747 100644 --- a/gramps/plugins/database/bsddb_support/write.py +++ b/gramps/plugins/database/bsddb_support/write.py @@ -1510,13 +1510,14 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): self.db_is_open = False @catch_db_error - def close(self, update=True): + def close(self, update=True, user=None): """ Close the database. if update is False, don't change access times, etc. """ if not self.db_is_open: return + self.autobackup(user) if self.txn: self.transaction_abort(self.transaction) self.env.txn_checkpoint() diff --git a/gramps/plugins/database/inmemorydb.py b/gramps/plugins/database/inmemorydb.py index 913fa7723..5af1967de 100644 --- a/gramps/plugins/database/inmemorydb.py +++ b/gramps/plugins/database/inmemorydb.py @@ -53,6 +53,13 @@ class InMemoryDB(DBAPI): with open(versionpath, "w") as version_file: version_file.write(str(self.VERSION)) + def autobackup(self, user=None): + """ + Nothing to do, as we write it out anyway. + No backups for inmemory databases. + """ + pass + def load(self, directory, callback=None, mode=None, force_schema_upgrade=False, force_bsddb_upgrade=False,