Nicer implementation of the mutable classes

This commit is contained in:
Kovid Goyal 2012-01-17 23:55:30 +05:30
parent d749690e79
commit 2f4941613c
2 changed files with 97 additions and 106 deletions

94
src/calibre/db/lazy.py Normal file
View File

@ -0,0 +1,94 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import (unicode_literals, division, absolute_import,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import weakref
from functools import wraps
from collections import MutableMapping, MutableSequence
def resolved(f):
@wraps(f)
def wrapper(self, *args, **kwargs):
if getattr(self, '_must_resolve', True):
self._must_resolve = False
self._resolve()
return f(self, *args, **kwargs)
return wrapper
class MutableBaseMixin(object): # {{{
@resolved
def __str__(self):
return str(self.values)
@resolved
def __repr__(self):
return repr(self.values)
@resolved
def __unicode__(self):
return unicode(self.values)
@resolved
def __len__(self):
return len(self.values)
@resolved
def __iter__(self):
return iter(self.values)
@resolved
def __contains__(self, key):
return key in self.values
@resolved
def __getitem__(self, fmt):
return self.values[fmt]
@resolved
def __setitem__(self, key, val):
self.values[key] = val
@resolved
def __delitem__(self, key):
del self.values[key]
# }}}
class FormatMetadata(MutableBaseMixin, MutableMapping): # {{{
def __init__(self, db, id_, formats):
self.dbwref = weakref.ref(db)
self.id_ = id_
self.formats = formats
self.values = {}
def _resolve(self):
db = self.dbwref()
for f in self.formats:
try:
self.values[f] = db.format_metadata(self.id_, f)
except:
pass
class FormatsList(MutableBaseMixin, MutableSequence):
def __init__(self, formats, format_metadata):
self.formats = formats
self.format_metadata = format_metadata
self.values = []
def _resolve(self):
self.values = [f for f in self.formats if f in self.format_metadata]
def insert(self, idx, val):
self._resolve()
self.values.insert(idx, val)
# }}}

View File

@ -7,8 +7,8 @@ __docformat__ = 'restructuredtext en'
The database used to store ebook metadata The database used to store ebook metadata
''' '''
import os, sys, shutil, cStringIO, glob, time, functools, traceback, re, \ import os, sys, shutil, cStringIO, glob, time, functools, traceback, re, \
json, uuid, hashlib, copy, weakref json, uuid, hashlib, copy
from collections import defaultdict, MutableMapping, MutableSequence from collections import defaultdict
import threading, random import threading, random
from itertools import repeat from itertools import repeat
from math import ceil from math import ceil
@ -40,6 +40,7 @@ from calibre.utils.magick.draw import save_cover_data_to
from calibre.utils.recycle_bin import delete_file, delete_tree from calibre.utils.recycle_bin import delete_file, delete_tree
from calibre.utils.formatter_functions import load_user_template_functions from calibre.utils.formatter_functions import load_user_template_functions
from calibre.db.errors import NoSuchFormat from calibre.db.errors import NoSuchFormat
from calibre.db.lazy import FormatMetadata, FormatsList
from calibre.utils.localization import (canonicalize_lang, from calibre.utils.localization import (canonicalize_lang,
calibre_langcode_to_name) calibre_langcode_to_name)
@ -81,110 +82,6 @@ class Tag(object):
def __repr__(self): def __repr__(self):
return str(self) return str(self)
class MutablePrintMixin(object): # {{{
def __str__(self):
self._resolve()
return str(self.values)
def __repr__(self):
self._resolve()
return repr(self.values)
def __unicode__(self):
self._resolve()
return unicode(self.values)
# }}}
class FormatMetadata(MutableMapping, MutablePrintMixin): # {{{
def __init__(self, db, id_, formats):
self.dbwref = weakref.ref(db)
self.id_ = id_
self.formats = formats
self._must_do = True
self.values = {}
def _resolve(self):
if self._must_do:
self._must_do = False
db = self.dbwref()
for f in self.formats:
try:
self.values[f] = db.format_metadata(self.id_, f)
except:
pass
def __contains__(self, key):
self._resolve()
return key in self.values
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, MutablePrintMixin):
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:
self._must_do = False
for f in self.formats:
try:
if f in self.format_metadata:
self.values.append(f)
except:
pass
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): class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
''' '''
An ebook metadata database that stores references to ebook files on disk. An ebook metadata database that stores references to ebook files on disk.