Source code for benchmarkstt.normalization.logger

import logging
import os
from benchmarkstt.diff.formatter import DiffFormatter
from collections import namedtuple
from collections import OrderedDict

NormalizedLogItem = namedtuple('NormalizedLogItem', ['stack', 'original', 'normalized'])


[docs]class Logger: def __init__(self): self.title = None self.logger = logging.getLogger('benchmarkstt.normalize') self.logger.setLevel(logging.INFO) self.logger.propagate = False self.stack = []
normalization_logger = Logger()
[docs]class ListHandler(logging.StreamHandler): def __init__(self): self._logs = [] super().__init__(os.devnull)
[docs] def emit(self, record): msg = self.format(record) self._logs.append(msg)
@property def logs(self): return self._logs
[docs] def flush(self): result = self._logs self._logs = [] return result
[docs]class DiffLoggingFormatterDialect:
[docs] def format(self, title, stack, diff): raise NotImplementedError()
[docs]class DiffLoggingTextFormatterDialect(DiffLoggingFormatterDialect):
[docs] def format(self, title, stack, diff): args = [] if title is not None: args.append(title) elif normalization_logger.title is not None: args.append(normalization_logger.title) args.append('/'.join(stack)) args.append(diff) return ': '.join(args)
[docs]class DiffLoggingDictFormatterDialect(DiffLoggingFormatterDialect):
[docs] def format(self, title, stack, diff): return OrderedDict(title=title, stack=stack, diff=diff)
[docs]class DiffLoggingFormatter(logging.Formatter): diff_logging_formatter_dialects = { "text": DiffLoggingTextFormatterDialect, "dict": DiffLoggingDictFormatterDialect, } def __init__(self, dialect=None, diff_formatter_dialect=None, title=None, *args, **kwargs): self._title = title self._differ = DiffFormatter(dialect, *args, **kwargs) strict = False if diff_formatter_dialect is None: diff_formatter_dialect = dialect else: strict = True self._formatter_dialect = self.get_dialect(diff_formatter_dialect, strict) super().__init__()
[docs] def format(self, record): item = record.msg if type(item) is NormalizedLogItem: diff = self._differ.diff(item.original, item.normalized) return self._formatter_dialect.format(self._title, item.stack, diff) return super().format(record)
[docs] @classmethod def has_dialect(cls, dialect): return dialect in cls.diff_logging_formatter_dialects
[docs] @classmethod def get_dialect(cls, dialect, strict=None): if dialect is None: dialect = 'text' if not cls.has_dialect(dialect): if strict: raise ValueError("Unknown diff formatter dialect", dialect) dialect = 'text' return cls.diff_logging_formatter_dialects[dialect]()
[docs]def log(func): """ Log decorator for normalization classes """ def _(cls, text): normalization_logger.stack.append(repr(cls)) result = func(cls, text) logger_ = normalization_logger.logger if text != result: logger_.info(NormalizedLogItem(list(normalization_logger.stack), text, result)) normalization_logger.stack.pop() return result return _
[docs]class LogCapturer: def __init__(self, *args, **kwargs): self.formatter_args = (args, kwargs) self.handler = None def __enter__(self): self.handler = ListHandler() self.handler.setFormatter(DiffLoggingFormatter(*self.formatter_args[0], **self.formatter_args[1])) normalization_logger.logger.addHandler(self.handler) return self @property def logs(self): return list(self.handler.logs) def __exit__(self, exc_type, exc_val, exc_tb): self.handler.flush() normalization_logger.logger.removeHandler(self.handler) self.handler = None