diff --git a/beets/logging.py b/beets/logging.py index 9d9afdab3..a213f1e20 100644 --- a/beets/logging.py +++ b/beets/logging.py @@ -2,11 +2,15 @@ Provide everything the "logging" module does, the only difference is that when getLogger(name) instantiates a logger that logger uses {}-style formatting. + +It requires special hacks for python 2.6 due to logging.Logger being an old- +style class and having no loggerClass attribute. """ from __future__ import absolute_import from copy import copy from logging import * # noqa +import sys # create a str.format-based logger @@ -23,8 +27,21 @@ class StrFormatLogger(Logger): def _log(self, level, msg, args, exc_info=None, extra=None, **kwargs): """Log msg.format(*args, **kwargs)""" m = self._LogMessage(msg, args, kwargs) - return super(StrFormatLogger, self)._log(level, m, (), exc_info, extra) + return Logger._log(self, level, m, (), exc_info, extra) + # we cannot call super(StrFormatLogger, self) because it is not + # allowed on old-style classes (py2) which Logger is in python 2.6 + # moreover we cannot make StrFormatLogger a new-style class (by + # declaring 'class StrFormatLogger(Logger, object)' because the class- + # patching stmt 'logger.__class__ = StrFormatLogger' would not work: + # both prev & new __class__ values must be either old- or new- style, + # no mixing allowed. + if sys.version_info[:2] == (2, 6): + def getChild(self, suffix): + """Shameless copy from cpython's Lib/logging/__init__.py""" + if self.root is not self: + suffix = '.'.join((self.name, suffix)) + return self.manager.getLogger(suffix) my_manager = copy(Logger.manager) my_manager.loggerClass = StrFormatLogger @@ -35,3 +52,21 @@ def getLogger(name=None): return my_manager.getLogger(name) else: return root + + +if sys.version_info[:2] == (2, 6): + # no Manager.loggerClass so we dynamically change the logger class + # we must be careful to do that on new loggers only to avoid side-effects. + # Wrap Manager.getLogger + old_getLogger = my_manager.getLogger + + def new_getLogger(name): + change_its_type = not isinstance(my_manager.loggerDict.get(name), + Logger) + # it either does not exist or is a placeholder + logger = old_getLogger(name) + if change_its_type: + logger.__class__ = StrFormatLogger + return logger + + my_manager.getLogger = new_getLogger diff --git a/test/test_logging.py b/test/test_logging.py index f63a63b63..0d2eb7291 100644 --- a/test/test_logging.py +++ b/test/test_logging.py @@ -11,15 +11,15 @@ class LoggingTest(TestCase): l1 = log.getLogger("foo123") l2 = blog.getLogger("foo123") self.assertEqual(l1, l2) - self.assertEqual(type(l1), log.Logger) + self.assertEqual(l1.__class__, log.Logger) l3 = blog.getLogger("bar123") l4 = log.getLogger("bar123") self.assertEqual(l3, l4) - self.assertEqual(type(l3), blog.StrFormatLogger) + self.assertEqual(l3.__class__, blog.StrFormatLogger) l5 = l3.getChild("shalala") - self.assertEqual(type(l5), blog.StrFormatLogger) + self.assertEqual(l5.__class__, blog.StrFormatLogger) def test_str_format_logging(self): l = blog.getLogger("baz123") @@ -29,7 +29,7 @@ class LoggingTest(TestCase): l.addHandler(handler) l.propagate = False - l.warning("foo {} {bar}", "oof", bar="baz") + l.warning("foo {0} {bar}", "oof", bar="baz") handler.flush() self.assertTrue(stream.getvalue(), "foo oof baz")