From 60774fb22d7dc947b72b8baf4d4a8a8377ecf81d Mon Sep 17 00:00:00 2001 From: Darragh Bailey Date: Tue, 20 Sep 2016 17:51:37 +0100 Subject: [PATCH] Simplify custom logging classes No need to use meta programming to support dedent of text blocks on message emission for simpler log messages. Change-Id: Icacb1c2f422cb6035b6b93a21c90b8896f0ac79c --- git_upstream/log.py | 78 ++++++++++----------------------------------- 1 file changed, 16 insertions(+), 62 deletions(-) diff --git a/git_upstream/log.py b/git_upstream/log.py index 9ad38e5..5cf017f 100644 --- a/git_upstream/log.py +++ b/git_upstream/log.py @@ -24,12 +24,9 @@ functions for verbose/quiet CLI args to retreive the appropriate level for logging output to the console. """ -from functools import wraps import logging import textwrap -import six - # Add new NOTICE logging level NOTICE = (logging.INFO + logging.WARN) // 2 @@ -37,17 +34,6 @@ logging.NOTICE = NOTICE logging.addLevelName(NOTICE, "NOTICE") -def notice(self, msg, *args, **kwargs): - """ - Supports same arguments as default methods available from - logging.Logger class - """ - if self.isEnabledFor(NOTICE): - self._log(NOTICE, msg, args, **kwargs) - -logging.Logger.notice = notice - - def get_logger(name=None): """ Wrapper for standard logging.getLogger that ensures all loggers in this @@ -96,53 +82,21 @@ class LevelFilterIgnoreBelow(logging.Filter): return record.levelno >= self.level -class DedentLoggerMeta(type): - """ - Meta class to wrap all level functions in logging interface with dedent - - Classes created from this should be derived from the logging.Logger class - as otherwise they will not contain the correct methods to be wrapped and - trying to pass them as the default class to create Loggers from will fail. - """ - - def __new__(cls, name, bases, dict): - # provide a more intelligent error instead of waiting for - # setattr/getattr adding of a wrapper function to fail - if logging.Logger not in bases: - raise TypeError("%s not derived from logging.Logger" % name) - - obj = super(DedentLoggerMeta, cls).__new__(cls, name, bases, dict) - for levelalias in _levels: - level = levelalias[0] - aliases = levelalias[1:] - setattr(obj, level, cls.wrap()(getattr(obj, level))) - for alias in aliases: - setattr(obj, alias, getattr(obj, level)) - setattr(obj, 'log', cls.wrap(True)(getattr(obj, 'log'))) - return obj - - @staticmethod - def wrap(with_level=False): - def dedentlog(func): - if with_level: - def _dedent_log(self, level, msg, *args, **kwargs): - dedent = kwargs.pop('dedent', True) - if dedent: - msg = textwrap.dedent(msg.lstrip('\n')) - func(self, level, msg, *args, **kwargs) - else: - def _dedent_log(self, msg, *args, **kwargs): - dedent = kwargs.pop('dedent', True) - if dedent: - msg = textwrap.dedent(msg.lstrip('\n')) - func(self, msg, *args, **kwargs) - return wraps(func)(_dedent_log) - return dedentlog - - -@six.add_metaclass(DedentLoggerMeta) class DedentLogger(logging.Logger): - pass + + def _log(self, level, msg, args, **kwargs): + dedent = kwargs.pop('dedent', True) + if dedent: + msg = textwrap.dedent(msg.lstrip('\n')) + super(DedentLogger, self)._log(level, msg, args, **kwargs) + + def notice(self, msg, *args, **kwargs): + """ + Supports same arguments as default methods available from + logging.Logger class + """ + if self.isEnabledFor(NOTICE): + self._log(NOTICE, msg, args, **kwargs) # override default logger class for everything that imports this module @@ -152,10 +106,10 @@ logging.setLoggerClass(DedentLogger) class LogDedentMixin(object): def __init__(self, *args, **kwargs): - self.__log = get_logger('%s.%s' % (__name__, self.__class__.__name__)) + self._log = get_logger('%s.%s' % (__name__, self.__class__.__name__)) super(LogDedentMixin, self).__init__(*args, **kwargs) @property def log(self): - return self.__log + return self._log