"""Code that handles logging for the project.""" import logging import logging.handlers import sys import colorclass class ColorFormatter(logging.Formatter): """Custom logging formatter that introduces console colors if not verbose.""" SPECIAL_SCOPE = __package__ def __init__(self, verbose, colors): """Constructor. :param bool verbose: Enable verbose logging. :param bool colors: Enable colored output for statements emitted from this project. """ self.verbose = verbose self.colors = colors if verbose: fmt = '%(asctime)s %(process)-5d %(levelname)-8s %(name)-40s %(message)s' else: fmt = '%(message)s' super(ColorFormatter, self).__init__(fmt) def format(self, record): """Apply little arrow and colors to the record. Arrow and colors are only applied to sphinxcontrib.versioning log statements. :param logging.LogRecord record: The log record object to log. """ formatted = super(ColorFormatter, self).format(record) if self.verbose or not record.name.startswith(self.SPECIAL_SCOPE): return formatted # Arrow. formatted = '=> ' + formatted # Colors. if not self.colors: return formatted if record.levelno >= logging.ERROR: formatted = str(colorclass.Color.red(formatted)) elif record.levelno >= logging.WARNING: formatted = str(colorclass.Color.yellow(formatted)) else: formatted = str(colorclass.Color.cyan(formatted)) return formatted def setup_logging(verbose=0, colors=False, name=None): """Configure console logging. Info and below go to stdout, others go to stderr. :param int verbose: Verbosity level. > 0 print debug statements. > 1 passed to sphinx-build. :param bool colors: Print color text in non-verbose mode. :param str name: Which logger name to set handlers to. Used for testing. """ root_logger = logging.getLogger(name) root_logger.setLevel(logging.DEBUG if verbose > 0 else logging.INFO) formatter = ColorFormatter(verbose > 0, colors) if colors: colorclass.Windows.enable() handler_stdout = logging.StreamHandler(sys.stdout) handler_stdout.setFormatter(formatter) handler_stdout.setLevel(logging.DEBUG) handler_stdout.addFilter(type('', (logging.Filter,), {'filter': staticmethod(lambda r: r.levelno <= logging.INFO)})) root_logger.addHandler(handler_stdout) handler_stderr = logging.StreamHandler(sys.stderr) handler_stderr.setFormatter(formatter) handler_stderr.setLevel(logging.WARNING) root_logger.addHandler(handler_stderr)