From 7f4ca92b5a5654f0b334dd57c94498b6214dfdd9 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 15 Apr 2019 08:53:43 +0530 Subject: [PATCH] Port ancient LRF viewer settings not serializable to JSON Also just ignore non-serializable settings, making them None when migrating .py files. Such settings are very rare and likely in unused/rarely used corners of calibre so better to hav those fail than the entire migration process. --- src/calibre/gui2/lrf_renderer/main.py | 31 ++++++++++++--------------- src/calibre/utils/config_base.py | 17 ++++++++++----- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/calibre/gui2/lrf_renderer/main.py b/src/calibre/gui2/lrf_renderer/main.py index 5aab2b3155..56d6287601 100644 --- a/src/calibre/gui2/lrf_renderer/main.py +++ b/src/calibre/gui2/lrf_renderer/main.py @@ -7,10 +7,12 @@ from PyQt5.Qt import ( QKeySequence, QPainter, QDialog, QSpinBox, QSlider, QIcon, Qt, QCoreApplication, QThread, QScrollBar) from calibre import __appname__, setup_cli_handlers, islinux, isbsd, as_unicode +from calibre.gui2 import gprefs from calibre.ebooks.lrf.lrfparser import LRFDocument -from calibre.gui2 import error_dialog, \ - config, choose_files, Application +from calibre.gui2 import ( + error_dialog, choose_files, Application + ) from calibre.gui2.dialogs.conversion_error import ConversionErrorDialog from calibre.gui2.lrf_renderer.main_ui import Ui_MainWindow from calibre.gui2.lrf_renderer.config_ui import Ui_ViewerConfig @@ -107,15 +109,12 @@ class Main(MainWindow, Ui_MainWindow): self.closed = False def configure(self, triggered): - opts = config['LRF_ebook_viewer_options'] - if not opts: - opts = self.opts + opts = self.opts d = Config(self, opts) d.exec_() if d.result() == QDialog.Accepted: - opts.white_background = bool(d.white_background.isChecked()) - opts.hyphenate = bool(d.hyphenate.isChecked()) - config['LRF_ebook_viewer_options'] = opts + gprefs['lrf_viewer_white_background'] = opts.white_background = bool(d.white_background.isChecked()) + gprefs['lrf_viewer_hyphenate'] = opts.hyphenate = bool(d.hyphenate.isChecked()) def set_ebook(self, stream): self.progress_bar.setMinimum(0) @@ -289,15 +288,13 @@ Read the LRF e-book book.lrf def normalize_settings(parser, opts): - saved_opts = config['LRF_ebook_viewer_options'] - if not saved_opts: - saved_opts = opts - for opt in parser.option_list: - if not opt.dest: - continue - if getattr(opts, opt.dest) == opt.default and hasattr(saved_opts, opt.dest): - continue - setattr(saved_opts, opt.dest, getattr(opts, opt.dest)) + saved_opts = opts + dh = gprefs.get('lrf_viewer_hyphenate', None) + if dh is not None: + opts.hyphenate = bool(dh) + wb = gprefs.get('lrf_viewer_white_background', None) + if wb is not None: + opts.white_background = bool(wb) return saved_opts diff --git a/src/calibre/utils/config_base.py b/src/calibre/utils/config_base.py index 6eae6234bb..da9f416a00 100644 --- a/src/calibre/utils/config_base.py +++ b/src/calibre/utils/config_base.py @@ -38,6 +38,13 @@ def to_json(obj): raise TypeError(repr(obj) + ' is not JSON serializable') +def safe_to_json(obj): + try: + return to_json(obj) + except Exception: + pass + + def from_json(obj): custom = obj.get('__class__') if custom is not None: @@ -52,9 +59,9 @@ def from_json(obj): return obj -def json_dumps(obj): +def json_dumps(obj, ignore_unserializable=False): import json - ans = json.dumps(obj, indent=2, default=to_json, sort_keys=True, ensure_ascii=False) + ans = json.dumps(obj, indent=2, default=safe_to_json if ignore_unserializable else to_json, sort_keys=True, ensure_ascii=False) if not isinstance(ans, bytes): ans = ans.encode('utf-8') return ans @@ -288,9 +295,9 @@ class OptionSet(object): return opts - def serialize(self, opts): + def serialize(self, opts, ignore_unserializable=False): data = {pref.name: getattr(opts, pref.name, pref.default) for pref in self.preferences} - return json_dumps(data) + return json_dumps(data, ignore_unserializable=ignore_unserializable) class ConfigInterface(object): @@ -351,7 +358,7 @@ class Config(ConfigInterface): migrate = bool(src) ans = self.option_set.parse_string(src) if migrate: - new_src = self.option_set.serialize(ans) + new_src = self.option_set.serialize(ans, ignore_unserializable=True) with ExclusiveFile(self.config_file_path) as f: f.seek(0), f.truncate() f.write(new_src)