Skip to content

Commit 340a4bb

Browse files
committed
Issue #17508: Merged fix from 3.2.
2 parents 8f35c89 + 3f885b5 commit 340a4bb

File tree

2 files changed

+61
-6
lines changed

2 files changed

+61
-6
lines changed

Lib/logging/config.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2001-2010 by Vinay Sajip. All Rights Reserved.
1+
# Copyright 2001-2013 by Vinay Sajip. All Rights Reserved.
22
#
33
# Permission to use, copy, modify, and distribute this software and its
44
# documentation for any purpose and without fee is hereby granted,
@@ -19,7 +19,7 @@
1919
is based on PEP 282 and comments thereto in comp.lang.python, and influenced
2020
by Apache's log4j system.
2121
22-
Copyright (C) 2001-2010 Vinay Sajip. All Rights Reserved.
22+
Copyright (C) 2001-2013 Vinay Sajip. All Rights Reserved.
2323
2424
To use, simply 'import logging' and log away!
2525
"""
@@ -561,14 +561,29 @@ def configure(self):
561561
# As handlers can refer to other handlers, sort the keys
562562
# to allow a deterministic order of configuration
563563
handlers = config.get('handlers', EMPTY_DICT)
564+
deferred = []
564565
for name in sorted(handlers):
566+
try:
567+
handler = self.configure_handler(handlers[name])
568+
handler.name = name
569+
handlers[name] = handler
570+
except Exception as e:
571+
if 'target not configured yet' in str(e):
572+
deferred.append(name)
573+
else:
574+
raise ValueError('Unable to configure handler '
575+
'%r: %s' % (name, e))
576+
577+
# Now do any that were deferred
578+
for name in deferred:
565579
try:
566580
handler = self.configure_handler(handlers[name])
567581
handler.name = name
568582
handlers[name] = handler
569583
except Exception as e:
570584
raise ValueError('Unable to configure handler '
571585
'%r: %s' % (name, e))
586+
572587
# Next, do loggers - they refer to handlers and filters
573588

574589
#we don't want to lose the existing loggers,
@@ -691,12 +706,17 @@ def configure_handler(self, config):
691706
c = self.resolve(c)
692707
factory = c
693708
else:
694-
klass = self.resolve(config.pop('class'))
709+
cname = config.pop('class')
710+
klass = self.resolve(cname)
695711
#Special case for handler which refers to another handler
696712
if issubclass(klass, logging.handlers.MemoryHandler) and\
697713
'target' in config:
698714
try:
699-
config['target'] = self.config['handlers'][config['target']]
715+
th = self.config['handlers'][config['target']]
716+
if not isinstance(th, logging.Handler):
717+
config['class'] = cname # restore for deferred configuration
718+
raise TypeError('target not configured yet')
719+
config['target'] = th
700720
except Exception as e:
701721
raise ValueError('Unable to set target handler '
702722
'%r: %s' % (config['target'], e))

Lib/test/test_logging.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22
#
3-
# Copyright 2001-2012 by Vinay Sajip. All Rights Reserved.
3+
# Copyright 2001-2013 by Vinay Sajip. All Rights Reserved.
44
#
55
# Permission to use, copy, modify, and distribute this software and its
66
# documentation for any purpose and without fee is hereby granted,
@@ -18,7 +18,7 @@
1818

1919
"""Test harness for the logging module. Run all tests.
2020
21-
Copyright (C) 2001-2012 Vinay Sajip. All Rights Reserved.
21+
Copyright (C) 2001-2013 Vinay Sajip. All Rights Reserved.
2222
"""
2323

2424
import logging
@@ -2364,6 +2364,36 @@ class ConfigDictTest(BaseTest):
23642364
},
23652365
}
23662366

2367+
out_of_order = {
2368+
"version": 1,
2369+
"formatters": {
2370+
"mySimpleFormatter": {
2371+
"format": "%(asctime)s (%(name)s) %(levelname)s: %(message)s"
2372+
}
2373+
},
2374+
"handlers": {
2375+
"fileGlobal": {
2376+
"class": "logging.StreamHandler",
2377+
"level": "DEBUG",
2378+
"formatter": "mySimpleFormatter"
2379+
},
2380+
"bufferGlobal": {
2381+
"class": "logging.handlers.MemoryHandler",
2382+
"capacity": 5,
2383+
"formatter": "mySimpleFormatter",
2384+
"target": "fileGlobal",
2385+
"level": "DEBUG"
2386+
}
2387+
},
2388+
"loggers": {
2389+
"mymodule": {
2390+
"level": "DEBUG",
2391+
"handlers": ["bufferGlobal"],
2392+
"propagate": "true"
2393+
}
2394+
}
2395+
}
2396+
23672397
def apply_config(self, conf):
23682398
logging.config.dictConfig(conf)
23692399

@@ -2664,6 +2694,11 @@ def test_listen_config_1_ok(self):
26642694
# Original logger output is empty.
26652695
self.assert_log_lines([])
26662696

2697+
def test_out_of_order(self):
2698+
self.apply_config(self.out_of_order)
2699+
handler = logging.getLogger('mymodule').handlers[0]
2700+
self.assertIsInstance(handler.target, logging.Handler)
2701+
26672702
def test_baseconfig(self):
26682703
d = {
26692704
'atuple': (1, 2, 3),

0 commit comments

Comments
 (0)