From 319fb366bf8ed1a59270e321721562e8c50b18a0 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 17 Jan 2012 10:52:22 +0100 Subject: [PATCH] Performance improvement: evaluate formats and format_metadata returned by get_metadata on demand. If the values aren't used in a template or in displaying the information, the timestamps are not retrieved. --- src/calibre/library/database2.py | 95 +++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 9 deletions(-) diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 1bbbf2405b..b1ccb069b0 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -8,7 +8,7 @@ The database used to store ebook metadata ''' import os, sys, shutil, cStringIO, glob, time, functools, traceback, re, \ json, uuid, hashlib, copy -from collections import defaultdict +from collections import defaultdict, MutableMapping, MutableSequence import threading, random from itertools import repeat from math import ceil @@ -81,6 +81,89 @@ class Tag(object): def __repr__(self): return str(self) +class FormatMetadata(MutableMapping): # {{{ + + def __init__(self, db, id_, formats): + self.db = db + self.id_ = id_ + self.formats = formats + self._must_do = True + self.values = {} + + def _resolve(self): + if self._must_do: + for f in self.formats: + try: + self.values[f] = self.db.format_metadata(self.id_, f) + except: + pass + self._must_do = False + + def __getitem__(self, fmt): + self._resolve() + return self.values[fmt] + + def __setitem__(self, key, val): + self._resolve() + self.values[key] = val + + def __delitem__(self, key): + self._resolve() + self.values.__delitem__(key) + + def __len__(self): + self._resolve() + return len(self.values) + + def __iter__(self): + self._resolve() + return self.values.__iter__() + +class FormatsList(MutableSequence): + + def __init__(self, formats, format_metadata): + self.formats = formats + self.format_metadata = format_metadata + self._must_do = True + self.values = [] + + def _resolve(self): + if self._must_do: + for f in self.formats: + try: + if f in self.format_metadata: + self.values.append(f) + except: + pass + self._must_do = False + + def __getitem__(self, dex): + self._resolve() + return self.values[dex] + + def __setitem__(self, key, dex): + self._resolve() + self.values[key] = dex + + def __delitem__(self, dex): + self._resolve() + self.values.__delitem__(dex) + + def __len__(self): + self._resolve() + return len(self.values) + + def __iter__(self): + self._resolve() + return self.values.__iter__() + + def insert(self, idx, val): + self._resolve() + self.values.insert(idx, val) + +# }}} + + class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): ''' @@ -944,14 +1027,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): good_formats = None else: formats = sorted(formats.split(',')) - good_formats = [] - for f in formats: - try: - mi.format_metadata[f] = self.format_metadata(id, f) - except: - pass - else: - good_formats.append(f) + mi.format_metadata = FormatMetadata(self, id, formats) + good_formats = FormatsList(formats, mi.format_metadata) mi.formats = good_formats tags = row[fm['tags']] if tags: