From 70778c8d8a94b9690706552cda1558e393284774 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 19 Jun 2012 17:30:52 +0200 Subject: [PATCH 1/3] Backup and restore db preferences --- src/calibre/gui2/ui.py | 1 + src/calibre/library/prefs.py | 25 ++++++++++++++++++++++++- src/calibre/library/restore.py | 13 +++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 8b5c34003d..713aa77e29 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -738,6 +738,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ # Goes here, because if cf is valid, db is valid. db.prefs['field_metadata'] = db.field_metadata.all_metadata() db.commit_dirty_cache() + db.prefs.write_serialized(prefs['library_path']) for action in self.iactions.values(): if not action.shutting_down(): return diff --git a/src/calibre/library/prefs.py b/src/calibre/library/prefs.py index 4514f4cf1e..8b2bb0c7fd 100644 --- a/src/calibre/library/prefs.py +++ b/src/calibre/library/prefs.py @@ -5,7 +5,7 @@ __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' -import json +import json, os from calibre.constants import preferred_encoding from calibre.utils.config import to_json, from_json @@ -68,3 +68,26 @@ class DBPrefs(dict): key = u'namespaced:%s:%s'%(namespace, key) self[key] = val + def write_serialized(self, library_path): + try: + to_filename = os.path.join(library_path, 'metadata_db_prefs.json') + with open(to_filename, "wb") as f: + f.write(json.dumps(self, indent=2, default=to_json)) + except: + import traceback + traceback.print_exc() + + def read_serialized(self, library_path): + try: + from_filename = os.path.join(library_path, 'metadata_db_prefs.json') + with open(from_filename, "rb") as f: + d = json.load(f, object_hook=from_json) + self.db.conn.execute('DELETE FROM preferences') + for k,v in d.iteritems(): + raw = self.to_raw(v) + self.db.conn.execute( + 'INSERT OR REPLACE INTO preferences (key,val) VALUES (?,?)', + (k, raw)) + except: + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/src/calibre/library/restore.py b/src/calibre/library/restore.py index 4fab2edbd6..fc0df4a006 100644 --- a/src/calibre/library/restore.py +++ b/src/calibre/library/restore.py @@ -101,6 +101,7 @@ class Restore(Thread): with TemporaryDirectory('_library_restore') as tdir: self.library_path = tdir self.scan_library() + self.load_preferences() self.create_cc_metadata() self.restore_books() if self.successes == 0 and len(self.dirs) > 0: @@ -109,6 +110,18 @@ class Restore(Thread): except: self.tb = traceback.format_exc() + def load_preferences(self): + self.progress_callback(None, 1) + self.progress_callback('Starting restore preferences', 0) + dbpath = os.path.join(self.src_library_path, 'metadata_db_prefs.json') + ndbpath = os.path.join(self.library_path, 'metadata_db_prefs.json') + shutil.copyfile(dbpath, ndbpath) + db = RestoreDatabase(self.library_path) + db.prefs.read_serialized(self.library_path) + db.commit() + db.conn.close() + self.progress_callback('Finished restore preferences', 1) + def scan_library(self): for dirpath, dirnames, filenames in os.walk(self.src_library_path): leaf = os.path.basename(dirpath) From 4205c7b8a1deb8fc088b38e399ac08dd11e05c6f Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 19 Jun 2012 17:46:02 +0200 Subject: [PATCH 2/3] Do a commit when preferences are restored. Ensure that the in-memory copy of the prefs is correct after restore. --- src/calibre/library/prefs.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/calibre/library/prefs.py b/src/calibre/library/prefs.py index 4bd39e20b2..1b80464d2a 100644 --- a/src/calibre/library/prefs.py +++ b/src/calibre/library/prefs.py @@ -84,13 +84,15 @@ class DBPrefs(dict): try: from_filename = os.path.join(library_path, 'metadata_db_prefs.json') with open(from_filename, "rb") as f: + self.clear() d = json.load(f, object_hook=from_json) self.db.conn.execute('DELETE FROM preferences') for k,v in d.iteritems(): raw = self.to_raw(v) self.db.conn.execute( - 'INSERT OR REPLACE INTO preferences (key,val) VALUES (?,?)', - (k, raw)) + 'INSERT INTO preferences (key,val) VALUES (?,?)', (k, raw)) + self.db.conn.commit() + self.update(d) except: import traceback traceback.print_exc() \ No newline at end of file From 6fe358ed3e0e87347ea06488ece404bdb5ce303b Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 19 Jun 2012 17:54:13 +0200 Subject: [PATCH 3/3] Add some exception handling code for when the preferences backup file doesn't exist. --- src/calibre/library/restore.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/calibre/library/restore.py b/src/calibre/library/restore.py index fc0df4a006..597e877833 100644 --- a/src/calibre/library/restore.py +++ b/src/calibre/library/restore.py @@ -115,12 +115,18 @@ class Restore(Thread): self.progress_callback('Starting restore preferences', 0) dbpath = os.path.join(self.src_library_path, 'metadata_db_prefs.json') ndbpath = os.path.join(self.library_path, 'metadata_db_prefs.json') - shutil.copyfile(dbpath, ndbpath) - db = RestoreDatabase(self.library_path) - db.prefs.read_serialized(self.library_path) - db.commit() - db.conn.close() - self.progress_callback('Finished restore preferences', 1) + if not os.path.exists(dbpath): + self.progress_callback('Cannot restore preferences. Backup file not found.', 1) + return + try: + shutil.copyfile(dbpath, ndbpath) + db = RestoreDatabase(self.library_path) + db.prefs.read_serialized(self.library_path) + db.commit() + db.conn.close() + self.progress_callback('Finished restore preferences', 1) + except: + self.progress_callback('Restoring preferences failed', 1) def scan_library(self): for dirpath, dirnames, filenames in os.walk(self.src_library_path):