summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVinay Sajip <vinay_sajip@yahoo.co.uk>2013-03-22 15:19:54 (GMT)
committerVinay Sajip <vinay_sajip@yahoo.co.uk>2013-03-22 15:19:54 (GMT)
commit3f885b543256df8acabc39fa9c28f45dfa6e4979 (patch)
tree8ec84f92fce88e722dd15905b0ff91fa9e73e9d3
parentd5537d071cc2acada7220431a0eea5931c2e8a2d (diff)
downloadcpython-3f885b543256df8acabc39fa9c28f45dfa6e4979.zip
cpython-3f885b543256df8acabc39fa9c28f45dfa6e4979.tar.gz
cpython-3f885b543256df8acabc39fa9c28f45dfa6e4979.tar.bz2
Issue #17508: Handled out-of-order handler configuration correctly.
-rw-r--r--Lib/logging/config.py28
-rw-r--r--Lib/test/test_logging.py38
2 files changed, 60 insertions, 6 deletions
diff --git a/Lib/logging/config.py b/Lib/logging/config.py
index 373da2b..38b21e6 100644
--- a/Lib/logging/config.py
+++ b/Lib/logging/config.py
@@ -1,4 +1,4 @@
-# Copyright 2001-2010 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 @@ Configuration functions for the logging package for Python. The core package
is based on PEP 282 and comments thereto in comp.lang.python, and influenced
by Apache's log4j system.
-Copyright (C) 2001-2010 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 @@ class DictConfigurator(BaseConfigurator):
# 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 @@ class DictConfigurator(BaseConfigurator):
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
index 2a3c780..bbd4852 100644
--- 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
@@ -1696,6 +1696,36 @@ class ConfigDictTest(BaseTest):
},
}
+ 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)
@@ -1994,6 +2024,10 @@ class ConfigDictTest(BaseTest):
# Original logger output is empty.
self.assert_log_lines([])
+ 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)
class ManagerTest(BaseTest):
def test_manager_loggerclass(self):