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
'''
import os, sys, shutil, cStringIO, glob, time, functools, traceback, re, \
json, uuid, hashlib, copy, weakref
from collections import defaultdict, MutableMapping, MutableSequence
json, uuid, hashlib, copy
from collections import defaultdict
import threading, random
from itertools import repeat
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.formatter_functions import load_user_template_functions
from calibre.db.errors import NoSuchFormat
from calibre.db.lazy import FormatMetadata, FormatsList
from calibre.utils.localization import (canonicalize_lang,
calibre_langcode_to_name)
@ -81,110 +82,6 @@ class Tag(object):
def __repr__(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):
'''
An ebook metadata database that stores references to ebook files on disk.