diff --git a/src/calibre/ebooks/metadata/book/__init__.py b/src/calibre/ebooks/metadata/book/__init__.py index 00bbc68f29..38a824374c 100644 --- a/src/calibre/ebooks/metadata/book/__init__.py +++ b/src/calibre/ebooks/metadata/book/__init__.py @@ -131,8 +131,3 @@ SERIALIZABLE_FIELDS = SOCIAL_METADATA_FIELDS.union( frozenset(['device_collections', 'formats', 'cover_data']) # these are rebuilt when needed - -# A special set used to optimize the performance of Metadata.__setattr__ -ATTR_NORMAL_FIELDS = frozenset(STANDARD_METADATA_FIELDS - - TOP_LEVEL_IDENTIFIERS - - set('identifiers')) diff --git a/src/calibre/ebooks/metadata/book/base.py b/src/calibre/ebooks/metadata/book/base.py index 7aa675c85b..ce80486af8 100644 --- a/src/calibre/ebooks/metadata/book/base.py +++ b/src/calibre/ebooks/metadata/book/base.py @@ -9,17 +9,19 @@ import copy, traceback from calibre import prints from calibre.constants import DEBUG -from calibre.ebooks.metadata.book import SC_COPYABLE_FIELDS -from calibre.ebooks.metadata.book import SC_FIELDS_COPY_NOT_NULL -from calibre.ebooks.metadata.book import STANDARD_METADATA_FIELDS -from calibre.ebooks.metadata.book import TOP_LEVEL_IDENTIFIERS -from calibre.ebooks.metadata.book import ALL_METADATA_FIELDS -from calibre.ebooks.metadata.book import ATTR_NORMAL_FIELDS +from calibre.ebooks.metadata.book import (SC_COPYABLE_FIELDS, + SC_FIELDS_COPY_NOT_NULL, STANDARD_METADATA_FIELDS, + TOP_LEVEL_IDENTIFIERS, ALL_METADATA_FIELDS) from calibre.library.field_metadata import FieldMetadata from calibre.utils.date import isoformat, format_date from calibre.utils.icu import sort_key from calibre.utils.formatter import TemplateFormatter +# Special sets used to optimize the performance of getting and setting +# attributes on Metadata objects +SIMPLE_GET = frozenset(STANDARD_METADATA_FIELDS - TOP_LEVEL_IDENTIFIERS) +SIMPLE_SET = frozenset(SIMPLE_GET - {'identifiers'}) + def human_readable(size, precision=2): """ Convert a size in bytes into megabytes """ return ('%.'+str(precision)+'f'+ 'MB') % ((size/(1024.*1024.)),) @@ -137,7 +139,7 @@ class Metadata(object): def __getattribute__(self, field): _data = object.__getattribute__(self, '_data') - if field in ATTR_NORMAL_FIELDS: + if field in SIMPLE_GET: return _data.get(field, None) if field in TOP_LEVEL_IDENTIFIERS: return _data.get('identifiers').get(field, None) @@ -174,7 +176,7 @@ class Metadata(object): def __setattr__(self, field, val, extra=None): _data = object.__getattribute__(self, '_data') - if field in ATTR_NORMAL_FIELDS: + if field in SIMPLE_SET: if val is None: val = copy.copy(NULL_VALUES.get(field, None)) _data[field] = val diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index a80d21ebdc..bcc4b05399 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -911,7 +911,14 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): Note that the list of formats is not verified. ''' idx = idx if index_is_id else self.id(idx) - row = self.data._data[idx] + try: + row = self.data._data[idx] + except: + row = None + + if row is None: + raise ValueError('No book with id: %d'%idx) + fm = self.FIELD_MAP mi = Metadata(None, template_cache=self.formatter_template_cache) @@ -949,14 +956,13 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): mi.book_size = row[fm['size']] mi.ondevice_col= row[fm['ondevice']] mi.last_modified = row[fm['last_modified']] - id = idx formats = row[fm['formats']] mi.format_metadata = {} if not formats: good_formats = None else: formats = sorted(formats.split(',')) - mi.format_metadata = FormatMetadata(self, id, formats) + mi.format_metadata = FormatMetadata(self, idx, formats) good_formats = FormatsList(formats, mi.format_metadata) mi.formats = good_formats tags = row[fm['tags']] @@ -969,9 +975,9 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): if mi.series: mi.series_index = row[fm['series_index']] mi.rating = row[fm['rating']] - mi.set_identifiers(self.get_identifiers(id, index_is_id=True)) - mi.application_id = id - mi.id = id + mi.set_identifiers(self.get_identifiers(idx, index_is_id=True)) + mi.application_id = idx + mi.id = idx mi.set_all_user_metadata(self.field_metadata.custom_field_metadata()) for key, meta in self.field_metadata.custom_iteritems(): @@ -999,12 +1005,12 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): if get_cover: if cover_as_data: - cdata = self.cover(id, index_is_id=True) + cdata = self.cover(idx, index_is_id=True) if cdata: mi.cover_data = ('jpeg', cdata) else: - mi.cover = self.cover(id, index_is_id=True, as_path=True) - mi.has_cover = _('Yes') if self.has_cover(id) else '' + mi.cover = self.cover(idx, index_is_id=True, as_path=True) + mi.has_cover = _('Yes') if self.has_cover(idx) else '' return mi def has_book(self, mi):