]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-111615: Fix regression in QueueHandler configuration. (GH-111638)
authorVinay Sajip <vinay_sajip@yahoo.co.uk>
Wed, 27 Dec 2023 09:35:15 +0000 (09:35 +0000)
committerGitHub <noreply@github.com>
Wed, 27 Dec 2023 09:35:15 +0000 (09:35 +0000)
Lib/logging/config.py
Lib/test/test_logging.py
Misc/NEWS.d/next/Library/2023-11-02-10-13-31.gh-issue-111615.3SMixi.rst [new file with mode: 0644]

index 4b520e3b1e0da6ff2c3e857a9523c3b12d210e10..de06090942d9658f4a37c4e7f3b5984ccde54b45 100644 (file)
@@ -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,
@@ -734,7 +734,7 @@ class DictConfigurator(BaseConfigurator):
             lklass = kwargs['listener']
         else:
             lklass = logging.handlers.QueueListener
-        listener = lklass(q, *kwargs['handlers'], respect_handler_level=rhl)
+        listener = lklass(q, *kwargs.get('handlers', []), respect_handler_level=rhl)
         handler = klass(q)
         handler.listener = listener
         return handler
@@ -776,11 +776,12 @@ class DictConfigurator(BaseConfigurator):
                     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:
-                    raise ValueError('No handlers specified for a QueueHandler')
+                if 'handlers' not in config:
+                    raise ValueError('No handlers specified for a QueueHandler')
                 if 'queue' in config:
+                    from multiprocessing.queues import Queue as MPQueue
                     qspec = config['queue']
-                    if not isinstance(qspec, queue.Queue):
+                    if not isinstance(qspec, (queue.Queue, MPQueue)):
                         if isinstance(qspec, str):
                             q = self.resolve(qspec)
                             if not callable(q):
@@ -813,18 +814,19 @@ class DictConfigurator(BaseConfigurator):
                         if not callable(listener):
                             raise TypeError('Invalid listener specifier %r' % lspec)
                         config['listener'] = listener
-                hlist = []
-                try:
-                    for hn in config['handlers']:
-                        h = self.config['handlers'][hn]
-                        if not isinstance(h, logging.Handler):
-                            config.update(config_copy)  # restore for deferred cfg
-                            raise TypeError('Required handler %r '
-                                            'is not configured yet' % hn)
-                        hlist.append(h)
-                except Exception as e:
-                    raise ValueError('Unable to set required handler %r' % hn) from e
-                config['handlers'] = hlist
+                if 'handlers' in config:
+                    hlist = []
+                    try:
+                        for hn in config['handlers']:
+                            h = self.config['handlers'][hn]
+                            if not isinstance(h, logging.Handler):
+                                config.update(config_copy)  # restore for deferred cfg
+                                raise TypeError('Required handler %r '
+                                                'is not configured yet' % hn)
+                            hlist.append(h)
+                    except Exception as e:
+                        raise ValueError('Unable to set required handler %r' % hn) from e
+                    config['handlers'] = hlist
             elif issubclass(klass, logging.handlers.SMTPHandler) and\
                 'mailhost' in config:
                 config['mailhost'] = self.as_tuple(config['mailhost'])
index 89be432e4b78c09e22936f33f44eb4449e2b5115..33db5d6443f6fd8c4efc0f964de2154c75ef54ab 100644 (file)
@@ -3922,6 +3922,25 @@ class ConfigDictTest(BaseTest):
         # Logger should be enabled, since explicitly mentioned
         self.assertFalse(logger.disabled)
 
+    def test_111615(self):
+        # See gh-111615
+        import multiprocessing as mp
+
+        config = {
+            'version': 1,
+            'handlers': {
+                'sink': {
+                    'class': 'logging.handlers.QueueHandler',
+                    'queue': mp.get_context('spawn').Queue(),
+                },
+            },
+            'root': {
+                'handlers': ['sink'],
+                'level': 'DEBUG',
+            },
+        }
+        logging.config.dictConfig(config)
+
 class ManagerTest(BaseTest):
     def test_manager_loggerclass(self):
         logged = []
diff --git a/Misc/NEWS.d/next/Library/2023-11-02-10-13-31.gh-issue-111615.3SMixi.rst b/Misc/NEWS.d/next/Library/2023-11-02-10-13-31.gh-issue-111615.3SMixi.rst
new file mode 100644 (file)
index 0000000..f80ab00
--- /dev/null
@@ -0,0 +1,2 @@
+Fix a regression caused by a fix to gh-93162 whereby you couldn't configure
+a :class:`QueueHandler` without specifying handlers.