Skip to content

Commit 09df271

Browse files
[3.12] gh-110875: Handle '.' properties in logging formatter configuration c… (GH-110943) (GH-111911)
Co-authored-by: Vinay Sajip <[email protected]>
1 parent fe7631e commit 09df271

File tree

2 files changed

+41
-5
lines changed

2 files changed

+41
-5
lines changed

Lib/logging/config.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -485,10 +485,10 @@ def configure_custom(self, config):
485485
c = config.pop('()')
486486
if not callable(c):
487487
c = self.resolve(c)
488-
props = config.pop('.', None)
489488
# Check for valid identifiers
490-
kwargs = {k: config[k] for k in config if valid_ident(k)}
489+
kwargs = {k: config[k] for k in config if (k != '.' and valid_ident(k))}
491490
result = c(**kwargs)
491+
props = config.pop('.', None)
492492
if props:
493493
for name, value in props.items():
494494
setattr(result, name, value)
@@ -841,8 +841,7 @@ def configure_handler(self, config):
841841
factory = functools.partial(self._configure_queue_handler, klass)
842842
else:
843843
factory = klass
844-
props = config.pop('.', None)
845-
kwargs = {k: config[k] for k in config if valid_ident(k)}
844+
kwargs = {k: config[k] for k in config if (k != '.' and valid_ident(k))}
846845
try:
847846
result = factory(**kwargs)
848847
except TypeError as te:
@@ -860,6 +859,7 @@ def configure_handler(self, config):
860859
result.setLevel(logging._checkLevel(level))
861860
if filters:
862861
self.add_filters(result, filters)
862+
props = config.pop('.', None)
863863
if props:
864864
for name, value in props.items():
865865
setattr(result, name, value)

Lib/test/test_logging.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3014,6 +3014,39 @@ class ConfigDictTest(BaseTest):
30143014
},
30153015
}
30163016

3017+
class CustomFormatter(logging.Formatter):
3018+
custom_property = "."
3019+
3020+
def format(self, record):
3021+
return super().format(record)
3022+
3023+
config17 = {
3024+
'version': 1,
3025+
'formatters': {
3026+
"custom": {
3027+
"()": CustomFormatter,
3028+
"style": "{",
3029+
"datefmt": "%Y-%m-%d %H:%M:%S",
3030+
"format": "{message}", # <-- to force an exception when configuring
3031+
".": {
3032+
"custom_property": "value"
3033+
}
3034+
}
3035+
},
3036+
'handlers' : {
3037+
'hand1' : {
3038+
'class' : 'logging.StreamHandler',
3039+
'formatter' : 'custom',
3040+
'level' : 'NOTSET',
3041+
'stream' : 'ext://sys.stdout',
3042+
},
3043+
},
3044+
'root' : {
3045+
'level' : 'WARNING',
3046+
'handlers' : ['hand1'],
3047+
},
3048+
}
3049+
30173050
bad_format = {
30183051
"version": 1,
30193052
"formatters": {
@@ -3495,7 +3528,10 @@ def test_config16_ok(self):
34953528
{'msg': 'Hello'}))
34963529
self.assertEqual(result, 'Hello ++ defaultvalue')
34973530

3498-
3531+
def test_config17_ok(self):
3532+
self.apply_config(self.config17)
3533+
h = logging._handlers['hand1']
3534+
self.assertEqual(h.formatter.custom_property, 'value')
34993535

35003536
def setup_via_listener(self, text, verify=None):
35013537
text = text.encode("utf-8")

0 commit comments

Comments
 (0)