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
This commit is contained in:
Darragh Bailey 2016-09-20 17:51:37 +01:00
parent 8d5fbf9388
commit 60774fb22d
1 changed files with 16 additions and 62 deletions

View File

@ -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