Bug #2049992: unknown function when referencing stored template "function" in epub:save_to_disk plugboard template

The comments in Saver.__init__ are there in case there is some reason to not remove the load_user_template_functions() call. They can be removed.
This commit is contained in:
Charles Haley 2024-01-21 14:38:34 +00:00
parent 779183f71a
commit 1ce6a63a62
2 changed files with 16 additions and 5 deletions

View File

@ -26,7 +26,6 @@ from calibre.library.save_to_disk import (
) )
from calibre.ptempfile import PersistentTemporaryDirectory, SpooledTemporaryFile from calibre.ptempfile import PersistentTemporaryDirectory, SpooledTemporaryFile
from calibre.utils.filenames import make_long_path_useable from calibre.utils.filenames import make_long_path_useable
from calibre.utils.formatter_functions import load_user_template_functions
from calibre.utils.ipc.pool import Failure, Pool from calibre.utils.ipc.pool import Failure, Pool
from polyglot.builtins import iteritems, itervalues from polyglot.builtins import iteritems, itervalues
from polyglot.queue import Empty from polyglot.queue import Empty
@ -80,7 +79,13 @@ class Saver(QObject):
self.db = db.new_api self.db = db.new_api
self.plugboards = self.db.pref('plugboards', {}) self.plugboards = self.db.pref('plugboards', {})
self.template_functions = self.db.pref('user_template_functions', []) self.template_functions = self.db.pref('user_template_functions', [])
load_user_template_functions('', self.template_functions) self.library_id = self.db.library_id
# This call to load_user_template_functions isn't needed because
# __init__ is running on the GUI thread. It must be done in the separate
# process by the worker
# from calibre.gui2 import is_gui_thread
# print(f'Saver __init__ is_gui_thread: {is_gui_thread()}')
# load_user_template_functions('', self.template_functions)
self.collected_data = {} self.collected_data = {}
self.errors = defaultdict(list) self.errors = defaultdict(list)
self._book_id_data = {} self._book_id_data = {}
@ -111,7 +116,8 @@ class Saver(QObject):
if self.pool is not None: if self.pool is not None:
self.pool.shutdown() self.pool.shutdown()
self.setParent(None) self.setParent(None)
self.jobs = self.pool = self.plugboards = self.template_functions = self.collected_data = self.all_book_ids = self.pd = self.db = None # noqa self.jobs = self.pool = self.plugboards = self.template_functions = self.library_id =\
self.collected_data = self.all_book_ids = self.pd = self.db = None # noqa
self.deleteLater() self.deleteLater()
def book_id_data(self, book_id): def book_id_data(self, book_id):
@ -155,7 +161,9 @@ class Saver(QObject):
plugboards_cache = {fmt:find_plugboard(plugboard_save_to_disk_value, fmt, self.plugboards) for fmt in all_fmts} plugboards_cache = {fmt:find_plugboard(plugboard_save_to_disk_value, fmt, self.plugboards) for fmt in all_fmts}
self.pool = Pool(name='SaveToDisk') if self.pool is None else self.pool self.pool = Pool(name='SaveToDisk') if self.pool is None else self.pool
try: try:
self.pool.set_common_data(plugboards_cache) self.pool.set_common_data({'plugboard_cache': plugboards_cache,
'template_functions': self.template_functions,
'library_id': self.library_id})
except Failure as err: except Failure as err:
error_dialog(self.pd, _('Critical failure'), _( error_dialog(self.pd, _('Critical failure'), _(
'Could not save books to disk, click "Show details" for more information'), 'Could not save books to disk, click "Show details" for more information'),

View File

@ -20,6 +20,7 @@ from calibre.utils.filenames import (
ascii_filename, make_long_path_useable, shorten_components_to, ascii_filename, make_long_path_useable, shorten_components_to,
) )
from calibre.utils.formatter import TemplateFormatter from calibre.utils.formatter import TemplateFormatter
from calibre.utils.formatter_functions import load_user_template_functions
from calibre.utils.localization import _ from calibre.utils.localization import _
plugboard_any_device_value = 'any device' plugboard_any_device_value = 'any device'
@ -439,8 +440,10 @@ def read_serialized_metadata(data):
def update_serialized_metadata(book, common_data=None): def update_serialized_metadata(book, common_data=None):
# This is called from a worker process. It must not open the database.
result = [] result = []
plugboard_cache = common_data plugboard_cache = common_data['plugboard_cache']
load_user_template_functions(common_data['library_id'], common_data['template_functions'])
from calibre.customize.ui import apply_null_metadata from calibre.customize.ui import apply_null_metadata
with apply_null_metadata: with apply_null_metadata:
fmts = [fp.rpartition(os.extsep)[-1] for fp in book['fmts']] fmts = [fp.rpartition(os.extsep)[-1] for fp in book['fmts']]