mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
commit
3cec1c5f30
@ -220,11 +220,10 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
def commit(self):
|
def commit(self):
|
||||||
# formatter_functions().reset_to_builtins()
|
# formatter_functions().reset_to_builtins()
|
||||||
pref_value = []
|
pref_value = []
|
||||||
for f in self.funcs:
|
for name, cls in self.funcs.iteritems():
|
||||||
func = self.funcs[f]
|
if name not in self.builtins:
|
||||||
pref_value.append((func.name, func.doc, func.arg_count, func.program_text))
|
pref_value.append((cls.name, cls.doc, cls.arg_count, cls.program_text))
|
||||||
self.db.prefs.set('user_template_functions', pref_value)
|
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)
|
load_user_template_functions(self.db.library_id, pref_value)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
import inspect, re, traceback
|
import inspect, re, traceback
|
||||||
from math import trunc
|
from math import trunc
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
from calibre import human_readable
|
from calibre import human_readable
|
||||||
from calibre.constants import DEBUG
|
from calibre.constants import DEBUG
|
||||||
@ -23,10 +22,16 @@ from calibre.utils.localization import calibre_langcode_to_name, canonicalize_la
|
|||||||
|
|
||||||
class FormatterFunctions(object):
|
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):
|
def __init__(self):
|
||||||
self._builtins = {}
|
self._builtins = {}
|
||||||
self._functions = {}
|
self._functions = {}
|
||||||
self._functions_from_library = defaultdict(list)
|
self._functions_from_library = {}
|
||||||
|
|
||||||
def register_builtin(self, func_class):
|
def register_builtin(self, func_class):
|
||||||
if not isinstance(func_class, FormatterFunction):
|
if not isinstance(func_class, FormatterFunction):
|
||||||
@ -40,7 +45,7 @@ class FormatterFunctions(object):
|
|||||||
for a in func_class.aliases:
|
for a in func_class.aliases:
|
||||||
self._functions[a] = func_class
|
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):
|
if not isinstance(func_class, FormatterFunction):
|
||||||
raise ValueError('Class %s is not an instance of FormatterFunction'%(
|
raise ValueError('Class %s is not an instance of FormatterFunction'%(
|
||||||
func_class.__class__.__name__))
|
func_class.__class__.__name__))
|
||||||
@ -48,16 +53,36 @@ class FormatterFunctions(object):
|
|||||||
if not replace and name in self._functions:
|
if not replace and name in self._functions:
|
||||||
raise ValueError('Name %s already used'%name)
|
raise ValueError('Name %s already used'%name)
|
||||||
self._functions[name] = func_class
|
self._functions[name] = func_class
|
||||||
self._functions_from_library[library_uuid].append(name)
|
|
||||||
|
|
||||||
def function_exists(self, name):
|
def register_functions(self, library_uuid, funcs):
|
||||||
return self._functions.get(name, None)
|
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):
|
def unregister_functions(self, library_uuid):
|
||||||
if library_uuid in self._functions_from_library:
|
if library_uuid in self._functions_from_library:
|
||||||
for name in self._functions_from_library[library_uuid]:
|
for cls in self._functions_from_library[library_uuid]:
|
||||||
self._functions.pop(name)
|
self._functions.pop(cls.name, None)
|
||||||
self._functions_from_library.pop(library_uuid)
|
self._functions_from_library.pop(library_uuid)
|
||||||
|
self._register_functions()
|
||||||
|
|
||||||
def get_builtins(self):
|
def get_builtins(self):
|
||||||
return self._builtins
|
return self._builtins
|
||||||
@ -1271,15 +1296,11 @@ class UserFunction(FormatterUserFunction):
|
|||||||
cls = locals_['UserFunction'](name, doc, arg_count, eval_func)
|
cls = locals_['UserFunction'](name, doc, arg_count, eval_func)
|
||||||
return cls
|
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):
|
def load_user_template_functions(library_uuid, funcs):
|
||||||
unload_user_template_functions(library_uuid)
|
unload_user_template_functions(library_uuid)
|
||||||
|
|
||||||
|
compiled_funcs = []
|
||||||
for func in funcs:
|
for func in funcs:
|
||||||
try:
|
try:
|
||||||
# Force a name conflict to test the logic
|
# 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
|
# source. This helps ensure that if the function already is defined
|
||||||
# then white space differences don't cause them to compare differently
|
# then white space differences don't cause them to compare differently
|
||||||
|
|
||||||
cls = compile_user_function(*func)
|
compiled_funcs.append(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)
|
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
formatter_functions().register_functions(library_uuid, compiled_funcs)
|
||||||
|
|
||||||
def unload_user_template_functions(library_uuid):
|
def unload_user_template_functions(library_uuid):
|
||||||
formatter_functions().unregister_functions(library_uuid)
|
formatter_functions().unregister_functions(library_uuid)
|
Loading…
x
Reference in New Issue
Block a user