Add format_metadata to get_metadata using a cache. Add formatter functions to deal with the information.

This commit is contained in:
Charles Haley 2011-06-30 18:09:18 +01:00
parent 42de0d5ff3
commit 23307b3aa5
2 changed files with 52 additions and 2 deletions

View File

@ -8,6 +8,7 @@ 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, tempfile, hashlib json, uuid, tempfile, hashlib
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
@ -487,6 +488,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
self.refresh_ondevice = functools.partial(self.data.refresh_ondevice, self) self.refresh_ondevice = functools.partial(self.data.refresh_ondevice, self)
self.refresh() self.refresh()
self.last_update_check = self.last_modified() self.last_update_check = self.last_modified()
self.format_metadata_cache = defaultdict(dict)
def break_cycles(self): def break_cycles(self):
self.data.break_cycles() self.data.break_cycles()
@ -914,11 +916,15 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
mi.book_size = row[fm['size']] mi.book_size = row[fm['size']]
mi.ondevice_col= row[fm['ondevice']] mi.ondevice_col= row[fm['ondevice']]
mi.last_modified = row[fm['last_modified']] mi.last_modified = row[fm['last_modified']]
id = idx if index_is_id else self.id(idx)
formats = row[fm['formats']] formats = row[fm['formats']]
mi.format_metadata = {}
if not formats: if not formats:
formats = None formats = None
else: else:
formats = formats.split(',') formats = formats.split(',')
for f in formats:
mi.format_metadata[f] = self.format_metadata(id, f, allow_cache=True)
mi.formats = formats mi.formats = formats
tags = row[fm['tags']] tags = row[fm['tags']]
if tags: if tags:
@ -927,7 +933,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
if mi.series: if mi.series:
mi.series_index = row[fm['series_index']] mi.series_index = row[fm['series_index']]
mi.rating = row[fm['rating']] mi.rating = row[fm['rating']]
id = idx if index_is_id else self.id(idx)
mi.set_identifiers(self.get_identifiers(id, index_is_id=True)) mi.set_identifiers(self.get_identifiers(id, index_is_id=True))
mi.application_id = id mi.application_id = id
mi.id = id mi.id = id
@ -1126,13 +1131,16 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
if m: if m:
return m['mtime'] return m['mtime']
def format_metadata(self, id_, fmt): def format_metadata(self, id_, fmt, allow_cache=True):
if allow_cache and fmt in self.format_metadata_cache.get(id_, {}):
return self.format_metadata_cache[id_][fmt]
path = self.format_abspath(id_, fmt, index_is_id=True) path = self.format_abspath(id_, fmt, index_is_id=True)
ans = {} ans = {}
if path is not None: if path is not None:
stat = os.stat(path) stat = os.stat(path)
ans['size'] = stat.st_size ans['size'] = stat.st_size
ans['mtime'] = utcfromtimestamp(stat.st_mtime) ans['mtime'] = utcfromtimestamp(stat.st_mtime)
self.format_metadata_cache[id_][fmt] = ans
return ans return ans
def format_hash(self, id_, fmt): def format_hash(self, id_, fmt):
@ -1254,6 +1262,11 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
ret.name = f.name ret.name = f.name
else: else:
ret = f.read() ret = f.read()
try:
self.format_metadata(index if index_is_id else self.id(index),
format, allow_cache=False)
except:
traceback.print_exc()
return ret return ret
def add_format_with_hooks(self, index, format, fpath, index_is_id=False, def add_format_with_hooks(self, index, format, fpath, index_is_id=False,

View File

@ -519,6 +519,41 @@ class BuiltinSelect(BuiltinFormatterFunction):
return v[len(key)+1:] return v[len(key)+1:]
return '' return ''
class BuiltinFormatsModtimes(BuiltinFormatterFunction):
name = 'formats_modtimes'
arg_count = 0
category = 'Get values from metadata'
__doc__ = doc = _('formats_modtimes() -- return a comma-separated list of '
'colon_separated items representing modification times '
'for the formats of a book. You can use the select '
'function to get the mod time for a specific '
'format. Note that format names are always uppercase, '
'as in EPUB.'
)
def evaluate(self, formatter, kwargs, mi, locals):
fmt_data = mi.get('format_metadata', {})
print fmt_data
return ','.join(k.upper()+':'+format_date(v['mtime'], 'iso')
for k,v in fmt_data.iteritems())
class BuiltinFormatsSizes(BuiltinFormatterFunction):
name = 'formats_sizes'
arg_count = 0
category = 'Get values from metadata'
__doc__ = doc = _('formats_sizes() -- return a comma-separated list of '
'colon_separated items representing sizes '
'of the formats of a book. You can use the select '
'function to get the size for a specific '
'format. Note that format names are always uppercase, '
'as in EPUB.'
)
def evaluate(self, formatter, kwargs, mi, locals):
fmt_data = mi.get('format_metadata', {})
print fmt_data
return ','.join(k.upper()+':'+str(v['size']) for k,v in fmt_data.iteritems())
class BuiltinSublist(BuiltinFormatterFunction): class BuiltinSublist(BuiltinFormatterFunction):
name = 'sublist' name = 'sublist'
arg_count = 4 arg_count = 4
@ -814,6 +849,8 @@ builtin_eval = BuiltinEval()
builtin_first_non_empty = BuiltinFirstNonEmpty() builtin_first_non_empty = BuiltinFirstNonEmpty()
builtin_field = BuiltinField() builtin_field = BuiltinField()
builtin_format_date = BuiltinFormatDate() builtin_format_date = BuiltinFormatDate()
builtin_formats_modt= BuiltinFormatsModtimes()
builtin_formats_size= BuiltinFormatsSizes()
builtin_identifier_in_list = BuiltinIdentifierInList() builtin_identifier_in_list = BuiltinIdentifierInList()
builtin_ifempty = BuiltinIfempty() builtin_ifempty = BuiltinIfempty()
builtin_in_list = BuiltinInList() builtin_in_list = BuiltinInList()