summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVinay Sajip <vinay_sajip@yahoo.co.uk>2023-11-09 19:51:43 (GMT)
committerGitHub <noreply@github.com>2023-11-09 19:51:43 (GMT)
commit078cdccc2ae343ed66cfc044c8150575f8d6cf94 (patch)
tree16c8937672a4e67b0b19a85ab2c1c60f4c27aa97
parent316221c23ff1b8acfe5c51298373464191c7d47f (diff)
downloadcpython-078cdccc2ae343ed66cfc044c8150575f8d6cf94.zip
cpython-078cdccc2ae343ed66cfc044c8150575f8d6cf94.tar.gz
cpython-078cdccc2ae343ed66cfc044c8150575f8d6cf94.tar.bz2
[3.11] gh-110875: Handle '.' properties in logging formatter configuration correctly. (GH-110943) (GH-111914)
Co-authored-by: Vinay Sajip <vinay_sajip@yahoo.co.uk>
-rw-r--r--Lib/logging/config.py12
-rw-r--r--Lib/test/test_logging.py42
2 files changed, 46 insertions, 8 deletions
diff --git a/Lib/logging/config.py b/Lib/logging/config.py
index 7e78a64..735ffbe 100644
--- a/Lib/logging/config.py
+++ b/Lib/logging/config.py
@@ -1,4 +1,4 @@
-# Copyright 2001-2019 by Vinay Sajip. All Rights Reserved.
+# Copyright 2001-2023 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-2019 Vinay Sajip. All Rights Reserved.
+Copyright (C) 2001-2023 Vinay Sajip. All Rights Reserved.
To use, simply 'import logging' and log away!
"""
@@ -477,10 +477,10 @@ class BaseConfigurator(object):
c = config.pop('()')
if not callable(c):
c = self.resolve(c)
- props = config.pop('.', None)
# Check for valid identifiers
- kwargs = {k: config[k] for k in config if valid_ident(k)}
+ kwargs = {k: config[k] for k in config if (k != '.' and valid_ident(k))}
result = c(**kwargs)
+ props = config.pop('.', None)
if props:
for name, value in props.items():
setattr(result, name, value)
@@ -752,8 +752,7 @@ class DictConfigurator(BaseConfigurator):
'address' in config:
config['address'] = self.as_tuple(config['address'])
factory = klass
- props = config.pop('.', None)
- kwargs = {k: config[k] for k in config if valid_ident(k)}
+ kwargs = {k: config[k] for k in config if (k != '.' and valid_ident(k))}
try:
result = factory(**kwargs)
except TypeError as te:
@@ -771,6 +770,7 @@ class DictConfigurator(BaseConfigurator):
result.setLevel(logging._checkLevel(level))
if filters:
self.add_filters(result, filters)
+ props = config.pop('.', None)
if props:
for name, value in props.items():
setattr(result, name, value)
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index e097acd..757cdc7 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -1,4 +1,4 @@
-# Copyright 2001-2022 by Vinay Sajip. All Rights Reserved.
+# Copyright 2001-2023 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,
@@ -16,7 +16,7 @@
"""Test harness for the logging module. Run all tests.
-Copyright (C) 2001-2022 Vinay Sajip. All Rights Reserved.
+Copyright (C) 2001-2023 Vinay Sajip. All Rights Reserved.
"""
import logging
@@ -2881,6 +2881,39 @@ class ConfigDictTest(BaseTest):
},
}
+ class CustomFormatter(logging.Formatter):
+ custom_property = "."
+
+ def format(self, record):
+ return super().format(record)
+
+ config17 = {
+ 'version': 1,
+ 'formatters': {
+ "custom": {
+ "()": CustomFormatter,
+ "style": "{",
+ "datefmt": "%Y-%m-%d %H:%M:%S",
+ "format": "{message}", # <-- to force an exception when configuring
+ ".": {
+ "custom_property": "value"
+ }
+ }
+ },
+ 'handlers' : {
+ 'hand1' : {
+ 'class' : 'logging.StreamHandler',
+ 'formatter' : 'custom',
+ 'level' : 'NOTSET',
+ 'stream' : 'ext://sys.stdout',
+ },
+ },
+ 'root' : {
+ 'level' : 'WARNING',
+ 'handlers' : ['hand1'],
+ },
+ }
+
out_of_order = {
"version": 1,
"formatters": {
@@ -3295,6 +3328,11 @@ class ConfigDictTest(BaseTest):
handler = logging.root.handlers[0]
self.addCleanup(cleanup, handler, fn)
+ def test_config17_ok(self):
+ self.apply_config(self.config17)
+ h = logging._handlers['hand1']
+ self.assertEqual(h.formatter.custom_property, 'value')
+
def setup_via_listener(self, text, verify=None):
text = text.encode("utf-8")
# Ask for a randomly assigned port (by using port 0)