[Python-checkins] (2.6): Issue #11424: Fix bug in determining child loggers.

vinay.sajip python-checkins at python.org
Mon Mar 7 19:22:58 CET 2011


http://hg.python.org/cpython/rev/b9d76846bb1c
changeset:   68315:b9d76846bb1c
branch:      2.6
parent:      68264:50166a4bcfc6
user:        Vinay Sajip <vinay_sajip at yahoo.co.uk>
date:        Mon Mar 07 15:02:11 2011 +0000
summary:
  Issue #11424: Fix bug in determining child loggers.

files:
  Lib/logging/config.py
  Lib/test/test_logging.py

diff --git a/Lib/logging/config.py b/Lib/logging/config.py
--- a/Lib/logging/config.py
+++ b/Lib/logging/config.py
@@ -232,14 +232,14 @@
             propagate = 1
         logger = logging.getLogger(qn)
         if qn in existing:
-            i = existing.index(qn)
+            i = existing.index(qn) + 1 # start with the entry after qn
             prefixed = qn + "."
             pflen = len(prefixed)
             num_existing = len(existing)
-            i = i + 1 # look at the entry after qn
-            while (i < num_existing) and (existing[i][:pflen] == prefixed):
-                child_loggers.append(existing[i])
-                i = i + 1
+            while i < num_existing:
+                if existing[i][:pflen] == prefixed:
+                    child_loggers.append(existing[i])
+                i += 1
             existing.remove(qn)
         if "level" in opts:
             level = cp.get(sectname, "level")
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -558,6 +558,38 @@
     datefmt=
     """
 
+    # config1a moves the handler to the root.
+    config1a = """
+    [loggers]
+    keys=root,parser
+
+    [handlers]
+    keys=hand1
+
+    [formatters]
+    keys=form1
+
+    [logger_root]
+    level=WARNING
+    handlers=hand1
+
+    [logger_parser]
+    level=DEBUG
+    handlers=
+    propagate=1
+    qualname=compiler.parser
+
+    [handler_hand1]
+    class=StreamHandler
+    level=NOTSET
+    formatter=form1
+    args=(sys.stdout,)
+
+    [formatter_form1]
+    format=%(levelname)s ++ %(message)s
+    datefmt=
+    """
+
     # config2 has a subtle configuration error that should be reported
     config2 = config1.replace("sys.stdout", "sys.stbout")
 
@@ -636,6 +668,44 @@
     datefmt=
     """
 
+    # config7 adds a compiler logger.
+    config7 = """
+    [loggers]
+    keys=root,parser,compiler
+
+    [handlers]
+    keys=hand1
+
+    [formatters]
+    keys=form1
+
+    [logger_root]
+    level=WARNING
+    handlers=hand1
+
+    [logger_compiler]
+    level=DEBUG
+    handlers=
+    propagate=1
+    qualname=compiler
+
+    [logger_parser]
+    level=DEBUG
+    handlers=
+    propagate=1
+    qualname=compiler.parser
+
+    [handler_hand1]
+    class=StreamHandler
+    level=NOTSET
+    formatter=form1
+    args=(sys.stdout,)
+
+    [formatter_form1]
+    format=%(levelname)s ++ %(message)s
+    datefmt=
+    """
+
     def apply_config(self, conf):
         try:
             fn = tempfile.mktemp(".ini")
@@ -705,6 +775,49 @@
     def test_config6_ok(self):
         self.test_config1_ok(config=self.config6)
 
+    def test_config7_ok(self):
+        with captured_stdout() as output:
+            self.apply_config(self.config1a)
+            logger = logging.getLogger("compiler.parser")
+            # See issue #11424. compiler-hyphenated sorts
+            # between compiler and compiler.xyz and this
+            # was preventing compiler.xyz from being included
+            # in the child loggers of compiler because of an
+            # overzealous loop termination condition.
+            hyphenated = logging.getLogger('compiler-hyphenated')
+            # All will output a message
+            logger.info(self.next_message())
+            logger.error(self.next_message())
+            hyphenated.critical(self.next_message())
+            self.assert_log_lines([
+                ('INFO', '1'),
+                ('ERROR', '2'),
+                ('CRITICAL', '3'),
+            ], stream=output)
+            # Original logger output is empty.
+            self.assert_log_lines([])
+        with captured_stdout() as output:
+            self.apply_config(self.config7)
+            logger = logging.getLogger("compiler.parser")
+            self.assertFalse(logger.disabled)
+            # Both will output a message
+            logger.info(self.next_message())
+            logger.error(self.next_message())
+            logger = logging.getLogger("compiler.lexer")
+            # Both will output a message
+            logger.info(self.next_message())
+            logger.error(self.next_message())
+            # Will not appear
+            hyphenated.critical(self.next_message())
+            self.assert_log_lines([
+                ('INFO', '4'),
+                ('ERROR', '5'),
+                ('INFO', '6'),
+                ('ERROR', '7'),
+            ], stream=output)
+            # Original logger output is empty.
+            self.assert_log_lines([])
+    
 class LogRecordStreamHandler(StreamRequestHandler):
 
     """Handler for a streaming logging request. It saves the log message in the

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list