From c8f566dfb8fe57ffff325d522289d3d092781160 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Thu, 2 May 2013 19:47:44 +0200 Subject: [PATCH 1/4] Delay instantiating all the formatter function classes --- src/calibre/utils/formatter_functions.py | 72 +++++++++++++++--------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index 67c75bdc79..dc60738394 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -10,6 +10,7 @@ __docformat__ = 'restructuredtext en' import inspect, re, traceback from math import trunc +from threading import RLock from calibre import human_readable from calibre.constants import DEBUG @@ -25,6 +26,15 @@ class FormatterFunctions(object): def __init__(self): self._builtins = {} self._functions = {} + self._lock = RLock() + self._loaded = False + + def load_builtins(self): + with self._lock: + if not self._loaded: + self._loaded = True + for c in _formatter_builtins: + c() def register_builtin(self, func_class): if not isinstance(func_class, FormatterFunction): @@ -39,6 +49,7 @@ class FormatterFunctions(object): self._functions[a] = func_class def register_function(self, func_class): + self.load_builtins() if not isinstance(func_class, FormatterFunction): raise ValueError('Class %s is not an instance of FormatterFunction'%( func_class.__class__.__name__)) @@ -48,9 +59,11 @@ class FormatterFunctions(object): self._functions[name] = func_class def get_builtins(self): + self.load_builtins() return self._builtins def get_builtins_and_aliases(self): + self.load_builtins() res = {} for f in self._builtins.itervalues(): res[f.name] = f @@ -59,10 +72,12 @@ class FormatterFunctions(object): return res def get_functions(self): + self.load_builtins() return self._functions def reset_to_builtins(self): self._functions = {} + self.load_builtins() for n,c in self._builtins.items(): self._functions[n] = c for a in c.aliases: @@ -1210,27 +1225,27 @@ class BuiltinFinishFormatting(BuiltinFormatterFunction): return prefix + formatter._do_format(val, fmt) + suffix _formatter_builtins = [ - BuiltinAdd(), BuiltinAnd(), BuiltinApproximateFormats(), - BuiltinAssign(), BuiltinBooksize(), - BuiltinCapitalize(), BuiltinCmp(), BuiltinContains(), BuiltinCount(), - BuiltinCurrentLibraryName(), BuiltinCurrentLibraryPath(), - BuiltinDaysBetween(), BuiltinDivide(), BuiltinEval(), BuiltinFirstNonEmpty(), - BuiltinField(), BuiltinFinishFormatting(), BuiltinFormatDate(), - BuiltinFormatNumber(), BuiltinFormatsModtimes(), BuiltinFormatsPaths(), - BuiltinFormatsSizes(), - BuiltinHasCover(), BuiltinHumanReadable(), BuiltinIdentifierInList(), - BuiltinIfempty(), BuiltinLanguageCodes(), BuiltinLanguageStrings(), - BuiltinInList(), BuiltinListDifference(), BuiltinListEquals(), - BuiltinListIntersection(), BuiltinListitem(), BuiltinListRe(), - BuiltinListSort(), BuiltinListUnion(), BuiltinLookup(), - BuiltinLowercase(), BuiltinMultiply(), BuiltinNot(), - BuiltinOndevice(), BuiltinOr(), BuiltinPrint(), BuiltinRawField(), - BuiltinRe(), BuiltinSelect(), BuiltinSeriesSort(), BuiltinShorten(), - BuiltinStrcat(), BuiltinStrcatMax(), - BuiltinStrcmp(), BuiltinStrInList(), BuiltinStrlen(), BuiltinSubitems(), - BuiltinSublist(),BuiltinSubstr(), BuiltinSubtract(), BuiltinSwapAroundComma(), - BuiltinSwitch(), BuiltinTemplate(), BuiltinTest(), BuiltinTitlecase(), - BuiltinToday(), BuiltinUppercase(), + BuiltinAdd, BuiltinAnd, BuiltinApproximateFormats, + BuiltinAssign, BuiltinBooksize, + BuiltinCapitalize, BuiltinCmp, BuiltinContains, BuiltinCount, + BuiltinCurrentLibraryName, BuiltinCurrentLibraryPath, + BuiltinDaysBetween, BuiltinDivide, BuiltinEval, BuiltinFirstNonEmpty, + BuiltinField, BuiltinFinishFormatting, BuiltinFormatDate, + BuiltinFormatNumber, BuiltinFormatsModtimes, BuiltinFormatsPaths, + BuiltinFormatsSizes, + BuiltinHasCover, BuiltinHumanReadable, BuiltinIdentifierInList, + BuiltinIfempty, BuiltinLanguageCodes, BuiltinLanguageStrings, + BuiltinInList, BuiltinListDifference, BuiltinListEquals, + BuiltinListIntersection, BuiltinListitem, BuiltinListRe, + BuiltinListSort, BuiltinListUnion, BuiltinLookup, + BuiltinLowercase, BuiltinMultiply, BuiltinNot, + BuiltinOndevice, BuiltinOr, BuiltinPrint, BuiltinRawField, + BuiltinRe, BuiltinSelect, BuiltinSeriesSort, BuiltinShorten, + BuiltinStrcat, BuiltinStrcatMax, + BuiltinStrcmp, BuiltinStrInList, BuiltinStrlen, BuiltinSubitems, + BuiltinSublist,BuiltinSubstr, BuiltinSubtract, BuiltinSwapAroundComma, + BuiltinSwitch, BuiltinTemplate, BuiltinTest, BuiltinTitlecase, + BuiltinToday, BuiltinUppercase, ] class FormatterUserFunction(FormatterFunction): @@ -1260,10 +1275,11 @@ class UserFunction(FormatterUserFunction): return cls def load_user_template_functions(funcs): - formatter_functions().reset_to_builtins() - for func in funcs: - try: - cls = compile_user_function(*func) - formatter_functions().register_function(cls) - except: - traceback.print_exc() + if funcs: + formatter_functions().reset_to_builtins() + for func in funcs: + try: + cls = compile_user_function(*func) + formatter_functions().register_function(cls) + except: + traceback.print_exc() From d79e5668f2d5b694968d700d147ea3e21668a32c Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sat, 4 May 2013 06:14:26 +0200 Subject: [PATCH 2/4] Fix regression that broke user category searches. --- src/calibre/utils/search_query_parser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/calibre/utils/search_query_parser.py b/src/calibre/utils/search_query_parser.py index 47bc902c1c..589aa313f2 100644 --- a/src/calibre/utils/search_query_parser.py +++ b/src/calibre/utils/search_query_parser.py @@ -133,6 +133,7 @@ class Parser(object): # Had to translate named constants to numeric values lex_scanner = re.Scanner([ (r'[()]', lambda x,t: (1, t)), + (r'@.+?:[^")\s]+', lambda x,t: (2, unicode(t))), (r'[^"()\s]+', lambda x,t: (2, unicode(t))), (r'".*?((? Date: Tue, 7 May 2013 00:56:07 +0200 Subject: [PATCH 3/4] Fix searching for escaped double quotes. --- src/calibre/utils/search_query_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/utils/search_query_parser.py b/src/calibre/utils/search_query_parser.py index 589aa313f2..9771f08133 100644 --- a/src/calibre/utils/search_query_parser.py +++ b/src/calibre/utils/search_query_parser.py @@ -135,7 +135,7 @@ class Parser(object): (r'[()]', lambda x,t: (1, t)), (r'@.+?:[^")\s]+', lambda x,t: (2, unicode(t))), (r'[^"()\s]+', lambda x,t: (2, unicode(t))), - (r'".*?((? Date: Tue, 7 May 2013 08:53:54 +0200 Subject: [PATCH 4/4] Revert changes to delay loading --- src/calibre/utils/formatter_functions.py | 72 +++++++++--------------- 1 file changed, 28 insertions(+), 44 deletions(-) diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index dc60738394..67c75bdc79 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -10,7 +10,6 @@ __docformat__ = 'restructuredtext en' import inspect, re, traceback from math import trunc -from threading import RLock from calibre import human_readable from calibre.constants import DEBUG @@ -26,15 +25,6 @@ class FormatterFunctions(object): def __init__(self): self._builtins = {} self._functions = {} - self._lock = RLock() - self._loaded = False - - def load_builtins(self): - with self._lock: - if not self._loaded: - self._loaded = True - for c in _formatter_builtins: - c() def register_builtin(self, func_class): if not isinstance(func_class, FormatterFunction): @@ -49,7 +39,6 @@ class FormatterFunctions(object): self._functions[a] = func_class def register_function(self, func_class): - self.load_builtins() if not isinstance(func_class, FormatterFunction): raise ValueError('Class %s is not an instance of FormatterFunction'%( func_class.__class__.__name__)) @@ -59,11 +48,9 @@ class FormatterFunctions(object): self._functions[name] = func_class def get_builtins(self): - self.load_builtins() return self._builtins def get_builtins_and_aliases(self): - self.load_builtins() res = {} for f in self._builtins.itervalues(): res[f.name] = f @@ -72,12 +59,10 @@ class FormatterFunctions(object): return res def get_functions(self): - self.load_builtins() return self._functions def reset_to_builtins(self): self._functions = {} - self.load_builtins() for n,c in self._builtins.items(): self._functions[n] = c for a in c.aliases: @@ -1225,27 +1210,27 @@ class BuiltinFinishFormatting(BuiltinFormatterFunction): return prefix + formatter._do_format(val, fmt) + suffix _formatter_builtins = [ - BuiltinAdd, BuiltinAnd, BuiltinApproximateFormats, - BuiltinAssign, BuiltinBooksize, - BuiltinCapitalize, BuiltinCmp, BuiltinContains, BuiltinCount, - BuiltinCurrentLibraryName, BuiltinCurrentLibraryPath, - BuiltinDaysBetween, BuiltinDivide, BuiltinEval, BuiltinFirstNonEmpty, - BuiltinField, BuiltinFinishFormatting, BuiltinFormatDate, - BuiltinFormatNumber, BuiltinFormatsModtimes, BuiltinFormatsPaths, - BuiltinFormatsSizes, - BuiltinHasCover, BuiltinHumanReadable, BuiltinIdentifierInList, - BuiltinIfempty, BuiltinLanguageCodes, BuiltinLanguageStrings, - BuiltinInList, BuiltinListDifference, BuiltinListEquals, - BuiltinListIntersection, BuiltinListitem, BuiltinListRe, - BuiltinListSort, BuiltinListUnion, BuiltinLookup, - BuiltinLowercase, BuiltinMultiply, BuiltinNot, - BuiltinOndevice, BuiltinOr, BuiltinPrint, BuiltinRawField, - BuiltinRe, BuiltinSelect, BuiltinSeriesSort, BuiltinShorten, - BuiltinStrcat, BuiltinStrcatMax, - BuiltinStrcmp, BuiltinStrInList, BuiltinStrlen, BuiltinSubitems, - BuiltinSublist,BuiltinSubstr, BuiltinSubtract, BuiltinSwapAroundComma, - BuiltinSwitch, BuiltinTemplate, BuiltinTest, BuiltinTitlecase, - BuiltinToday, BuiltinUppercase, + BuiltinAdd(), BuiltinAnd(), BuiltinApproximateFormats(), + BuiltinAssign(), BuiltinBooksize(), + BuiltinCapitalize(), BuiltinCmp(), BuiltinContains(), BuiltinCount(), + BuiltinCurrentLibraryName(), BuiltinCurrentLibraryPath(), + BuiltinDaysBetween(), BuiltinDivide(), BuiltinEval(), BuiltinFirstNonEmpty(), + BuiltinField(), BuiltinFinishFormatting(), BuiltinFormatDate(), + BuiltinFormatNumber(), BuiltinFormatsModtimes(), BuiltinFormatsPaths(), + BuiltinFormatsSizes(), + BuiltinHasCover(), BuiltinHumanReadable(), BuiltinIdentifierInList(), + BuiltinIfempty(), BuiltinLanguageCodes(), BuiltinLanguageStrings(), + BuiltinInList(), BuiltinListDifference(), BuiltinListEquals(), + BuiltinListIntersection(), BuiltinListitem(), BuiltinListRe(), + BuiltinListSort(), BuiltinListUnion(), BuiltinLookup(), + BuiltinLowercase(), BuiltinMultiply(), BuiltinNot(), + BuiltinOndevice(), BuiltinOr(), BuiltinPrint(), BuiltinRawField(), + BuiltinRe(), BuiltinSelect(), BuiltinSeriesSort(), BuiltinShorten(), + BuiltinStrcat(), BuiltinStrcatMax(), + BuiltinStrcmp(), BuiltinStrInList(), BuiltinStrlen(), BuiltinSubitems(), + BuiltinSublist(),BuiltinSubstr(), BuiltinSubtract(), BuiltinSwapAroundComma(), + BuiltinSwitch(), BuiltinTemplate(), BuiltinTest(), BuiltinTitlecase(), + BuiltinToday(), BuiltinUppercase(), ] class FormatterUserFunction(FormatterFunction): @@ -1275,11 +1260,10 @@ class UserFunction(FormatterUserFunction): return cls def load_user_template_functions(funcs): - if funcs: - formatter_functions().reset_to_builtins() - for func in funcs: - try: - cls = compile_user_function(*func) - formatter_functions().register_function(cls) - except: - traceback.print_exc() + formatter_functions().reset_to_builtins() + for func in funcs: + try: + cls = compile_user_function(*func) + formatter_functions().register_function(cls) + except: + traceback.print_exc()