From 79f3ba25e079816ea26f642ccbbe991ca4c66207 Mon Sep 17 00:00:00 2001 From: Vinay Sajip Date: Thu, 9 Nov 2023 18:55:22 +0000 Subject: [PATCH 1/2] =?UTF-8?q?gh-110875:=20Handle=20'.'=20properties=20in?= =?UTF-8?q?=20logging=20formatter=20configuration=20c=E2=80=A6=20(GH-11094?= =?UTF-8?q?3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit a5f29c9faf046b9ef3e498a0bc63dbc29017b5e3) --- Lib/logging/config.py | 12 ++++++------ Lib/test/test_logging.py | 42 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/Lib/logging/config.py b/Lib/logging/config.py index 7e78a64a2f08a6..735ffbe1946780 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 @@ 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 @@ def configure_custom(self, config): 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 @@ def configure_handler(self, config): '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 @@ def configure_handler(self, config): 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 e097acd85eb72b..757cdc72bbc89c 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 @@ def cleanup(h1, fn): 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) From 4ffc96aeae9c4cef26d2ab5e94503ed7087eb877 Mon Sep 17 00:00:00 2001 From: Vinay Sajip Date: Thu, 9 Nov 2023 19:26:32 +0000 Subject: [PATCH 2/2] =?UTF-8?q?[3.11]=20gh-110875:=20Handle=20'.'=20proper?= =?UTF-8?q?ties=20in=20logging=20formatter=20configuration=20c=E2=80=A6=20?= =?UTF-8?q?(GH-110943).=20(cherry=20picked=20from=20commit=20a5f29c9faf046?= =?UTF-8?q?b9ef3e498a0bc63dbc29017b5e3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Vinay Sajip