[Python-checkins] cpython (merge 3.3 -> default): Closes #17508: Merged fix from 3.3.

vinay.sajip python-checkins at python.org
Fri Mar 22 16:28:24 CET 2013


http://hg.python.org/cpython/rev/b916efe30d77
changeset:   82884:b916efe30d77
parent:      82879:6e25e5dbb269
parent:      82883:d674bbbed333
user:        Vinay Sajip <vinay_sajip at yahoo.co.uk>
date:        Fri Mar 22 15:27:52 2013 +0000
summary:
  Closes #17508: Merged fix from 3.3.

files:
  Lib/logging/config.py    |  28 +++++++++++++++++--
  Lib/test/test_logging.py |  39 ++++++++++++++++++++++++++-
  2 files changed, 61 insertions(+), 6 deletions(-)


diff --git a/Lib/logging/config.py b/Lib/logging/config.py
--- a/Lib/logging/config.py
+++ b/Lib/logging/config.py
@@ -1,4 +1,4 @@
-# Copyright 2001-2012 by Vinay Sajip. All Rights Reserved.
+# Copyright 2001-2013 by Vinay Sajip. All Rights Reserved.
 #
 # Permission to use, copy, modify, and distribute this software and its
 # documentation for any purpose and without fee is hereby granted,
@@ -19,7 +19,7 @@
 is based on PEP 282 and comments thereto in comp.lang.python, and influenced
 by Apache's log4j system.
 
-Copyright (C) 2001-2012 Vinay Sajip. All Rights Reserved.
+Copyright (C) 2001-2013 Vinay Sajip. All Rights Reserved.
 
 To use, simply 'import logging' and log away!
 """
@@ -564,14 +564,29 @@
                 # As handlers can refer to other handlers, sort the keys
                 # to allow a deterministic order of configuration
                 handlers = config.get('handlers', EMPTY_DICT)
+                deferred = []
                 for name in sorted(handlers):
                     try:
                         handler = self.configure_handler(handlers[name])
                         handler.name = name
                         handlers[name] = handler
                     except Exception as e:
+                        if 'target not configured yet' in str(e):
+                            deferred.append(name)
+                        else:
+                            raise ValueError('Unable to configure handler '
+                                             '%r: %s' % (name, e))
+
+                # Now do any that were deferred
+                for name in deferred:
+                    try:
+                        handler = self.configure_handler(handlers[name])
+                        handler.name = name
+                        handlers[name] = handler
+                    except Exception as e:
                         raise ValueError('Unable to configure handler '
                                          '%r: %s' % (name, e))
+
                 # Next, do loggers - they refer to handlers and filters
 
                 #we don't want to lose the existing loggers,
@@ -694,12 +709,17 @@
                 c = self.resolve(c)
             factory = c
         else:
-            klass = self.resolve(config.pop('class'))
+            cname = config.pop('class')
+            klass = self.resolve(cname)
             #Special case for handler which refers to another handler
             if issubclass(klass, logging.handlers.MemoryHandler) and\
                 'target' in config:
                 try:
-                    config['target'] = self.config['handlers'][config['target']]
+                    th = self.config['handlers'][config['target']]
+                    if not isinstance(th, logging.Handler):
+                        config['class'] = cname # restore for deferred configuration
+                        raise TypeError('target not configured yet')
+                    config['target'] = th
                 except Exception as e:
                     raise ValueError('Unable to set target handler '
                                      '%r: %s' % (config['target'], e))
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
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# Copyright 2001-2012 by Vinay Sajip. All Rights Reserved.
+# Copyright 2001-2013 by Vinay Sajip. All Rights Reserved.
 #
 # Permission to use, copy, modify, and distribute this software and its
 # documentation for any purpose and without fee is hereby granted,
@@ -18,7 +18,7 @@
 
 """Test harness for the logging module. Run all tests.
 
-Copyright (C) 2001-2012 Vinay Sajip. All Rights Reserved.
+Copyright (C) 2001-2013 Vinay Sajip. All Rights Reserved.
 """
 
 import logging
@@ -2415,6 +2415,36 @@
         },
     }
 
+    out_of_order = {
+        "version": 1,
+        "formatters": {
+            "mySimpleFormatter": {
+                "format": "%(asctime)s (%(name)s) %(levelname)s: %(message)s"
+            }
+        },
+        "handlers": {
+            "fileGlobal": {
+                "class": "logging.StreamHandler",
+                "level": "DEBUG",
+                "formatter": "mySimpleFormatter"
+            },
+            "bufferGlobal": {
+                "class": "logging.handlers.MemoryHandler",
+                "capacity": 5,
+                "formatter": "mySimpleFormatter",
+                "target": "fileGlobal",
+                "level": "DEBUG"
+                }
+        },
+        "loggers": {
+            "mymodule": {
+                "level": "DEBUG",
+                "handlers": ["bufferGlobal"],
+                "propagate": "true"
+            }
+        }
+    }
+
     def apply_config(self, conf):
         logging.config.dictConfig(conf)
 
@@ -2787,6 +2817,11 @@
             ('ERROR', '2'),
         ], pat=r"^[\w.]+ -> (\w+): (\d+)$")
 
+    def test_out_of_order(self):
+        self.apply_config(self.out_of_order)
+        handler = logging.getLogger('mymodule').handlers[0]
+        self.assertIsInstance(handler.target, logging.Handler)
+
     def test_baseconfig(self):
         d = {
             'atuple': (1, 2, 3),

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


More information about the Python-checkins mailing list