Alternate implementation that makes the decision about composite columns in user_categories_for_books().

This commit is contained in:
Charles Haley 2014-10-24 18:35:53 +02:00
parent e90d22da9e
commit 77abf61f8e
3 changed files with 68 additions and 14 deletions

View File

@ -1901,6 +1901,32 @@ class Cache(object):
ans[book].append(lib)
return {k:tuple(sorted(v, key=sort_key)) for k, v in ans.iteritems()}
@read_api
def user_categories_for_book(self, book_id, proxy_metadata):
user_cats = self.backend.prefs['user_categories']
user_cat_vals = {}
for ucat in user_cats:
res = []
for name,cat,ign in user_cats[ucat]:
try:
field_obj = self.fields[cat]
except KeyError:
continue
if field_obj.is_composite:
v = field_obj.get_value_with_cache(book_id, lambda x:proxy_metadata)
else:
v = self._fast_field_for(field_obj, book_id)
if isinstance(v, (list, tuple)):
if name in v:
res.append([name,cat])
elif name == v:
res.append([name,cat])
user_cat_vals[ucat] = res
return user_cat_vals
@write_api
def embed_metadata(self, book_ids, only_fmts=None, report_error=None, report_progress=None):
''' Update metadata in all formats of the specified book_ids to current metadata in the database. '''

View File

@ -107,7 +107,7 @@ ga = object.__getattribute__
sa = object.__setattr__
def simple_getter(field, default_value=None):
def func(dbref, book_id, cache):
def func(dbref, book_id, cache, proxy_metadata):
try:
return cache[field]
except KeyError:
@ -117,7 +117,7 @@ def simple_getter(field, default_value=None):
return func
def pp_getter(field, postprocess, default_value=None):
def func(dbref, book_id, cache):
def func(dbref, book_id, cache, proxy_metadata):
try:
return cache[field]
except KeyError:
@ -127,7 +127,7 @@ def pp_getter(field, postprocess, default_value=None):
return func
def adata_getter(field):
def func(dbref, book_id, cache):
def func(dbref, book_id, cache, proxy_metadata):
try:
author_ids, adata = cache['adata']
except KeyError:
@ -141,7 +141,7 @@ def adata_getter(field):
return func
def dt_getter(field):
def func(dbref, book_id, cache):
def func(dbref, book_id, cache, proxy_metadata):
try:
return cache[field]
except KeyError:
@ -151,7 +151,7 @@ def dt_getter(field):
return func
def item_getter(field, default_value=None, key=0):
def func(dbref, book_id, cache):
def func(dbref, book_id, cache, proxy_metadata):
try:
return cache[field]
except KeyError:
@ -164,7 +164,7 @@ def item_getter(field, default_value=None, key=0):
return func
def fmt_getter(field):
def func(dbref, book_id, cache):
def func(dbref, book_id, cache, proxy_metadata):
try:
format_metadata = cache['format_metadata']
except KeyError:
@ -179,7 +179,7 @@ def fmt_getter(field):
return format_metadata
return func
def approx_fmts_getter(dbref, book_id, cache):
def approx_fmts_getter(dbref, book_id, cache, proxy_metadata):
try:
return cache['formats']
except KeyError:
@ -188,9 +188,9 @@ def approx_fmts_getter(dbref, book_id, cache):
return ret
def series_index_getter(field='series'):
def func(dbref, book_id, cache):
def func(dbref, book_id, cache, proxy_metadata):
try:
series = getters[field](dbref, book_id, cache)
series = getters[field](dbref, book_id, cache, proxy_metadata)
except KeyError:
series = custom_getter(field, dbref, book_id, cache)
if series:
@ -202,7 +202,7 @@ def series_index_getter(field='series'):
return ret
return func
def has_cover_getter(dbref, book_id, cache):
def has_cover_getter(dbref, book_id, cache, proxy_metadata):
try:
return cache['has_cover']
except KeyError:
@ -232,7 +232,7 @@ def composite_getter(mi, field, metadata, book_id, cache, formatter, template_ca
template_cache=template_cache).strip()
return ret
def virtual_libraries_getter(dbref, book_id, cache):
def virtual_libraries_getter(dbref, book_id, cache, proxy_metadata):
try:
return cache['virtual_libraries']
except KeyError:
@ -241,6 +241,16 @@ def virtual_libraries_getter(dbref, book_id, cache):
ret = cache['virtual_libraries'] = ', '.join(vls)
return ret
def user_categories_getter(dbref, book_id, cache, proxy_metadata):
try:
return cache['user_categories']
except KeyError:
db = dbref()
cache['user_categories'] = {}
val = db.user_categories_for_book(book_id, proxy_metadata)
ret = cache['user_categories'] = val
return ret
getters = {
'title':simple_getter('title', _('Unknown')),
'title_sort':simple_getter('sort', _('Unknown')),
@ -258,6 +268,7 @@ getters = {
'application_id':lambda x, book_id, y: book_id,
'id':lambda x, book_id, y: book_id,
'virtual_libraries':virtual_libraries_getter,
'user_categories':user_categories_getter,
}
for field in ('comments', 'publisher', 'identifiers', 'series', 'rating'):
@ -283,13 +294,13 @@ class ProxyMetadata(Metadata):
sa(self, 'formatter', SafeFormat() if formatter is None else formatter)
sa(self, '_db', weakref.ref(db))
sa(self, '_book_id', book_id)
sa(self, '_cache', {'user_categories':{}, 'cover_data':(None,None), 'device_collections':[]})
sa(self, '_cache', {'cover_data':(None,None), 'device_collections':[]})
sa(self, '_user_metadata', db.field_metadata)
def __getattribute__(self, field):
getter = getters.get(field, None)
if getter is not None:
return getter(ga(self, '_db'), ga(self, '_book_id'), ga(self, '_cache'))
return getter(ga(self, '_db'), ga(self, '_book_id'), ga(self, '_cache'), self)
if field in SIMPLE_GET:
return ga(self, '_cache').get(field, None)
try:

View File

@ -1397,6 +1397,23 @@ class BuiltinVirtualLibraries(BuiltinFormatterFunction):
return mi._proxy_metadata.virtual_libraries
return _('This function can be used only in the GUI')
class BuiltinUserCategories(BuiltinFormatterFunction):
name = 'user_categories'
arg_count = 0
category = 'Get values from metadata'
__doc__ = doc = _('user_categories() -- return a comma-separated list of '
'the user categories that contain this book. This function '
'works only in the GUI. If you want to use these values '
'in save-to-disk or send-to-device templates then you '
'must make a custom "Column built from other columns", use '
'the function in that column\'s template, and use that '
'column\'s value in your save/send templates')
def evaluate(self, formatter, kwargs, mi, locals_):
if hasattr(mi, '_proxy_metadata'):
return ', '.join(k for (k, v) in mi._proxy_metadata.user_categories.items() if v)
return _('This function can be used only in the GUI')
class BuiltinTransliterate(BuiltinFormatterFunction):
name = 'transliterate'
arg_count = 1
@ -1480,7 +1497,7 @@ _formatter_builtins = [
BuiltinSublist(),BuiltinSubstr(), BuiltinSubtract(), BuiltinSwapAroundComma(),
BuiltinSwitch(), BuiltinTemplate(), BuiltinTest(), BuiltinTitlecase(),
BuiltinToday(), BuiltinTransliterate(), BuiltinUppercase(),
BuiltinVirtualLibraries()
BuiltinUserCategories(), BuiltinVirtualLibraries()
]
class FormatterUserFunction(FormatterFunction):