I saved this PTM template in Preferences > Template Functions:
The globals dict was of course empty since it gets filled at runtime, so an error message about the key, 'val', missing was spurious. I still was able to save & apply the PTM template.
I then ran the above PTM template in a plugin's Job using this code:
Code:
funcobject = user_template_functions['daltonst1']
func_name = funcobject.name
formatter = TemplateFormatter()
formatter.funcs.update(formatter_functions()._functions_from_library)
ptc = PythonTemplateContext()
ptc.funcs = formatter_functions()._functions_from_library
if func_name in ptc.funcs:
func = ptc.funcs[func_name]
elif func_name in formatter.funcs:
func = formatter.funcs[func_name]
else:
func = funcobject
ptc.func = func
ptc.func_name = func_name
ptc.name = func_name
ptc.globals = {}
ptc.globals['val'] = "ABCDEFGHIJK9999999999MNOPQRSTUVWXYZ"
ptc.arguments = ""
ptc.db = guidb
mi = guidb.new_api.get_metadata(current_book)
ptc.book = mi
ptc.formatter = formatter
formatter.python_context_object = ptc
formatter.func = func
formatter.func_name = func_name
formatter.name = func_name
formatter.db = guidb
formatter.mi = mi
formatter.book = mi
formatter.kwargs = None
ffc = FormatterFuncsCaller(formatter)
call = ffc.__getattribute__(func_name)
output_text = call(formatter.python_context_object)
The debug log for the above Job shows:
I went back into where I saved this PTM template in Preferences > Template Functions to work on the same PTM template, but the GUI raised the error shown below, and would not let me back into Preferences > Template Functions to work on the PTM template to fix the error (Catch-22):
Spoiler:
calibre, version 6.10.0
ERROR: Unhandled exception: <b>AttributeError</b>:'list' object has no attribute 'object_type'
calibre 6.10 embedded-python: True
Windows-10-10.0.22621-SP0 Windows ('64bit', 'WindowsPE')
('Windows', '10', '10.0.22621')
Python 3.10.1
Windows: ('10', '10.0.22621', 'SP0', 'Multiprocessor Free')
Interface language: None
Successfully initialized third party plugins: Audit Log (1, 0, 18) && Author Book Count (2, 2, 2) && Author Book Count Hierarchy (1, 2, 3) && CalibreSpy (1, 0, 90) && Consolidate All Library Metadata (2, 0, 43) && Drop Search Results (1, 0, 13) && English Noun Frequency (1, 0, 15) && Entities Manager (1, 0, 18) && Extract People Other Metadata (1, 0, 0) && Extract RIS Citations (1, 0, 5) && Favourites Menu (1, 3, 0) && Job Spy (1, 0, 197) && Library Codes (1, 0, 53) && Library Splitter (1, 0, 6) && Media File Importer (1, 0, 26) && MultiColumnSearch (1, 0, 95) && QuarantineAndScrub (3, 6, 119) && Save Composite Custom Columns (1, 1, 1) && View Manager (1, 10, 2) && Zotero Metadata Importer (1, 0, 77)
Traceback (most recent call last):
File "calibre\gui2\preferences\main.py", line 308, in show_plugin
File "calibre\customize\__init__.py", line 675, in create_widget
File "calibre\gui2\preferences\__init__.py", line 267, in __init__
File "calibre\gui2\preferences\template_functions_ui.py ", line 31, in setupUi
File "calibre\gui2\dialogs\template_dialog.py", line 1090, in __init__
File "calibre\gui2\dialogs\template_dialog.py", line 453, in __init__
File "calibre\gui2\dialogs\template_dialog.py", line 858, in function_type_string
AttributeError: 'list' object has no attribute 'object_type'
Since I could not use Preferences > Template Functions any more, at all, I went into metadata.db, table Preferences, key 'user_template_functions', and carved out the entry for my PTM template from the JSON:
I then ran Calibre, and could finally enter into Preferences > Template Functions since the PTM template in question no longer existed.
----------------------------------------------------------------------------------------------
Question: Can the PTM template cache get poisoned when the PTM template is run "in batch" via a Job? If so, is there a way to clear it so the template_dialog for Preferences > Template Functions can always be successfully executed?
Question: How do I create a PTM template using a dict with keys that only exist at runtime?
Question: Is this syntax supported: text = context.globals['val'] ? If not, what is the proper way to accomplish passing a single string value to a PTM template at runtime?
Thank you.
Happy/Merry Christmas.
DaltonST