mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
1) Fix silly regression in template_functions preference that caused all functions to be added to the custom function preference.
2) Change function registration and deregistration to restore function bodies if the name conflict goes away.
This commit is contained in:
parent
e7777df9ae
commit
8a5c71f36a
@ -220,11 +220,10 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
def commit(self):
|
||||
# formatter_functions().reset_to_builtins()
|
||||
pref_value = []
|
||||
for f in self.funcs:
|
||||
func = self.funcs[f]
|
||||
pref_value.append((func.name, func.doc, func.arg_count, func.program_text))
|
||||
for name, cls in self.funcs.iteritems():
|
||||
if name not in self.builtins:
|
||||
pref_value.append((cls.name, cls.doc, cls.arg_count, cls.program_text))
|
||||
self.db.prefs.set('user_template_functions', pref_value)
|
||||
formatter_functions().unregister_functions(self.db.library_id)
|
||||
load_user_template_functions(self.db.library_id, pref_value)
|
||||
return False
|
||||
|
||||
|
@ -10,7 +10,6 @@ __docformat__ = 'restructuredtext en'
|
||||
|
||||
import inspect, re, traceback
|
||||
from math import trunc
|
||||
from collections import defaultdict
|
||||
|
||||
from calibre import human_readable
|
||||
from calibre.constants import DEBUG
|
||||
@ -23,10 +22,16 @@ from calibre.utils.localization import calibre_langcode_to_name, canonicalize_la
|
||||
|
||||
class FormatterFunctions(object):
|
||||
|
||||
error_function_body = ('def evaluate(self, formatter, kwargs, mi, locals):\n'
|
||||
'\treturn "' +
|
||||
_('Duplicate user function name {0}. '
|
||||
'Change the name or ensure that the functions are identical')
|
||||
+ '"')
|
||||
|
||||
def __init__(self):
|
||||
self._builtins = {}
|
||||
self._functions = {}
|
||||
self._functions_from_library = defaultdict(list)
|
||||
self._functions_from_library = {}
|
||||
|
||||
def register_builtin(self, func_class):
|
||||
if not isinstance(func_class, FormatterFunction):
|
||||
@ -40,7 +45,7 @@ class FormatterFunctions(object):
|
||||
for a in func_class.aliases:
|
||||
self._functions[a] = func_class
|
||||
|
||||
def register_function(self, library_uuid, func_class, replace=False):
|
||||
def _register_function(self, func_class, replace=False):
|
||||
if not isinstance(func_class, FormatterFunction):
|
||||
raise ValueError('Class %s is not an instance of FormatterFunction'%(
|
||||
func_class.__class__.__name__))
|
||||
@ -48,16 +53,36 @@ class FormatterFunctions(object):
|
||||
if not replace and name in self._functions:
|
||||
raise ValueError('Name %s already used'%name)
|
||||
self._functions[name] = func_class
|
||||
self._functions_from_library[library_uuid].append(name)
|
||||
|
||||
def function_exists(self, name):
|
||||
return self._functions.get(name, None)
|
||||
def register_functions(self, library_uuid, funcs):
|
||||
self._functions_from_library[library_uuid] = funcs
|
||||
self._register_functions()
|
||||
|
||||
def _register_functions(self):
|
||||
for compiled_funcs in self._functions_from_library.itervalues():
|
||||
for cls in compiled_funcs:
|
||||
f = self._functions.get(cls.name, None)
|
||||
replace = False
|
||||
if f is not None:
|
||||
existing_body = f.program_text
|
||||
new_body = cls.program_text
|
||||
if new_body != existing_body:
|
||||
# Change the body of the template function to one that will
|
||||
# return an error message. Also change the arg count to
|
||||
# -1 (variable) to avoid template compilation errors
|
||||
replace = True
|
||||
func = [cls.name, '', -1, self.error_function_body.format(cls.name)]
|
||||
cls = compile_user_function(*func)
|
||||
else:
|
||||
continue
|
||||
formatter_functions()._register_function(cls, replace=replace)
|
||||
|
||||
def unregister_functions(self, library_uuid):
|
||||
if library_uuid in self._functions_from_library:
|
||||
for name in self._functions_from_library[library_uuid]:
|
||||
self._functions.pop(name)
|
||||
for cls in self._functions_from_library[library_uuid]:
|
||||
self._functions.pop(cls.name, None)
|
||||
self._functions_from_library.pop(library_uuid)
|
||||
self._register_functions()
|
||||
|
||||
def get_builtins(self):
|
||||
return self._builtins
|
||||
@ -1271,15 +1296,11 @@ class UserFunction(FormatterUserFunction):
|
||||
cls = locals_['UserFunction'](name, doc, arg_count, eval_func)
|
||||
return cls
|
||||
|
||||
error_function_body = ('def evaluate(self, formatter, kwargs, mi, locals):\n'
|
||||
'\treturn "' +
|
||||
_('Duplicate user function name {0}. '
|
||||
'Change the name or ensure that the functions are identical')
|
||||
+ '"')
|
||||
|
||||
def load_user_template_functions(library_uuid, funcs):
|
||||
unload_user_template_functions(library_uuid)
|
||||
|
||||
compiled_funcs = []
|
||||
for func in funcs:
|
||||
try:
|
||||
# Force a name conflict to test the logic
|
||||
@ -1290,26 +1311,10 @@ def load_user_template_functions(library_uuid, funcs):
|
||||
# source. This helps ensure that if the function already is defined
|
||||
# then white space differences don't cause them to compare differently
|
||||
|
||||
cls = compile_user_function(*func)
|
||||
f = formatter_functions().function_exists(cls.name)
|
||||
replace = False
|
||||
if f is not None:
|
||||
existing_body = f.program_text
|
||||
new_body = cls.program_text
|
||||
if new_body != existing_body:
|
||||
# Change the body of the template function to one that will
|
||||
# return an error message. Also change the arg count to
|
||||
# -1 (variable) to avoid template compilation errors
|
||||
replace = True
|
||||
func[3] = error_function_body.format(func[0])
|
||||
func[2] = -1
|
||||
cls = compile_user_function(*func)
|
||||
else:
|
||||
continue
|
||||
|
||||
formatter_functions().register_function(library_uuid, cls, replace=replace)
|
||||
compiled_funcs.append(compile_user_function(*func))
|
||||
except:
|
||||
traceback.print_exc()
|
||||
formatter_functions().register_functions(library_uuid, compiled_funcs)
|
||||
|
||||
def unload_user_template_functions(library_uuid):
|
||||
formatter_functions().unregister_functions(library_uuid)
|
Loading…
x
Reference in New Issue
Block a user