Browse Source

Added unittests for the compat implementation of LoggerAdapter.

Ask Solem 14 years ago
parent
commit
f9d7ca551b
2 changed files with 143 additions and 79 deletions
  1. 61 0
      celery/tests/test_log.py
  2. 82 79
      celery/utils/compat.py

+ 61 - 0
celery/tests/test_log.py

@@ -18,7 +18,9 @@ from celery.log import (setup_logger, setup_task_logger, emergency_error,
                         get_default_logger, get_task_logger,
                         redirect_stdouts_to_logger, LoggingProxy)
 from celery.tests.utils import override_stdouts, execute_context
+from celery.utils import gen_unique_id
 from celery.utils.compat import LoggerAdapter
+from celery.utils.compat import _CompatLoggerAdapter
 
 
 def get_handlers(logger):
@@ -165,3 +167,62 @@ class test_task_logger(test_default_logger):
     def setUp(self):
         self.setup_logger = setup_task_logger
         self.get_logger = get_task_logger
+
+
+class MockLogger(logging.Logger):
+    _records = None
+
+    def __init__(self, *args, **kwargs):
+        self._records = []
+        logging.Logger.__init__(self, *args, **kwargs)
+
+    def handle(self, record):
+        self._records.append(record)
+
+    def isEnabledFor(self, level):
+        return True
+
+
+class test_CompatLoggerAdapter(unittest.TestCase):
+    levels = ("debug",
+              "info",
+              "warn", "warning",
+              "error",
+              "fatal", "critical")
+
+    def setUp(self):
+        self.logger, self.adapter = self.createAdapter()
+
+    def createAdapter(self, name=None, extra={"foo": "bar"}):
+        logger = MockLogger(name=name or gen_unique_id())
+        return logger, _CompatLoggerAdapter(logger, extra)
+
+    def test_levels(self):
+        for level in self.levels:
+            msg = "foo bar %s" % (level, )
+            logger, adapter = self.createAdapter()
+            getattr(adapter, level)(msg)
+            self.assertEqual(logger._records[0].msg, msg)
+
+    def test_exception(self):
+        try:
+            raise KeyError("foo")
+        except KeyError:
+            self.adapter.exception("foo bar exception")
+        self.assertEqual(self.logger._records[0].msg, "foo bar exception")
+
+    def test_setLevel(self):
+        self.adapter.setLevel(logging.INFO)
+        self.assertEqual(self.logger.level, logging.INFO)
+
+    def test_process(self):
+        msg, kwargs = self.adapter.process("foo bar baz", {"exc_info": 1})
+        self.assertDictEqual(kwargs, {"exc_info": 1,
+                                      "extra": {"foo": "bar"}})
+
+    def test_add_remove_handlers(self):
+        handler = logging.StreamHandler()
+        self.adapter.addHandler(handler)
+        self.assertIs(self.logger.handlers[0], handler)
+        self.adapter.removeHandler(handler)
+        self.assertListEqual(self.logger.handlers, [])

+ 82 - 79
celery/utils/compat.py

@@ -290,90 +290,93 @@ except ImportError:
     collections.defaultdict = defaultdict # Pickle needs this.
 
 ############## logging.LoggerAdapter ########################################
-
-try:
-    from logging import LoggerAdapter
-except ImportError:
-    import logging
-    class LoggerAdapter(object):
-
-        def __init__(self, logger, extra):
-            self.logger = logger
-            self.extra = extra
-
-        def setLevel(self, level):
-            self.level = logging._checkLevel(level)
-
-        def process(self, msg, kwargs):
-            kwargs["extra"] = self.extra
-            return msg, kwargs
-
-        def debug(self, msg, *args, **kwargs):
-            self.log(logging.DEBUG, msg, args, **kwargs)
-
-        def info(self, msg, *args, **kwargs):
-            self.log(logging.INFO, msg, args, **kwargs)
-
-        def warning(self, msg, *args, **kwargs):
-            self.log(logging.WARNING, msg, args, **kwargs)
-        warn = warning
-
-        def error(self, msg, *args, **kwargs):
-            self.log(logging.ERROR, msg, args, **kwargs)
-
-        def exception(self, msg, *args, **kwargs):
-            kwargs.setdefault("exc_info", 1)
-            self.error(msg, *args, **kwargs)
-
-        def critical(self, msg, *args, **kwargs):
-            self.log(logging.CRITICAL, msg, args, **kwargs)
-        fatal = critical
-
-        def log(self, level, msg, args, **kwargs):
-            if self.logger.isEnabledFor(level):
-                msg, kwargs = self.process(msg, kwargs)
-                self._log(level, msg, args, **kwargs)
-
-        def makeRecord(self, name, level, fn, lno, msg, args, exc_info, 
-                func=None, extra=None):
-            rv = logging.LogRecord(name, level, fn, lno,
-                                   msg, args, exc_info, func)
-            if extra is not None:
-                for key, value in extra.items():
-                    if key in ("message", "asctime") or key in rv.__dict__:
-                        raise KeyError(
-                                "Attempt to override %r in LogRecord" % key)
-                    rv.__dict__[key] = value
-            return rv
-
-        def _log(self, level, msg, args, exc_info=None, extra=None):
-            defcaller = "(unknown file)", 0, "(unknown function)"
-            if logging._srcfile:
-                # IronPython doesn't track Python frames, so findCaller
-                # throws an exception on some versions of IronPython.
-                # We trap it here so that IronPython can use logging.
-                try:
-                    fn, lno, func = self.logger.findCaller()
-                except ValueError:
-                    fn, lno, func = defcaller
-            else:
+import sys
+import logging
+
+class _CompatLoggerAdapter(object):
+
+    def __init__(self, logger, extra):
+        self.logger = logger
+        self.extra = extra
+
+    def setLevel(self, level):
+        self.logger.level = logging._checkLevel(level)
+
+    def process(self, msg, kwargs):
+        kwargs["extra"] = self.extra
+        return msg, kwargs
+
+    def debug(self, msg, *args, **kwargs):
+        self.log(logging.DEBUG, msg, args, **kwargs)
+
+    def info(self, msg, *args, **kwargs):
+        self.log(logging.INFO, msg, args, **kwargs)
+
+    def warning(self, msg, *args, **kwargs):
+        self.log(logging.WARNING, msg, args, **kwargs)
+    warn = warning
+
+    def error(self, msg, *args, **kwargs):
+        self.log(logging.ERROR, msg, args, **kwargs)
+
+    def exception(self, msg, *args, **kwargs):
+        kwargs.setdefault("exc_info", 1)
+        self.error(msg, *args, **kwargs)
+
+    def critical(self, msg, *args, **kwargs):
+        self.log(logging.CRITICAL, msg, args, **kwargs)
+    fatal = critical
+
+    def log(self, level, msg, args, **kwargs):
+        if self.logger.isEnabledFor(level):
+            msg, kwargs = self.process(msg, kwargs)
+            self._log(level, msg, args, **kwargs)
+
+    def makeRecord(self, name, level, fn, lno, msg, args, exc_info, 
+            func=None, extra=None):
+        rv = logging.LogRecord(name, level, fn, lno,
+                               msg, args, exc_info, func)
+        if extra is not None:
+            for key, value in extra.items():
+                if key in ("message", "asctime") or key in rv.__dict__:
+                    raise KeyError(
+                            "Attempt to override %r in LogRecord" % key)
+                rv.__dict__[key] = value
+        return rv
+
+    def _log(self, level, msg, args, exc_info=None, extra=None):
+        defcaller = "(unknown file)", 0, "(unknown function)"
+        if logging._srcfile:
+            # IronPython doesn't track Python frames, so findCaller
+            # throws an exception on some versions of IronPython.
+            # We trap it here so that IronPython can use logging.
+            try:
+                fn, lno, func = self.logger.findCaller()
+            except ValueError:
                 fn, lno, func = defcaller
-            if exc_info:
-                if not isinstance(exc_info, tuple):
-                    exc_info = sys.exc_info()
-            record = self.makeRecord(self.logger.name, level, fn, lno, msg,
-                                     args, exc_info, func, extra)
-            self.logger.handle(record)
+        else:
+            fn, lno, func = defcaller
+        if exc_info:
+            if not isinstance(exc_info, tuple):
+                exc_info = sys.exc_info()
+        record = self.makeRecord(self.logger.name, level, fn, lno, msg,
+                                    args, exc_info, func, extra)
+        self.logger.handle(record)
+
+    def isEnabledFor(self, level):
+        return self.logger.isEnabledFor(level)
 
-        def isEnabledFor(self, level):
-            return self.logger.isEnabledFor(level)
+    def addHandler(self, hdlr):
+        self.logger.addHandler(hdlr)
 
-        def addHandler(self, hdlr):
-            self.logger.addHandler(hdlr)
+    def removeHandler(self, hdlr):
+        self.logger.removeHandler(hdlr)
 
-        def removeHandler(self, hdlr):
-            self.logger.removeHandler(hdlr)
 
+try:
+    from logging import LoggerAdapter
+except ImportError:
+    LoggerAdapter = _CompatLoggerAdapter
 
 ############## itertools.izip_longest #######################################