diff --git a/product/ZSQLCatalog/SearchText/SearchTextParser.py b/product/ZSQLCatalog/SearchText/SearchTextParser.py index e75581af1ea233e587cbbf628a6f9c217fffdfd6..64784e221c6a799d01258a64ce62da0345125528 100755 --- a/product/ZSQLCatalog/SearchText/SearchTextParser.py +++ b/product/ZSQLCatalog/SearchText/SearchTextParser.py @@ -43,28 +43,36 @@ if __name__ == '__main__': else: DEBUG = 0 -parser_pool = threading.local() +class ParserPool(object): + """ + Per-thread parser pool, because ply is not thread-safe. + """ -@profiler_decorator -def getAdvancedSearchTextDetector(): - try: - return parser_pool.advanced_search_text_detector - except AttributeError: - advanced_search_text_detector = AdvancedSearchTextDetector() - advanced_search_text_detector.init(debug=DEBUG) - parser_pool.advanced_search_text_detector = advanced_search_text_detector - return advanced_search_text_detector + def __init__(self): + self.parser_pool = threading.local() + self.parser_registry = {} -@profiler_decorator -def getAdvancedSearchTextParser(): - try: - return parser_pool.parser - except AttributeError: - parser = AdvancedSearchTextParser() - parser.init(debug=DEBUG) - parser_pool.parser = parser + def register(self, parser): + parser_registry = self.parser_registry + name = (parser.__module__, parser.__name__) + if name in parser_registry: + raise ValueError, 'Duplicate parser for name %r' % (name, ) + parser_registry[name] = parser + return name + + def get(self, name): + try: + parser = getattr(self.parser_pool, name) + except AttributeError: + parser = self.parser_registry[name]() + parser.init(debug=DEBUG) + setattr(self.parser_pool, name, parser) return parser +parser_pool = ParserPool() +DETECTOR_ID = parser_pool.register(AdvancedSearchTextDetector) +PARSER_ID = parser_pool.register(AdvancedSearchTextParser) + def safeParsingDecorator(func): """ Wrapper hiding parsing errors and returning None when they occur. @@ -84,13 +92,13 @@ def safeParsingDecorator(func): @profiler_decorator def isAdvancedSearchText(input, is_column): - return getAdvancedSearchTextDetector()(input, is_column) + return parser_pool.get(DETECTOR_ID)(input, is_column) @profiler_decorator @safeParsingDecorator def parse(input, is_column, *args, **kw): if isAdvancedSearchText(input, is_column): - result = getAdvancedSearchTextParser()(input, is_column, *args, **kw) + result = parser_pool.get(PARSER_ID)(input, is_column, *args, **kw) else: result = None return result @@ -328,7 +336,8 @@ if __name__ == '__main__': print repr(input) try: try: - detector_result = getAdvancedSearchTextDetector()(input, isColumn) + detector_result = parser_pool.get(DETECTOR_ID)(input, + isColumn) except ParserOrLexerError, message: print ' Detector raise: %r' % (message, ) detector_result = False @@ -336,7 +345,7 @@ if __name__ == '__main__': print ' Detector: %r' % (detector_result, ) if detector_result: print ' LEX:' - advanced_parser = getAdvancedSearchTextParser() + advanced_parser = parser_pool.get(PARSER_ID) lexer = advanced_parser.lexer advanced_parser.isColumn = isColumn lexer.input(input)