diff --git a/src/calibre/db/cache.py b/src/calibre/db/cache.py index bb2fe6c94e..77471abae0 100644 --- a/src/calibre/db/cache.py +++ b/src/calibre/db/cache.py @@ -1231,7 +1231,7 @@ class Cache(object): v = sid = None if sid is None and name.startswith('#'): sid = self._fast_field_for(sfield, k) - sid = 1.0 if sid is None else sid # The value to be set the db link table + sid = 1.0 if sid is None else sid # The value to be set the db link table bimap[k] = v if sid is not None: simap[k] = sid diff --git a/src/calibre/db/write.py b/src/calibre/db/write.py index de0166339a..285460a333 100644 --- a/src/calibre/db/write.py +++ b/src/calibre/db/write.py @@ -18,6 +18,8 @@ from calibre.utils.date import ( from calibre.utils.localization import canonicalize_lang from calibre.utils.icu import strcmp +missing = object() + # Convert data into values suitable for the db {{{ @@ -196,10 +198,10 @@ def one_one_in_books(book_id_val_map, db, field, *args): # We can't do this for the cover because the file might change without # the presence-of-cover flag changing if field.name != 'cover': - book_id_val_map = {k:v for k, v in iteritems(book_id_val_map) - if v != field.table.book_col_map.get(k, None)} + g = field.table.book_col_map.get + book_id_val_map = {k:v for k, v in book_id_val_map.items() if v != g(k, missing)} if book_id_val_map: - sequence = ((sqlite_datetime(v), k) for k, v in iteritems(book_id_val_map)) + sequence = ((sqlite_datetime(v), k) for k, v in book_id_val_map.items()) db.executemany( 'UPDATE books SET %s=? WHERE id=?'%field.metadata['column'], sequence) field.table.book_col_map.update(book_id_val_map) @@ -215,15 +217,15 @@ def set_title(book_id_val_map, db, field, *args): ans = one_one_in_books(book_id_val_map, db, field, *args) # Set the title sort field if the title changed field.title_sort_field.writer.set_books( - {k:title_sort(v) for k, v in iteritems(book_id_val_map) if k in ans}, db) + {k:title_sort(v) for k, v in book_id_val_map.items() if k in ans}, db) return ans def one_one_in_other(book_id_val_map, db, field, *args): 'Set a one-one field in the non-books table, like comments' # Ignore those items whose value is the same as the current value - book_id_val_map = {k:v for k, v in iteritems(book_id_val_map) - if v != field.table.book_col_map.get(k, None)} + g = field.table.book_col_map.get + book_id_val_map = {k:v for k, v in iteritems(book_id_val_map) if v != g(k, missing)} deleted = tuple((k,) for k, v in iteritems(book_id_val_map) if v is None) if deleted: db.executemany('DELETE FROM %s WHERE book=?'%field.metadata['table'], @@ -247,7 +249,7 @@ def custom_series_index(book_id_val_map, db, field, *args): if sidx is None: sidx = 1.0 if ids: - if field.table.book_col_map.get(book_id, None) != sidx: + if field.table.book_col_map.get(book_id, missing) != sidx: sequence.append((sidx, book_id, ids[0])) field.table.book_col_map[book_id] = sidx else: @@ -433,11 +435,11 @@ def many_many(book_id_val_map, db, field, allow_case_change, *args): field.author_sort_field.writer.set_books({book_id:new_sort}, db) book_id_item_id_map = {k:tuple(val_map[v] for v in vals) - for k, vals in iteritems(book_id_val_map)} + for k, vals in book_id_val_map.items()} # Ignore those items whose value is the same as the current value - book_id_item_id_map = {k:v for k, v in iteritems(book_id_item_id_map) - if v != table.book_col_map.get(k, tuple())} + g = table.book_col_map.get + book_id_item_id_map = {k:v for k, v in book_id_item_id_map.items() if v != g(k, missing)} dirtied |= set(book_id_item_id_map) # Update the book->col and col->book maps @@ -495,8 +497,8 @@ def many_many(book_id_val_map, db, field, allow_case_change, *args): def identifiers(book_id_val_map, db, field, *args): # {{{ # Ignore those items whose value is the same as the current value - book_id_val_map = {k:v for k, v in iteritems(book_id_val_map) - if v != field.table.book_col_map.get(k, None)} + g = field.table.book_col_map.get + book_id_val_map = {k:v for k, v in book_id_val_map.items() if v != g(k, missing)} table = field.table updates = set() diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index 7e8f149379..214efbf3fc 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -15,6 +15,7 @@ __docformat__ = 'restructuredtext en' import inspect, re, traceback, numbers from datetime import datetime, timedelta from math import trunc, floor, ceil, modf +from contextlib import suppress from calibre import human_readable, prints from calibre.constants import DEBUG @@ -1266,12 +1267,10 @@ class BuiltinAnnotationCount(BuiltinFormatterFunction): 'This function works only in the GUI.') def evaluate(self, formatter, kwargs, mi, locals): - try: + with suppress(Exception): from calibre.gui2.ui import get_gui c = get_gui().current_db.new_api.annotation_count_for_book(mi.id) return '' if c == 0 else unicode_type(c) - except: - pass return _('This function can be used only in the GUI') @@ -1285,12 +1284,10 @@ class BuiltinIsMarked(BuiltinFormatterFunction): "marks. Returns '' if the book is not marked.") def evaluate(self, formatter, kwargs, mi, locals): - try: + with suppress(Exception): from calibre.gui2.ui import get_gui c = get_gui().current_db.data.get_marked(mi.id) return c if c else '' - except: - pass return _('This function can be used only in the GUI') @@ -1758,12 +1755,10 @@ class BuiltinVirtualLibraries(BuiltinFormatterFunction): 'column\'s value in your save/send templates') def evaluate(self, formatter, kwargs, mi, locals_): - try: + with suppress(Exception): from calibre.gui2.ui import get_gui a = get_gui().current_db.data.get_virtual_libraries_for_books((mi.id,)) return ', '.join(a[mi.id]) - except: - pass return _('This function can be used only in the GUI') @@ -1861,7 +1856,7 @@ class BuiltinConnectedDeviceName(BuiltinFormatterFunction): "'carda' and 'cardb'. This function works only in the GUI.") def evaluate(self, formatter, kwargs, mi, locals, storage_location): - try: + with suppress(Exception): # Do the import here so that we don't entangle the GUI when using # command line functions from calibre.gui2.ui import get_gui @@ -1877,11 +1872,9 @@ class BuiltinConnectedDeviceName(BuiltinFormatterFunction): if storage_location not in info: return '' return info[storage_location]['device_name'] - except: + except Exception: traceback.print_exc() raise - except: - pass return _('This function can be used only in the GUI') @@ -1897,7 +1890,7 @@ class BuiltinConnectedDeviceUUID(BuiltinFormatterFunction): "the GUI.") def evaluate(self, formatter, kwargs, mi, locals, storage_location): - try: + with suppress(Exception): # Do the import here so that we don't entangle the GUI when using # command line functions from calibre.gui2.ui import get_gui @@ -1913,11 +1906,9 @@ class BuiltinConnectedDeviceUUID(BuiltinFormatterFunction): if storage_location not in info: return '' return info[storage_location]['device_store_uuid'] - except: + except Exception: traceback.print_exc() raise - except: - pass return _('This function can be used only in the GUI')