diff --git a/src/calibre/gui2/save.py b/src/calibre/gui2/save.py index 584c64d353..6be6703b0e 100644 --- a/src/calibre/gui2/save.py +++ b/src/calibre/gui2/save.py @@ -26,7 +26,6 @@ from calibre.library.save_to_disk import ( ) from calibre.ptempfile import PersistentTemporaryDirectory, SpooledTemporaryFile 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 polyglot.builtins import iteritems, itervalues from polyglot.queue import Empty @@ -80,7 +79,13 @@ class Saver(QObject): self.db = db.new_api self.plugboards = self.db.pref('plugboards', {}) 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.errors = defaultdict(list) self._book_id_data = {} @@ -111,7 +116,8 @@ class Saver(QObject): if self.pool is not None: self.pool.shutdown() 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() 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} self.pool = Pool(name='SaveToDisk') if self.pool is None else self.pool 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: error_dialog(self.pd, _('Critical failure'), _( 'Could not save books to disk, click "Show details" for more information'), diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py index e844d23b74..8e652a2c6a 100644 --- a/src/calibre/library/save_to_disk.py +++ b/src/calibre/library/save_to_disk.py @@ -20,6 +20,7 @@ from calibre.utils.filenames import ( ascii_filename, make_long_path_useable, shorten_components_to, ) from calibre.utils.formatter import TemplateFormatter +from calibre.utils.formatter_functions import load_user_template_functions from calibre.utils.localization import _ plugboard_any_device_value = 'any device' @@ -439,8 +440,10 @@ def read_serialized_metadata(data): def update_serialized_metadata(book, common_data=None): + # This is called from a worker process. It must not open the database. 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 with apply_null_metadata: fmts = [fp.rpartition(os.extsep)[-1] for fp in book['fmts']]