Tests for the new formatter db functions, and fixes for the errors that the tests found.

I left in the code I used to select specific tests. Yank it out if you don't want it.
This commit is contained in:
Charles Haley 2022-07-04 13:47:31 +01:00
parent f34ab14e78
commit 173f6644e6
2 changed files with 109 additions and 4 deletions

View File

@ -745,3 +745,97 @@ class ReadingTest(BaseTest):
val = val.encode('utf-8') val = val.encode('utf-8')
self.assertEqual(got, val) self.assertEqual(got, val)
# }}} # }}}
def test_template_db_functions(self): # {{{
from calibre.ebooks.metadata.book.base import Metadata
from calibre.ebooks.metadata.book.formatter import SafeFormat
formatter = SafeFormat()
db = self.init_cache(self.library_path)
db.create_custom_column('mult', 'CC1', 'composite', True, display={'composite_template': 'b,a,c'})
db = self.init_legacy(self.library_path)
class GetGuiAns():
current_db = None
get_gui_ans = GetGuiAns()
get_gui_ans.current_db = db
from calibre.gui2.ui import get_gui
get_gui.ans = get_gui_ans
try:
# need an empty metadata object to pass to the formatter
mi = Metadata('A', 'B')
# test counting books matching the search
v = formatter.safe_format('program: book_count("series:true", 0)', {}, 'TEMPLATE ERROR', mi)
self.assertEqual(v, '2')
# test counting books when none match the search
v = formatter.safe_format('program: book_count("series:afafaf", 0)', {}, 'TEMPLATE ERROR', mi)
self.assertEqual(v, '0')
# test is_multiple values
v = formatter.safe_format('program: book_values("tags", "tags:true", ",", 0)', {}, 'TEMPLATE ERROR', mi)
self.assertEqual(set(v.split(',')), {'Tag One', 'News', 'Tag Two'})
# test not is_multiple values
v = formatter.safe_format('program: book_values("series", "series:true", ",", 0)', {}, 'TEMPLATE ERROR', mi)
self.assertEqual(v, 'A Series One')
# test returning values for a column not searched for
v = formatter.safe_format('program: book_values("tags", "series:\\"A Series One\\"", ",", 0)', {}, 'TEMPLATE ERROR', mi)
self.assertEqual(set(v.split(',')), {'Tag One', 'News', 'Tag Two'})
# test getting a singleton value from books where the column is empty
v = formatter.safe_format('program: book_values("series", "series:false", ",", 0)', {}, 'TEMPLATE ERROR', mi)
self.assertEqual(v, '')
# test getting a multiple value from books where the column is empty
v = formatter.safe_format('program: book_values("tags", "tags:false", ",", 0)', {}, 'TEMPLATE ERROR', mi)
self.assertEqual(v, '')
# test fetching an unknown column
v = formatter.safe_format('program: book_values("taaags", "tags:false", ",", 0)', {}, 'TEMPLATE ERROR', mi)
self.assertEqual(v, "TEMPLATE ERROR The column taaags doesn't exist")
# test finding all books
v = formatter.safe_format('program: book_values("id", "title:true", ",", 0)', {}, 'TEMPLATE ERROR', mi)
self.assertEqual(set(v.split(',')), {'1', '2', '3'})
# test getting value of a composite
v = formatter.safe_format('program: book_values("#mult", "id:1", ",", 0)', {}, 'TEMPLATE ERROR', mi)
self.assertEqual(set(v.split(',')), {'b', 'c', 'a'})
# test getting value of a custom float
v = formatter.safe_format('program: book_values("#float", "title:true", ",", 0)', {}, 'TEMPLATE ERROR', mi)
self.assertEqual(set(v.split(',')), {'20.02', '10.01'})
# test getting value of an int (rating)
v = formatter.safe_format('program: book_values("rating", "title:true", ",", 0)', {}, 'TEMPLATE ERROR', mi)
self.assertEqual(set(v.split(',')), {'4', '6'})
finally:
get_gui.ans = None
# }}}
import unittest, importlib, sys
from calibre.utils.run_tests import run_tests, filter_tests_by_name
if __name__ == '__main__':
try:
import init_calibre # noqa
except ImportError:
pass
tests = sys.argv[1:]
sys.argv = sys.argv[0:1]
def find_tests():
m = importlib.import_module('calibre.db.tests.reading')
suite = unittest.TestSuite([unittest.defaultTestLoader.loadTestsFromModule(m)])
if tests:
return filter_tests_by_name(suite, *tests)
else:
return suite
run_tests(find_tests)

View File

@ -2265,14 +2265,25 @@ class BuiltinBookValues(BuiltinFormatterFunction):
if (not tweaks.get('allow_template_database_functions_in_composites', False) and if (not tweaks.get('allow_template_database_functions_in_composites', False) and
formatter.global_vars.get(rendering_composite_name, None)): formatter.global_vars.get(rendering_composite_name, None)):
raise ValueError(_('The book_values() function cannot be used in a composite column')) raise ValueError(_('The book_values() function cannot be used in a composite column'))
with suppress(Exception): try:
from calibre.gui2.ui import get_gui from calibre.gui2.ui import get_gui
db = get_gui().current_db db = get_gui().current_db
ids = db.search_getting_ids(query, None, use_virtual_library=use_vl != '0') except:
ff = db.new_api.field_for
s = {ff(column, id_) for id_ in ids if ff(column, id_)}
return sep.join(s)
return _('This function can be used only in the GUI') return _('This function can be used only in the GUI')
if column not in db.field_metadata:
raise ValueError(_("The column {} doesn't exist").format(column))
try:
ids = db.search_getting_ids(query, None, use_virtual_library=use_vl != '0')
s = set()
for id_ in ids:
f = db.new_api.get_proxy_metadata(id_).get(column, None)
if isinstance(f, (tuple, list)):
s.update(f)
elif f:
s.add(str(f))
return sep.join(s)
except Exception as e:
raise ValueError(e)
_formatter_builtins = [ _formatter_builtins = [