Clean up previous PR

A few micro-optimizations in the loops checking for changed values.
And use suppress() to ignore exceptions
This commit is contained in:
Kovid Goyal 2021-09-14 08:58:26 +05:30
parent 38de7930c7
commit 27dcbfd8c5
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 23 additions and 30 deletions

View File

@ -1231,7 +1231,7 @@ class Cache(object):
v = sid = None v = sid = None
if sid is None and name.startswith('#'): if sid is None and name.startswith('#'):
sid = self._fast_field_for(sfield, k) 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 bimap[k] = v
if sid is not None: if sid is not None:
simap[k] = sid simap[k] = sid

View File

@ -18,6 +18,8 @@ from calibre.utils.date import (
from calibre.utils.localization import canonicalize_lang from calibre.utils.localization import canonicalize_lang
from calibre.utils.icu import strcmp from calibre.utils.icu import strcmp
missing = object()
# Convert data into values suitable for the db {{{ # 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 # We can't do this for the cover because the file might change without
# the presence-of-cover flag changing # the presence-of-cover flag changing
if field.name != 'cover': if field.name != 'cover':
book_id_val_map = {k:v for k, v in iteritems(book_id_val_map) g = field.table.book_col_map.get
if v != field.table.book_col_map.get(k, None)} 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: 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( db.executemany(
'UPDATE books SET %s=? WHERE id=?'%field.metadata['column'], sequence) 'UPDATE books SET %s=? WHERE id=?'%field.metadata['column'], sequence)
field.table.book_col_map.update(book_id_val_map) 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) ans = one_one_in_books(book_id_val_map, db, field, *args)
# Set the title sort field if the title changed # Set the title sort field if the title changed
field.title_sort_field.writer.set_books( 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 return ans
def one_one_in_other(book_id_val_map, db, field, *args): def one_one_in_other(book_id_val_map, db, field, *args):
'Set a one-one field in the non-books table, like comments' 'Set a one-one field in the non-books table, like comments'
# Ignore those items whose value is the same as the current value # 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) g = field.table.book_col_map.get
if v != field.table.book_col_map.get(k, None)} 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) deleted = tuple((k,) for k, v in iteritems(book_id_val_map) if v is None)
if deleted: if deleted:
db.executemany('DELETE FROM %s WHERE book=?'%field.metadata['table'], 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: if sidx is None:
sidx = 1.0 sidx = 1.0
if ids: 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])) sequence.append((sidx, book_id, ids[0]))
field.table.book_col_map[book_id] = sidx field.table.book_col_map[book_id] = sidx
else: 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) 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) 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 # 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) g = table.book_col_map.get
if v != table.book_col_map.get(k, tuple())} 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) dirtied |= set(book_id_item_id_map)
# Update the book->col and col->book maps # 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): # {{{ def identifiers(book_id_val_map, db, field, *args): # {{{
# Ignore those items whose value is the same as the current value # 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) g = field.table.book_col_map.get
if v != field.table.book_col_map.get(k, None)} book_id_val_map = {k:v for k, v in book_id_val_map.items() if v != g(k, missing)}
table = field.table table = field.table
updates = set() updates = set()

View File

@ -15,6 +15,7 @@ __docformat__ = 'restructuredtext en'
import inspect, re, traceback, numbers import inspect, re, traceback, numbers
from datetime import datetime, timedelta from datetime import datetime, timedelta
from math import trunc, floor, ceil, modf from math import trunc, floor, ceil, modf
from contextlib import suppress
from calibre import human_readable, prints from calibre import human_readable, prints
from calibre.constants import DEBUG from calibre.constants import DEBUG
@ -1266,12 +1267,10 @@ class BuiltinAnnotationCount(BuiltinFormatterFunction):
'This function works only in the GUI.') 'This function works only in the GUI.')
def evaluate(self, formatter, kwargs, mi, locals): def evaluate(self, formatter, kwargs, mi, locals):
try: with suppress(Exception):
from calibre.gui2.ui import get_gui from calibre.gui2.ui import get_gui
c = get_gui().current_db.new_api.annotation_count_for_book(mi.id) c = get_gui().current_db.new_api.annotation_count_for_book(mi.id)
return '' if c == 0 else unicode_type(c) return '' if c == 0 else unicode_type(c)
except:
pass
return _('This function can be used only in the GUI') 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.") "marks. Returns '' if the book is not marked.")
def evaluate(self, formatter, kwargs, mi, locals): def evaluate(self, formatter, kwargs, mi, locals):
try: with suppress(Exception):
from calibre.gui2.ui import get_gui from calibre.gui2.ui import get_gui
c = get_gui().current_db.data.get_marked(mi.id) c = get_gui().current_db.data.get_marked(mi.id)
return c if c else '' return c if c else ''
except:
pass
return _('This function can be used only in the GUI') 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') 'column\'s value in your save/send templates')
def evaluate(self, formatter, kwargs, mi, locals_): def evaluate(self, formatter, kwargs, mi, locals_):
try: with suppress(Exception):
from calibre.gui2.ui import get_gui from calibre.gui2.ui import get_gui
a = get_gui().current_db.data.get_virtual_libraries_for_books((mi.id,)) a = get_gui().current_db.data.get_virtual_libraries_for_books((mi.id,))
return ', '.join(a[mi.id]) return ', '.join(a[mi.id])
except:
pass
return _('This function can be used only in the GUI') 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.") "'carda' and 'cardb'. This function works only in the GUI.")
def evaluate(self, formatter, kwargs, mi, locals, storage_location): 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 # Do the import here so that we don't entangle the GUI when using
# command line functions # command line functions
from calibre.gui2.ui import get_gui from calibre.gui2.ui import get_gui
@ -1877,11 +1872,9 @@ class BuiltinConnectedDeviceName(BuiltinFormatterFunction):
if storage_location not in info: if storage_location not in info:
return '' return ''
return info[storage_location]['device_name'] return info[storage_location]['device_name']
except: except Exception:
traceback.print_exc() traceback.print_exc()
raise raise
except:
pass
return _('This function can be used only in the GUI') return _('This function can be used only in the GUI')
@ -1897,7 +1890,7 @@ class BuiltinConnectedDeviceUUID(BuiltinFormatterFunction):
"the GUI.") "the GUI.")
def evaluate(self, formatter, kwargs, mi, locals, storage_location): 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 # Do the import here so that we don't entangle the GUI when using
# command line functions # command line functions
from calibre.gui2.ui import get_gui from calibre.gui2.ui import get_gui
@ -1913,11 +1906,9 @@ class BuiltinConnectedDeviceUUID(BuiltinFormatterFunction):
if storage_location not in info: if storage_location not in info:
return '' return ''
return info[storage_location]['device_store_uuid'] return info[storage_location]['device_store_uuid']
except: except Exception:
traceback.print_exc() traceback.print_exc()
raise raise
except:
pass
return _('This function can be used only in the GUI') return _('This function can be used only in the GUI')