From 6d0bb43232dd6ebc5245daa4fe29f07f815f0bad Mon Sep 17 00:00:00 2001 From: Vinay Sajip Date: Wed, 17 Apr 2024 13:55:18 +0100 Subject: [PATCH] gh-117975: Ensure flush level is checked when configuring a logging MemoryHandler. (GH-117976) --- Lib/logging/config.py | 26 ++++++++++++++------------ Lib/test/test_logging.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/Lib/logging/config.py b/Lib/logging/config.py index ea37dd75445..860e4751207 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -761,18 +761,20 @@ class DictConfigurator(BaseConfigurator): klass = cname else: klass = self.resolve(cname) - if issubclass(klass, logging.handlers.MemoryHandler) and\ - 'target' in config: - # Special case for handler which refers to another handler - try: - tn = config['target'] - th = self.config['handlers'][tn] - if not isinstance(th, logging.Handler): - config.update(config_copy) # restore for deferred cfg - raise TypeError('target not configured yet') - config['target'] = th - except Exception as e: - raise ValueError('Unable to set target handler %r' % tn) from e + if issubclass(klass, logging.handlers.MemoryHandler): + if 'flushLevel' in config: + config['flushLevel'] = logging._checkLevel(config['flushLevel']) + if 'target' in config: + # Special case for handler which refers to another handler + try: + tn = config['target'] + th = self.config['handlers'][tn] + if not isinstance(th, logging.Handler): + config.update(config_copy) # restore for deferred cfg + raise TypeError('target not configured yet') + config['target'] = th + except Exception as e: + raise ValueError('Unable to set target handler %r' % tn) from e elif issubclass(klass, logging.handlers.QueueHandler): # Another special case for handler which refers to other handlers # if 'handlers' not in config: diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 3f0b363066d..826b7381686 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -3036,6 +3036,30 @@ class ConfigDictTest(BaseTest): }, } + config18 = { + "version": 1, + "handlers": { + "console": { + "class": "logging.StreamHandler", + "level": "DEBUG", + }, + "buffering": { + "class": "logging.handlers.MemoryHandler", + "capacity": 5, + "target": "console", + "level": "DEBUG", + "flushLevel": "ERROR" + } + }, + "loggers": { + "mymodule": { + "level": "DEBUG", + "handlers": ["buffering"], + "propagate": "true" + } + } + } + bad_format = { "version": 1, "formatters": { @@ -3522,6 +3546,11 @@ class ConfigDictTest(BaseTest): h = logging._handlers['hand1'] self.assertEqual(h.formatter.custom_property, 'value') + def test_config18_ok(self): + self.apply_config(self.config18) + handler = logging.getLogger('mymodule').handlers[0] + self.assertEqual(handler.flushLevel, logging.ERROR) + def setup_via_listener(self, text, verify=None): text = text.encode("utf-8") # Ask for a randomly assigned port (by using port 0)