Skip to content

Commit ba3e19a

Browse files
[3.12] gh-111615: Fix regression in QueueHandler configuration. (GH-111638) (GH-113507)
1 parent 6177a85 commit ba3e19a

File tree

3 files changed

+40
-17
lines changed

3 files changed

+40
-17
lines changed

Lib/logging/config.py

+19-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2001-2022 by Vinay Sajip. All Rights Reserved.
1+
# Copyright 2001-2023 by Vinay Sajip. All Rights Reserved.
22
#
33
# Permission to use, copy, modify, and distribute this software and its
44
# documentation for any purpose and without fee is hereby granted,
@@ -740,7 +740,7 @@ def _configure_queue_handler(self, klass, **kwargs):
740740
lklass = kwargs['listener']
741741
else:
742742
lklass = logging.handlers.QueueListener
743-
listener = lklass(q, *kwargs['handlers'], respect_handler_level=rhl)
743+
listener = lklass(q, *kwargs.get('handlers', []), respect_handler_level=rhl)
744744
handler = klass(q)
745745
handler.listener = listener
746746
return handler
@@ -782,11 +782,12 @@ def configure_handler(self, config):
782782
raise ValueError('Unable to set target handler %r' % tn) from e
783783
elif issubclass(klass, logging.handlers.QueueHandler):
784784
# Another special case for handler which refers to other handlers
785-
if 'handlers' not in config:
786-
raise ValueError('No handlers specified for a QueueHandler')
785+
# if 'handlers' not in config:
786+
# raise ValueError('No handlers specified for a QueueHandler')
787787
if 'queue' in config:
788+
from multiprocessing.queues import Queue as MPQueue
788789
qspec = config['queue']
789-
if not isinstance(qspec, queue.Queue):
790+
if not isinstance(qspec, (queue.Queue, MPQueue)):
790791
if isinstance(qspec, str):
791792
q = self.resolve(qspec)
792793
if not callable(q):
@@ -819,18 +820,19 @@ def configure_handler(self, config):
819820
if not callable(listener):
820821
raise TypeError('Invalid listener specifier %r' % lspec)
821822
config['listener'] = listener
822-
hlist = []
823-
try:
824-
for hn in config['handlers']:
825-
h = self.config['handlers'][hn]
826-
if not isinstance(h, logging.Handler):
827-
config.update(config_copy) # restore for deferred cfg
828-
raise TypeError('Required handler %r '
829-
'is not configured yet' % hn)
830-
hlist.append(h)
831-
except Exception as e:
832-
raise ValueError('Unable to set required handler %r' % hn) from e
833-
config['handlers'] = hlist
823+
if 'handlers' in config:
824+
hlist = []
825+
try:
826+
for hn in config['handlers']:
827+
h = self.config['handlers'][hn]
828+
if not isinstance(h, logging.Handler):
829+
config.update(config_copy) # restore for deferred cfg
830+
raise TypeError('Required handler %r '
831+
'is not configured yet' % hn)
832+
hlist.append(h)
833+
except Exception as e:
834+
raise ValueError('Unable to set required handler %r' % hn) from e
835+
config['handlers'] = hlist
834836
elif issubclass(klass, logging.handlers.SMTPHandler) and\
835837
'mailhost' in config:
836838
config['mailhost'] = self.as_tuple(config['mailhost'])

Lib/test/test_logging.py

+19
Original file line numberDiff line numberDiff line change
@@ -3892,6 +3892,25 @@ def test_90195(self):
38923892
# Logger should be enabled, since explicitly mentioned
38933893
self.assertFalse(logger.disabled)
38943894

3895+
def test_111615(self):
3896+
# See gh-111615
3897+
import multiprocessing as mp
3898+
3899+
config = {
3900+
'version': 1,
3901+
'handlers': {
3902+
'sink': {
3903+
'class': 'logging.handlers.QueueHandler',
3904+
'queue': mp.get_context('spawn').Queue(),
3905+
},
3906+
},
3907+
'root': {
3908+
'handlers': ['sink'],
3909+
'level': 'DEBUG',
3910+
},
3911+
}
3912+
logging.config.dictConfig(config)
3913+
38953914
class ManagerTest(BaseTest):
38963915
def test_manager_loggerclass(self):
38973916
logged = []
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a regression caused by a fix to gh-93162 whereby you couldn't configure
2+
a :class:`QueueHandler` without specifying handlers.

0 commit comments

Comments
 (0)