Quote:
Originally Posted by Montana Harper
One question, though: is there any way to modify that template to iterate over all the authors for a given title? That would be the absolute ideal solution for me.

|
This template checks every value for a field in a book. If the field is "authors" then it checks every author.
Code:
python:
def evaluate(book, context):
if context.arguments is None or len(context.arguments) != 2:
# Set these to what you want
field_name = 'authors'
value_in_note = 'note'
else:
field_name = context.arguments[0]
value_in_note = context.arguments[1]
db = context.db.new_api
# check if we have already cached the notes
note_items = context.globals.get('items_with_notes', None)
if note_items is not None:
# We've already fetched which items have notes.
# Get the cached search result values
note_search_results = context.globals['note_search_results']
item_name_map = context.globals['item_name_map']
else:
# First time. Get the items with notes and initialize
# the search value cache.
note_items = db.get_all_items_that_have_notes(field_name)
context.globals['items_with_notes'] = note_items
note_search_results = {}
context.globals['note_search_results'] = note_search_results
# db.get_item_id() uses a linear search. Avoid this by getting
# and caching the map
item_name_map = db.get_item_name_map(field_name)
context.globals['item_name_map'] = item_name_map
# Check if this book is a match -- that the field has a note containing
# the desired text.
# We must first get the item_id for the value in the field to be checked.
field_values = book.get(field_name)
if not field_values:
return ''
# We want to check every value in the item, so use a list.
# If the given field is not multi-valued, turn it into a list
if not isinstance(field_values, (tuple, list, set)):
field_values = (field_values,)
# Loop over the field values, checking each one. Stop on first success
result = ''
for field_value in field_values:
# Get the cached internal ID of the value in field_name
item_id = item_name_map[field_value]
# Does the item have a note? If not, give up now.
if item_id not in note_items:
continue
# The item has a note. Have we already checked it?
result = note_search_results.get(item_id)
if result is not None:
# We've already checked this item.
if result:
# It matched. Break out of the loop
break
# It didn't match. Check the next item
continue
# Item has a note but we haven't seen it before. Do the compare
# on the plain text version of the note.
# Get the note.
note = db.notes_data_for(field_name, item_id)
if note:
# Get the plain text of the note.
note = note['searchable_text'].partition('\n')[2]
if note:
# use a case insensitive compare to check if the search value is in the note
from calibre.utils.icu import primary_contains
result = 'Yes' if primary_contains(value_in_note, note) else ''
# Cache the result of the comparison
note_search_results[item_id] = result
if result:
break
# Cache the updated results
context.globals['note_search_results'] = note_search_results
return result