diff --git a/src/calibre/db/backend.py b/src/calibre/db/backend.py index 27d0c09d52..8800b47885 100644 --- a/src/calibre/db/backend.py +++ b/src/calibre/db/backend.py @@ -152,8 +152,11 @@ class DBPrefs(dict): # {{{ def write_serialized(self, library_path): try: to_filename = os.path.join(library_path, 'metadata_db_prefs_backup.json') + data = json.dumps(self, indent=2, default=to_json) + if not isinstance(data, bytes): + data = data.encode('utf-8') with open(to_filename, "wb") as f: - f.write(json.dumps(self, indent=2, default=to_json)) + f.write(data) except: import traceback traceback.print_exc() diff --git a/src/calibre/db/categories.py b/src/calibre/db/categories.py index cc6ea00dd8..d073a2d5f1 100644 --- a/src/calibre/db/categories.py +++ b/src/calibre/db/categories.py @@ -75,7 +75,7 @@ class Tag(object): def find_categories(field_metadata): - for category, cat in iteritems(field_metadata): + for category, cat in field_metadata.iter_items(): if (cat['is_category'] and cat['kind'] not in {'user', 'search'}): yield (category, cat['is_multiple'].get('cache_to_list', None), False) elif (cat['datatype'] == 'composite' and diff --git a/src/calibre/db/search.py b/src/calibre/db/search.py index 594ffde15c..7463a11ef9 100644 --- a/src/calibre/db/search.py +++ b/src/calibre/db/search.py @@ -632,7 +632,7 @@ class Parser(SearchQueryParser): # {{{ text_fields = set() field_metadata = {} - for x, fm in iteritems(self.field_metadata): + for x, fm in self.field_metadata.iter_items(): if x.startswith('@'): continue if fm['search_terms'] and x not in {'series_sort', 'id'}: diff --git a/src/calibre/devices/usbms/driver.py b/src/calibre/devices/usbms/driver.py index c475800ab3..22aa18a6b5 100644 --- a/src/calibre/devices/usbms/driver.py +++ b/src/calibre/devices/usbms/driver.py @@ -128,13 +128,19 @@ class USBMS(CLI, Device): driveinfo = None driveinfo = self._update_driveinfo_record(driveinfo, prefix, location_code, name) + data = json.dumps(driveinfo, default=to_json) + if not isinstance(data, bytes): + data = data.encode('utf-8') with lopen(os.path.join(prefix, self.DRIVEINFO), 'wb') as f: - f.write(json.dumps(driveinfo, default=to_json)) + f.write(data) fsync(f) else: driveinfo = self._update_driveinfo_record({}, prefix, location_code, name) + data = json.dumps(driveinfo, default=to_json) + if not isinstance(data, bytes): + data = data.encode('utf-8') with lopen(os.path.join(prefix, self.DRIVEINFO), 'wb') as f: - f.write(json.dumps(driveinfo, default=to_json)) + f.write(data) fsync(f) return driveinfo diff --git a/src/calibre/ebooks/metadata/book/json_codec.py b/src/calibre/ebooks/metadata/book/json_codec.py index 46027c03c0..8bef9a9e25 100644 --- a/src/calibre/ebooks/metadata/book/json_codec.py +++ b/src/calibre/ebooks/metadata/book/json_codec.py @@ -132,8 +132,10 @@ class JsonCodec(object): self.field_metadata = field_metadata or FieldMetadata() def encode_to_file(self, file_, booklist): - file_.write(json.dumps(self.encode_booklist_metadata(booklist), - indent=2, encoding='utf-8')) + data = json.dumps(self.encode_booklist_metadata(booklist), indent=2, encoding='utf-8') + if not isinstance(data, bytes): + data = data.encode('utf-8') + file_.write(data) def encode_booklist_metadata(self, booklist): result = [] diff --git a/src/calibre/gui2/dialogs/plugin_updater.py b/src/calibre/gui2/dialogs/plugin_updater.py index cfcddde0e1..b3a09de848 100644 --- a/src/calibre/gui2/dialogs/plugin_updater.py +++ b/src/calibre/gui2/dialogs/plugin_updater.py @@ -45,7 +45,7 @@ def get_plugin_updates_available(raise_error=False): return None display_plugins = read_available_plugins(raise_error=raise_error) if display_plugins: - update_plugins = filter(filter_upgradeable_plugins, display_plugins) + update_plugins = list(filter(filter_upgradeable_plugins, display_plugins)) if len(update_plugins) > 0: return update_plugins return None @@ -589,7 +589,7 @@ class PluginUpdaterDialog(SizePersistedDialog): def _finished(self, *args): if self.model: - update_plugins = filter(filter_upgradeable_plugins, self.model.display_plugins) + update_plugins = list(filter(filter_upgradeable_plugins, self.model.display_plugins)) self.gui.recalc_update_label(len(update_plugins)) def _plugin_current_changed(self, current, previous): diff --git a/src/calibre/gui2/dialogs/search.py b/src/calibre/gui2/dialogs/search.py index 0a3ebd278a..b764b09ad3 100644 --- a/src/calibre/gui2/dialogs/search.py +++ b/src/calibre/gui2/dialogs/search.py @@ -19,7 +19,7 @@ from calibre.utils.icu import sort_key from calibre.utils.config import tweaks from calibre.utils.date import now from calibre.utils.localization import localize_user_manual_link -from polyglot.builtins import iteritems, unicode_type, range +from polyglot.builtins import unicode_type, range box_values = {} last_matchkind = CONTAINS_MATCH @@ -174,7 +174,7 @@ def create_date_tab(self, db): w.h1 = h = QHBoxLayout() l.addLayout(h) self.date_field = df = add(_("&Search the"), QComboBox(w)) - vals = [((v['search_terms'] or [k])[0], v['name'] or k) for k, v in iteritems(db.field_metadata) if v.get('datatype', None) == 'datetime'] + vals = [((v['search_terms'] or [k])[0], v['name'] or k) for k, v in db.field_metadata.iter_items() if v.get('datatype', None) == 'datetime'] for k, v in sorted(vals, key=lambda k_v: sort_key(k_v[1])): df.addItem(v, k) h.addWidget(df) diff --git a/src/calibre/gui2/library/delegates.py b/src/calibre/gui2/library/delegates.py index 7c91eaec3b..b5192b280f 100644 --- a/src/calibre/gui2/library/delegates.py +++ b/src/calibre/gui2/library/delegates.py @@ -202,7 +202,7 @@ def get_val_for_textlike_columns(index_): class RatingDelegate(QStyledItemDelegate, UpdateEditorGeometry): # {{{ def __init__(self, *args, **kwargs): - QStyledItemDelegate.__init__(self, *args, **kwargs) + QStyledItemDelegate.__init__(self, *args) self.is_half_star = kwargs.get('is_half_star', False) self.table_widget = args[0] self.rf = QFont(rating_font()) diff --git a/src/calibre/gui2/preferences/coloring.py b/src/calibre/gui2/preferences/coloring.py index 43aa34edd1..96216b7bf7 100644 --- a/src/calibre/gui2/preferences/coloring.py +++ b/src/calibre/gui2/preferences/coloring.py @@ -1090,8 +1090,11 @@ class EditRules(QWidget): # {{{ 'type': self.model.pref_name, 'rules': self.model.rules_as_list(for_export=True) } + data = json.dumps(rules, indent=2) + if not isinstance(data, bytes): + data = data.encode('utf-8') with lopen(path, 'wb') as f: - f.write(json.dumps(rules, indent=2)) + f.write(data) def import_rules(self): files = choose_files(self, 'import-coloring-rules', _('Choose file to import from'), diff --git a/src/calibre/gui2/threaded_jobs.py b/src/calibre/gui2/threaded_jobs.py index aef553133d..e58808993d 100644 --- a/src/calibre/gui2/threaded_jobs.py +++ b/src/calibre/gui2/threaded_jobs.py @@ -129,9 +129,11 @@ class ThreadedJob(BaseJob): if not os.path.exists(log_dir): os.makedirs(log_dir) fd, path = tempfile.mkstemp(suffix='.json', prefix='log-', dir=log_dir) + data = json.dumps(logs, ensure_ascii=False, indent=2) + if not isinstance(data, bytes): + data = data.encode('utf-8') with os.fdopen(fd, 'wb') as f: - f.write(json.dumps(logs, ensure_ascii=False, - indent=2).encode('utf-8')) + f.write(data) self.consolidated_log = path self.log = None diff --git a/src/calibre/gui2/viewer/bookmarkmanager.py b/src/calibre/gui2/viewer/bookmarkmanager.py index 3b81f80eaf..2452c9e678 100644 --- a/src/calibre/gui2/viewer/bookmarkmanager.py +++ b/src/calibre/gui2/viewer/bookmarkmanager.py @@ -200,8 +200,11 @@ class BookmarkManager(QWidget): self, 'export-viewer-bookmarks', _('Export bookmarks'), filters=[(_('Saved bookmarks'), ['calibre-bookmarks'])], all_files=False, initial_filename='bookmarks.calibre-bookmarks') if filename: + data = json.dumps(self.get_bookmarks(), indent=True) + if not isinstance(data, bytes): + data = data.encode('utf-8') with lopen(filename, 'wb') as fileobj: - fileobj.write(json.dumps(self.get_bookmarks(), indent=True)) + fileobj.write(data) def import_bookmarks(self): files = choose_files(self, 'export-viewer-bookmarks', _('Import bookmarks'), diff --git a/src/calibre/library/field_metadata.py b/src/calibre/library/field_metadata.py index 523f322521..27a6d29d6f 100644 --- a/src/calibre/library/field_metadata.py +++ b/src/calibre/library/field_metadata.py @@ -493,13 +493,14 @@ class FieldMetadata(object): def iteritems(self): for key in self._tb_cats: yield (key, self._tb_cats[key]) + iter_items = iteritems def custom_iteritems(self): for key, meta in iteritems(self._tb_custom_fields): yield (key, meta) def items(self): - return list(iteritems(self)) + return list(self.iter_items()) def is_custom_field(self, key): return key.startswith(self.custom_field_prefix) diff --git a/src/calibre/library/prefs.py b/src/calibre/library/prefs.py index 3c41a4d78f..9ef2214da8 100644 --- a/src/calibre/library/prefs.py +++ b/src/calibre/library/prefs.py @@ -81,8 +81,11 @@ class DBPrefs(dict): def write_serialized(self, library_path): try: to_filename = os.path.join(library_path, 'metadata_db_prefs_backup.json') + data = json.dumps(self, indent=2, default=to_json) + if not isinstance(data, bytes): + data = data.encode('utf-8') with open(to_filename, "wb") as f: - f.write(json.dumps(self, indent=2, default=to_json)) + f.write(data) except: import traceback traceback.print_exc() diff --git a/src/calibre/srv/render_book.py b/src/calibre/srv/render_book.py index 1bac7c4082..407c457889 100644 --- a/src/calibre/srv/render_book.py +++ b/src/calibre/srv/render_book.py @@ -230,8 +230,11 @@ class Container(ContainerBase): self.commit() for name in excluded_names: os.remove(self.name_path_map[name]) + data = json.dumps(self.book_render_data, ensure_ascii=False) + if not isinstance(data, bytes): + data = data.encode('utf-8') with lopen(os.path.join(self.root, 'calibre-book-manifest.json'), 'wb') as f: - f.write(json.dumps(self.book_render_data, ensure_ascii=False).encode('utf-8')) + f.write(data) def create_cover_page(self, input_fmt): templ = '''