Skip to content

Commit 078cdcc

Browse files
authored
[3.11] gh-110875: Handle '.' properties in logging formatter configuration correctly. (GH-110943) (GH-111914)
Co-authored-by: Vinay Sajip <[email protected]>
1 parent 316221c commit 078cdcc

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

Lib/logging/config.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2001-2019 by Vinay Sajip. All Rights Reserved.
1+
# Copyright 2001-2023 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-2019 Vinay Sajip. All Rights Reserved.
22+
Copyright (C) 2001-2023 Vinay Sajip. All Rights Reserved.
2323
2424
To use, simply 'import logging' and log away!
2525
"""
@@ -477,10 +477,10 @@ def configure_custom(self, config):
477477
c = config.pop('()')
478478
if not callable(c):
479479
c = self.resolve(c)
480-
props = config.pop('.', None)
481480
# Check for valid identifiers
482-
kwargs = {k: config[k] for k in config if valid_ident(k)}
481+
kwargs = {k: config[k] for k in config if (k != '.' and valid_ident(k))}
483482
result = c(**kwargs)
483+
props = config.pop('.', None)
484484
if props:
485485
for name, value in props.items():
486486
setattr(result, name, value)
@@ -752,8 +752,7 @@ def configure_handler(self, config):
752752
'address' in config:
753753
config['address'] = self.as_tuple(config['address'])
754754
factory = klass
755-
props = config.pop('.', None)
756-
kwargs = {k: config[k] for k in config if valid_ident(k)}
755+
kwargs = {k: config[k] for k in config if (k != '.' and valid_ident(k))}
757756
try:
758757
result = factory(**kwargs)
759758
except TypeError as te:
@@ -771,6 +770,7 @@ def configure_handler(self, config):
771770
result.setLevel(logging._checkLevel(level))
772771
if filters:
773772
self.add_filters(result, filters)
773+
props = config.pop('.', None)
774774
if props:
775775
for name, value in props.items():
776776
setattr(result, name, value)

Lib/test/test_logging.py

+40-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2001-2022 by Vinay Sajip. All Rights Reserved.
1+
# Copyright 2001-2023 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,
@@ -16,7 +16,7 @@
1616

1717
"""Test harness for the logging module. Run all tests.
1818
19-
Copyright (C) 2001-2022 Vinay Sajip. All Rights Reserved.
19+
Copyright (C) 2001-2023 Vinay Sajip. All Rights Reserved.
2020
"""
2121

2222
import logging
@@ -2881,6 +2881,39 @@ class ConfigDictTest(BaseTest):
28812881
},
28822882
}
28832883

2884+
class CustomFormatter(logging.Formatter):
2885+
custom_property = "."
2886+
2887+
def format(self, record):
2888+
return super().format(record)
2889+
2890+
config17 = {
2891+
'version': 1,
2892+
'formatters': {
2893+
"custom": {
2894+
"()": CustomFormatter,
2895+
"style": "{",
2896+
"datefmt": "%Y-%m-%d %H:%M:%S",
2897+
"format": "{message}", # <-- to force an exception when configuring
2898+
".": {
2899+
"custom_property": "value"
2900+
}
2901+
}
2902+
},
2903+
'handlers' : {
2904+
'hand1' : {
2905+
'class' : 'logging.StreamHandler',
2906+
'formatter' : 'custom',
2907+
'level' : 'NOTSET',
2908+
'stream' : 'ext://sys.stdout',
2909+
},
2910+
},
2911+
'root' : {
2912+
'level' : 'WARNING',
2913+
'handlers' : ['hand1'],
2914+
},
2915+
}
2916+
28842917
out_of_order = {
28852918
"version": 1,
28862919
"formatters": {
@@ -3295,6 +3328,11 @@ def cleanup(h1, fn):
32953328
handler = logging.root.handlers[0]
32963329
self.addCleanup(cleanup, handler, fn)
32973330

3331+
def test_config17_ok(self):
3332+
self.apply_config(self.config17)
3333+
h = logging._handlers['hand1']
3334+
self.assertEqual(h.formatter.custom_property, 'value')
3335+
32983336
def setup_via_listener(self, text, verify=None):
32993337
text = text.encode("utf-8")
33003338
# Ask for a randomly assigned port (by using port 0)

0 commit comments

Comments
 (0)