14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#!/usr/bin/env python
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Copyright 2001-2010 by Vinay Sajip. All Rights Reserved.
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Permission to use, copy, modify, and distribute this software and its
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# documentation for any purpose and without fee is hereby granted,
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# provided that the above copyright notice appear in all copies and that
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# both that copyright notice and this permission notice appear in
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# supporting documentation, and that the name of Vinay Sajip
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# not be used in advertising or publicity pertaining to distribution
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# of the software without specific, written prior permission.
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"""Test harness for the logging module. Run all tests.
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmCopyright (C) 2001-2010 Vinay Sajip. All Rights Reserved.
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"""
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport logging
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport logging.handlers
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport logging.config
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport codecs
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport cPickle
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport cStringIO
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport gc
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport json
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport os
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport re
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport select
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport socket
374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom SocketServer import ThreadingTCPServer, StreamRequestHandler
384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport struct
394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport sys
404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport tempfile
414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom test.test_support import captured_stdout, run_with_locale, run_unittest
424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport textwrap
434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport unittest
444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport warnings
454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport weakref
464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtry:
474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    import threading
484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmexcept ImportError:
494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    threading = None
504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass BaseTest(unittest.TestCase):
524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Base class for logging tests."""
544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    log_format = "%(name)s -> %(levelname)s: %(message)s"
564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    expected_log_pat = r"^([\w.]+) -> ([\w]+): ([\d]+)$"
574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    message_num = 0
584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setUp(self):
604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Setup the default logging stream to an internal StringIO instance,
614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        so that we can examine log output as we want."""
624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        logger_dict = logging.getLogger().manager.loggerDict
634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        logging._acquireLock()
644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.saved_handlers = logging._handlers.copy()
664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.saved_handler_list = logging._handlerList[:]
674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.saved_loggers = logger_dict.copy()
684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.saved_level_names = logging._levelNames.copy()
694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logging._releaseLock()
714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Set two unused loggers: one non-ASCII and one Unicode.
734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # This is to test correct operation when sorting existing
744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # loggers in the configuration code. See issue 8201.
754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        logging.getLogger("\xab\xd7\xbb")
764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        logging.getLogger(u"\u013f\u00d6\u0047")
774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_logger = logging.getLogger("")
794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.original_logging_level = self.root_logger.getEffectiveLevel()
804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.stream = cStringIO.StringIO()
824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_logger.setLevel(logging.DEBUG)
834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_hdlr = logging.StreamHandler(self.stream)
844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_formatter = logging.Formatter(self.log_format)
854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_hdlr.setFormatter(self.root_formatter)
864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_logger.addHandler(self.root_hdlr)
874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def tearDown(self):
894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Remove our logging stream, and restore the original logging
904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        level."""
914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.stream.close()
924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_logger.removeHandler(self.root_hdlr)
934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        while self.root_logger.handlers:
944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            h = self.root_logger.handlers[0]
954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.root_logger.removeHandler(h)
964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            h.close()
974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_logger.setLevel(self.original_logging_level)
984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        logging._acquireLock()
994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logging._levelNames.clear()
1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logging._levelNames.update(self.saved_level_names)
1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logging._handlers.clear()
1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logging._handlers.update(self.saved_handlers)
1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logging._handlerList[:] = self.saved_handler_list
1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            loggerDict = logging.getLogger().manager.loggerDict
1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            loggerDict.clear()
1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            loggerDict.update(self.saved_loggers)
1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logging._releaseLock()
1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def assert_log_lines(self, expected_values, stream=None):
1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Match the collected log lines against the regular expression
1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.expected_log_pat, and compare the extracted group values to
1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        the expected_values list of tuples."""
1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        stream = stream or self.stream
1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pat = re.compile(self.expected_log_pat)
1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            stream.reset()
1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            actual_lines = stream.readlines()
1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except AttributeError:
1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # StringIO.StringIO lacks a reset() method.
1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            actual_lines = stream.getvalue().splitlines()
1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(len(actual_lines), len(expected_values))
1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for actual, expected in zip(actual_lines, expected_values):
1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            match = pat.search(actual)
1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not match:
1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail("Log line does not match expected pattern:\n" +
1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            actual)
1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(tuple(match.groups()), expected)
1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s = stream.read()
1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if s:
1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.fail("Remaining output at end of log stream:\n" + s)
1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def next_message(self):
1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Generate a message consisting solely of an auto-incrementing
1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        integer."""
1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.message_num += 1
1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return "%d" % self.message_num
1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass BuiltinLevelsTest(BaseTest):
1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test builtin levels and their inheritance."""
1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_flat(self):
1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #Logging levels in a flat logger namespace.
1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = self.next_message
1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ERR = logging.getLogger("ERR")
1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ERR.setLevel(logging.ERROR)
1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF = logging.getLogger("INF")
1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF.setLevel(logging.INFO)
1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        DEB = logging.getLogger("DEB")
1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        DEB.setLevel(logging.DEBUG)
1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # These should log.
1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ERR.log(logging.CRITICAL, m())
1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ERR.error(m())
1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF.log(logging.CRITICAL, m())
1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF.error(m())
1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF.warn(m())
1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF.info(m())
1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        DEB.log(logging.CRITICAL, m())
1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        DEB.error(m())
1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        DEB.warn (m())
1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        DEB.info (m())
1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        DEB.debug(m())
1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # These should not log.
1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ERR.warn(m())
1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ERR.info(m())
1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ERR.debug(m())
1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF.debug(m())
1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assert_log_lines([
1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('ERR', 'CRITICAL', '1'),
1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('ERR', 'ERROR', '2'),
1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF', 'CRITICAL', '3'),
1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF', 'ERROR', '4'),
1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF', 'WARNING', '5'),
1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF', 'INFO', '6'),
1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('DEB', 'CRITICAL', '7'),
1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('DEB', 'ERROR', '8'),
1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('DEB', 'WARNING', '9'),
1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('DEB', 'INFO', '10'),
1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('DEB', 'DEBUG', '11'),
1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ])
1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_nested_explicit(self):
1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Logging levels in a nested namespace, all explicitly set.
1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = self.next_message
1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF = logging.getLogger("INF")
1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF.setLevel(logging.INFO)
1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR  = logging.getLogger("INF.ERR")
1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR.setLevel(logging.ERROR)
1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # These should log.
2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR.log(logging.CRITICAL, m())
2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR.error(m())
2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # These should not log.
2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR.warn(m())
2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR.info(m())
2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR.debug(m())
2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assert_log_lines([
2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF.ERR', 'CRITICAL', '1'),
2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF.ERR', 'ERROR', '2'),
2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ])
2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_nested_inherited(self):
2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #Logging levels in a nested namespace, inherited from parent loggers.
2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = self.next_message
2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF = logging.getLogger("INF")
2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF.setLevel(logging.INFO)
2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR  = logging.getLogger("INF.ERR")
2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR.setLevel(logging.ERROR)
2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_UNDEF = logging.getLogger("INF.UNDEF")
2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF")
2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        UNDEF = logging.getLogger("UNDEF")
2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # These should log.
2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_UNDEF.log(logging.CRITICAL, m())
2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_UNDEF.error(m())
2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_UNDEF.warn(m())
2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_UNDEF.info(m())
2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR_UNDEF.log(logging.CRITICAL, m())
2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR_UNDEF.error(m())
2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # These should not log.
2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_UNDEF.debug(m())
2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR_UNDEF.warn(m())
2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR_UNDEF.info(m())
2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF_ERR_UNDEF.debug(m())
2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assert_log_lines([
2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF.UNDEF', 'CRITICAL', '1'),
2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF.UNDEF', 'ERROR', '2'),
2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF.UNDEF', 'WARNING', '3'),
2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF.UNDEF', 'INFO', '4'),
2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF.ERR.UNDEF', 'CRITICAL', '5'),
2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF.ERR.UNDEF', 'ERROR', '6'),
2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ])
2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_nested_with_virtual_parent(self):
2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Logging levels when some parent does not exist yet.
2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = self.next_message
2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF = logging.getLogger("INF")
2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        GRANDCHILD = logging.getLogger("INF.BADPARENT.UNDEF")
2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        CHILD = logging.getLogger("INF.BADPARENT")
2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        INF.setLevel(logging.INFO)
2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # These should log.
2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        GRANDCHILD.log(logging.FATAL, m())
2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        GRANDCHILD.info(m())
2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        CHILD.log(logging.FATAL, m())
2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        CHILD.info(m())
2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # These should not log.
2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        GRANDCHILD.debug(m())
2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        CHILD.debug(m())
2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assert_log_lines([
2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF.BADPARENT.UNDEF', 'CRITICAL', '1'),
2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF.BADPARENT.UNDEF', 'INFO', '2'),
2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF.BADPARENT', 'CRITICAL', '3'),
2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INF.BADPARENT', 'INFO', '4'),
2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ])
2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass BasicFilterTest(BaseTest):
2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test the bundled Filter class."""
2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_filter(self):
2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Only messages satisfying the specified criteria pass through the
2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #  filter.
2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        filter_ = logging.Filter("spam.eggs")
2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        handler = self.root_logger.handlers[0]
2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            handler.addFilter(filter_)
2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            spam = logging.getLogger("spam")
2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            spam_eggs = logging.getLogger("spam.eggs")
2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            spam_eggs_fish = logging.getLogger("spam.eggs.fish")
2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            spam_bakedbeans = logging.getLogger("spam.bakedbeans")
2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            spam.info(self.next_message())
2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            spam_eggs.info(self.next_message())  # Good.
2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            spam_eggs_fish.info(self.next_message())  # Good.
2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            spam_bakedbeans.info(self.next_message())
2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('spam.eggs', 'INFO', '2'),
2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('spam.eggs.fish', 'INFO', '3'),
3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ])
3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            handler.removeFilter(filter_)
3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#
3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#   First, we define our levels. There can be as many as you want - the only
3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#     limitations are that they should be integers, the lowest should be > 0 and
3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#   larger values mean less information being logged. If you need specific
3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#   level values which do not fit into these limitations, you can use a
3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#   mapping dictionary to convert between your application levels and the
3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#   logging system.
3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#
3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSILENT      = 120
3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTACITURN    = 119
3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTERSE       = 118
3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmEFFUSIVE    = 117
3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSOCIABLE    = 116
3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmVERBOSE     = 115
3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTALKATIVE   = 114
3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmGARRULOUS   = 113
3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmCHATTERBOX  = 112
3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmBORING      = 111
3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmLEVEL_RANGE = range(BORING, SILENT + 1)
3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#
3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#   Next, we define names for our levels. You don't need to do this - in which
3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#   case the system will use "Level n" to denote the text for the level.
3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#
3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmy_logging_levels = {
3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    SILENT      : 'Silent',
3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    TACITURN    : 'Taciturn',
3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    TERSE       : 'Terse',
3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    EFFUSIVE    : 'Effusive',
3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    SOCIABLE    : 'Sociable',
3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    VERBOSE     : 'Verbose',
3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    TALKATIVE   : 'Talkative',
3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    GARRULOUS   : 'Garrulous',
3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHATTERBOX  : 'Chatterbox',
3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    BORING      : 'Boring',
3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass GarrulousFilter(logging.Filter):
3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """A filter which blocks garrulous messages."""
3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def filter(self, record):
3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return record.levelno != GARRULOUS
3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass VerySpecificFilter(logging.Filter):
3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """A filter which blocks sociable and taciturn messages."""
3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def filter(self, record):
3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return record.levelno not in [SOCIABLE, TACITURN]
3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass CustomLevelsAndFiltersTest(BaseTest):
3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test various filtering possibilities with custom logging levels."""
3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # Skip the logger name group.
3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    expected_log_pat = r"^[\w.]+ -> ([\w]+): ([\d]+)$"
3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setUp(self):
3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        BaseTest.setUp(self)
3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for k, v in my_logging_levels.items():
3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logging.addLevelName(k, v)
3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def log_at_all_levels(self, logger):
3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for lvl in LEVEL_RANGE:
3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.log(lvl, self.next_message())
3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_logger_filter(self):
3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Filter at logger level.
3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_logger.setLevel(VERBOSE)
3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Levels >= 'Verbose' are good.
3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.log_at_all_levels(self.root_logger)
3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assert_log_lines([
3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('Verbose', '5'),
3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('Sociable', '6'),
3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('Effusive', '7'),
3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('Terse', '8'),
3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('Taciturn', '9'),
3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('Silent', '10'),
3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ])
3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_handler_filter(self):
3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Filter at handler level.
3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_logger.handlers[0].setLevel(SOCIABLE)
3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Levels >= 'Sociable' are good.
3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.log_at_all_levels(self.root_logger)
3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Sociable', '6'),
3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Effusive', '7'),
3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Terse', '8'),
3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Taciturn', '9'),
3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Silent', '10'),
4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ])
4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.root_logger.handlers[0].setLevel(logging.NOTSET)
4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_specific_filters(self):
4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Set a specific filter object on the handler, and then add another
4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #  filter object on the logger itself.
4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        handler = self.root_logger.handlers[0]
4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        specific_filter = None
4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        garr = GarrulousFilter()
4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        handler.addFilter(garr)
4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.log_at_all_levels(self.root_logger)
4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            first_lines = [
4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # Notice how 'Garrulous' is missing
4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Boring', '1'),
4164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Chatterbox', '2'),
4174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Talkative', '4'),
4184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Verbose', '5'),
4194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Sociable', '6'),
4204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Effusive', '7'),
4214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Terse', '8'),
4224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Taciturn', '9'),
4234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Silent', '10'),
4244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ]
4254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines(first_lines)
4264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            specific_filter = VerySpecificFilter()
4284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.root_logger.addFilter(specific_filter)
4294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.log_at_all_levels(self.root_logger)
4304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines(first_lines + [
4314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # Not only 'Garrulous' is still missing, but also 'Sociable'
4324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # and 'Taciturn'
4334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Boring', '11'),
4344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Chatterbox', '12'),
4354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Talkative', '14'),
4364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Verbose', '15'),
4374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Effusive', '17'),
4384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Terse', '18'),
4394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('Silent', '20'),
4404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ])
4414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
4424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if specific_filter:
4434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.root_logger.removeFilter(specific_filter)
4444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            handler.removeFilter(garr)
4454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass MemoryHandlerTest(BaseTest):
4484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Tests for the MemoryHandler."""
4504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # Do not bother with a logger name group.
4524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    expected_log_pat = r"^[\w.]+ -> ([\w]+): ([\d]+)$"
4534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setUp(self):
4554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        BaseTest.setUp(self)
4564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.mem_hdlr = logging.handlers.MemoryHandler(10, logging.WARNING,
4574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                                        self.root_hdlr)
4584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.mem_logger = logging.getLogger('mem')
4594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.mem_logger.propagate = 0
4604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.mem_logger.addHandler(self.mem_hdlr)
4614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def tearDown(self):
4634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.mem_hdlr.close()
4644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        BaseTest.tearDown(self)
4654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_flush(self):
4674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # The memory handler flushes to its target handler based on specific
4684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #  criteria (message count and message level).
4694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.mem_logger.debug(self.next_message())
4704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assert_log_lines([])
4714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.mem_logger.info(self.next_message())
4724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assert_log_lines([])
4734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # This will flush because the level is >= logging.WARNING
4744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.mem_logger.warn(self.next_message())
4754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        lines = [
4764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('DEBUG', '1'),
4774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('INFO', '2'),
4784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('WARNING', '3'),
4794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ]
4804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assert_log_lines(lines)
4814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for n in (4, 14):
4824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for i in range(9):
4834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.mem_logger.debug(self.next_message())
4844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines(lines)
4854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # This will flush because it's the 10th message since the last
4864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #  flush.
4874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.mem_logger.debug(self.next_message())
4884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            lines = lines + [('DEBUG', str(i)) for i in range(n, n + 10)]
4894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines(lines)
4904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.mem_logger.debug(self.next_message())
4924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assert_log_lines(lines)
4934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass ExceptionFormatter(logging.Formatter):
4964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """A special exception formatter."""
4974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def formatException(self, ei):
4984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return "Got a [%s]" % ei[0].__name__
4994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass ConfigFileTest(BaseTest):
5024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Reading logging config from a .ini-style config file."""
5044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    expected_log_pat = r"^([\w]+) \+\+ ([\w]+)$"
5064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config0 is a standard configuration.
5084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config0 = """
5094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [loggers]
5104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=root
5114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [handlers]
5134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=hand1
5144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [formatters]
5164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=form1
5174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [logger_root]
5194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=WARNING
5204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    handlers=hand1
5214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [handler_hand1]
5234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class=StreamHandler
5244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=NOTSET
5254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    formatter=form1
5264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    args=(sys.stdout,)
5274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [formatter_form1]
5294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    format=%(levelname)s ++ %(message)s
5304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    datefmt=
5314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
5324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config1 adds a little to the standard configuration.
5344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config1 = """
5354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [loggers]
5364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=root,parser
5374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [handlers]
5394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=hand1
5404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [formatters]
5424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=form1
5434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [logger_root]
5454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=WARNING
5464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    handlers=
5474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [logger_parser]
5494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=DEBUG
5504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    handlers=hand1
5514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    propagate=1
5524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    qualname=compiler.parser
5534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [handler_hand1]
5554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class=StreamHandler
5564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=NOTSET
5574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    formatter=form1
5584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    args=(sys.stdout,)
5594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [formatter_form1]
5614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    format=%(levelname)s ++ %(message)s
5624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    datefmt=
5634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
5644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config1a moves the handler to the root.
5664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config1a = """
5674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [loggers]
5684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=root,parser
5694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [handlers]
5714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=hand1
5724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [formatters]
5744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=form1
5754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [logger_root]
5774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=WARNING
5784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    handlers=hand1
5794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [logger_parser]
5814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=DEBUG
5824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    handlers=
5834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    propagate=1
5844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    qualname=compiler.parser
5854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [handler_hand1]
5874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class=StreamHandler
5884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=NOTSET
5894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    formatter=form1
5904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    args=(sys.stdout,)
5914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [formatter_form1]
5934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    format=%(levelname)s ++ %(message)s
5944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    datefmt=
5954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
5964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config2 has a subtle configuration error that should be reported
5984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config2 = config1.replace("sys.stdout", "sys.stbout")
5994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config3 has a less subtle configuration error
6014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config3 = config1.replace("formatter=form1", "formatter=misspelled_name")
6024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config4 specifies a custom formatter class to be loaded
6044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config4 = """
6054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [loggers]
6064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=root
6074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [handlers]
6094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=hand1
6104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [formatters]
6124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=form1
6134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [logger_root]
6154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=NOTSET
6164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    handlers=hand1
6174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [handler_hand1]
6194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class=StreamHandler
6204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=NOTSET
6214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    formatter=form1
6224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    args=(sys.stdout,)
6234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [formatter_form1]
6254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class=""" + __name__ + """.ExceptionFormatter
6264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    format=%(levelname)s:%(name)s:%(message)s
6274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    datefmt=
6284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
6294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config5 specifies a custom handler class to be loaded
6314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config5 = config1.replace('class=StreamHandler', 'class=logging.StreamHandler')
6324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config6 uses ', ' delimiters in the handlers and formatters sections
6344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config6 = """
6354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [loggers]
6364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=root,parser
6374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [handlers]
6394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=hand1, hand2
6404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [formatters]
6424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=form1, form2
6434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [logger_root]
6454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=WARNING
6464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    handlers=
6474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [logger_parser]
6494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=DEBUG
6504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    handlers=hand1
6514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    propagate=1
6524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    qualname=compiler.parser
6534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [handler_hand1]
6554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class=StreamHandler
6564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=NOTSET
6574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    formatter=form1
6584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    args=(sys.stdout,)
6594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [handler_hand2]
6614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class=StreamHandler
6624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=NOTSET
6634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    formatter=form1
6644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    args=(sys.stderr,)
6654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [formatter_form1]
6674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    format=%(levelname)s ++ %(message)s
6684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    datefmt=
6694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [formatter_form2]
6714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    format=%(message)s
6724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    datefmt=
6734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
6744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config7 adds a compiler logger.
6764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config7 = """
6774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [loggers]
6784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=root,parser,compiler
6794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [handlers]
6814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=hand1
6824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [formatters]
6844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    keys=form1
6854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [logger_root]
6874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=WARNING
6884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    handlers=hand1
6894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [logger_compiler]
6914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=DEBUG
6924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    handlers=
6934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    propagate=1
6944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    qualname=compiler
6954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [logger_parser]
6974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=DEBUG
6984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    handlers=
6994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    propagate=1
7004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    qualname=compiler.parser
7014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [handler_hand1]
7034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class=StreamHandler
7044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    level=NOTSET
7054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    formatter=form1
7064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    args=(sys.stdout,)
7074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    [formatter_form1]
7094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    format=%(levelname)s ++ %(message)s
7104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    datefmt=
7114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
7124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def apply_config(self, conf):
7144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        file = cStringIO.StringIO(textwrap.dedent(conf))
7154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        logging.config.fileConfig(file)
7164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config0_ok(self):
7184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A simple config file which overrides the default settings.
7194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
7204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config0)
7214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger()
7224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Won't output anything
7234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
7244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Outputs a message
7254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
7264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
7274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '2'),
7284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ], stream=output)
7294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Original logger output is empty.
7304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([])
7314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config1_ok(self, config=config1):
7334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A config file defining a sub-parser as well.
7344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
7354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(config)
7364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.parser")
7374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Both will output a message
7384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
7394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
7404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
7414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('INFO', '1'),
7424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '2'),
7434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ], stream=output)
7444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Original logger output is empty.
7454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([])
7464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config2_failure(self):
7484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A simple config file which overrides the default settings.
7494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(StandardError, self.apply_config, self.config2)
7504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config3_failure(self):
7524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A simple config file which overrides the default settings.
7534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(StandardError, self.apply_config, self.config3)
7544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config4_ok(self):
7564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A config file specifying a custom formatter class.
7574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
7584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config4)
7594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger()
7604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
7614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                raise RuntimeError()
7624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except RuntimeError:
7634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                logging.exception("just testing")
7644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            sys.stdout.seek(0)
7654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(output.getvalue(),
7664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                "ERROR:root:just testing\nGot a [RuntimeError]\n")
7674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Original logger output is empty
7684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([])
7694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config5_ok(self):
7714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.test_config1_ok(config=self.config5)
7724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config6_ok(self):
7744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.test_config1_ok(config=self.config6)
7754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config7_ok(self):
7774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
7784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config1a)
7794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.parser")
7804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # See issue #11424. compiler-hyphenated sorts
7814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # between compiler and compiler.xyz and this
7824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # was preventing compiler.xyz from being included
7834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # in the child loggers of compiler because of an
7844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # overzealous loop termination condition.
7854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            hyphenated = logging.getLogger('compiler-hyphenated')
7864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # All will output a message
7874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
7884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
7894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            hyphenated.critical(self.next_message())
7904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
7914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('INFO', '1'),
7924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '2'),
7934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('CRITICAL', '3'),
7944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ], stream=output)
7954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Original logger output is empty.
7964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([])
7974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
7984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config7)
7994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.parser")
8004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertFalse(logger.disabled)
8014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Both will output a message
8024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
8034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
8044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.lexer")
8054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Both will output a message
8064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
8074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
8084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Will not appear
8094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            hyphenated.critical(self.next_message())
8104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
8114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('INFO', '4'),
8124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '5'),
8134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('INFO', '6'),
8144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '7'),
8154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ], stream=output)
8164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Original logger output is empty.
8174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([])
8184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass LogRecordStreamHandler(StreamRequestHandler):
8204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Handler for a streaming logging request. It saves the log message in the
8224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    TCP server's 'log_output' attribute."""
8234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    TCP_LOG_END = "!!!END!!!"
8254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def handle(self):
8274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Handle multiple requests - each expected to be of 4-byte length,
8284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        followed by the LogRecord in pickle format. Logs the record
8294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        according to whatever policy is configured locally."""
8304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        while True:
8314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            chunk = self.connection.recv(4)
8324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if len(chunk) < 4:
8334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                break
8344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            slen = struct.unpack(">L", chunk)[0]
8354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            chunk = self.connection.recv(slen)
8364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            while len(chunk) < slen:
8374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                chunk = chunk + self.connection.recv(slen - len(chunk))
8384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            obj = self.unpickle(chunk)
8394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            record = logging.makeLogRecord(obj)
8404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.handle_log_record(record)
8414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def unpickle(self, data):
8434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return cPickle.loads(data)
8444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def handle_log_record(self, record):
8464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # If the end-of-messages sentinel is seen, tell the server to
8474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #  terminate.
8484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if self.TCP_LOG_END in record.msg:
8494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.server.abort = 1
8504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return
8514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.server.log_output += record.msg + "\n"
8524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass LogRecordSocketReceiver(ThreadingTCPServer):
8554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """A simple-minded TCP socket-based logging receiver suitable for test
8574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    purposes."""
8584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    allow_reuse_address = 1
8604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    log_output = ""
8614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __init__(self, host='localhost',
8634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             port=logging.handlers.DEFAULT_TCP_LOGGING_PORT,
8644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                     handler=LogRecordStreamHandler):
8654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ThreadingTCPServer.__init__(self, (host, port), handler)
8664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.abort = False
8674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.timeout = 0.1
8684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.finished = threading.Event()
8694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def serve_until_stopped(self):
8714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        while not self.abort:
8724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            rd, wr, ex = select.select([self.socket.fileno()], [], [],
8734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                       self.timeout)
8744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if rd:
8754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.handle_request()
8764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Notify the main thread that we're about to exit
8774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.finished.set()
8784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # close the listen socket
8794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.server_close()
8804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm@unittest.skipUnless(threading, 'Threading required for this test.')
8834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass SocketHandlerTest(BaseTest):
8844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test for SocketHandler objects."""
8864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setUp(self):
8884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Set up a TCP server to receive log messages, and a SocketHandler
8894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pointing to that server's address and port."""
8904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        BaseTest.setUp(self)
8914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.tcpserver = LogRecordSocketReceiver(port=0)
8924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.port = self.tcpserver.socket.getsockname()[1]
8934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.threads = [
8944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                threading.Thread(target=self.tcpserver.serve_until_stopped)]
8954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for thread in self.threads:
8964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            thread.start()
8974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.sock_hdlr = logging.handlers.SocketHandler('localhost', self.port)
8994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.sock_hdlr.setFormatter(self.root_formatter)
9004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_logger.removeHandler(self.root_logger.handlers[0])
9014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_logger.addHandler(self.sock_hdlr)
9024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def tearDown(self):
9044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Shutdown the TCP server."""
9054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
9064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.tcpserver.abort = True
9074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            del self.tcpserver
9084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.root_logger.removeHandler(self.sock_hdlr)
9094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.sock_hdlr.close()
9104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for thread in self.threads:
9114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                thread.join(2.0)
9124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
9134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            BaseTest.tearDown(self)
9144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def get_output(self):
9164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Get the log output as received by the TCP server."""
9174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Signal the TCP receiver and wait for it to terminate.
9184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_logger.critical(LogRecordStreamHandler.TCP_LOG_END)
9194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.tcpserver.finished.wait(2.0)
9204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self.tcpserver.log_output
9214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_output(self):
9234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # The log message sent to the SocketHandler is properly received.
9244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        logger = logging.getLogger("tcp")
9254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        logger.error("spam")
9264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        logger.debug("eggs")
9274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(self.get_output(), "spam\neggs\n")
9284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass MemoryTest(BaseTest):
9314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test memory persistence of logger objects."""
9334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setUp(self):
9354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Create a dict to remember potentially destroyed objects."""
9364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        BaseTest.setUp(self)
9374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._survivors = {}
9384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def _watch_for_survival(self, *args):
9404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Watch the given objects for survival, by creating weakrefs to
9414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        them."""
9424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for obj in args:
9434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            key = id(obj), repr(obj)
9444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self._survivors[key] = weakref.ref(obj)
9454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def _assertTruesurvival(self):
9474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Assert that all objects watched for survival have survived."""
9484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Trigger cycle breaking.
9494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        gc.collect()
9504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dead = []
9514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for (id_, repr_), ref in self._survivors.items():
9524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if ref() is None:
9534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                dead.append(repr_)
9544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if dead:
9554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.fail("%d objects should have survived "
9564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                "but have been destroyed: %s" % (len(dead), ", ".join(dead)))
9574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_persistent_loggers(self):
9594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Logger objects are persistent and retain their configuration, even
9604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #  if visible references are destroyed.
9614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_logger.setLevel(logging.INFO)
9624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        foo = logging.getLogger("foo")
9634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._watch_for_survival(foo)
9644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        foo.setLevel(logging.DEBUG)
9654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.root_logger.debug(self.next_message())
9664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        foo.debug(self.next_message())
9674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assert_log_lines([
9684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('foo', 'DEBUG', '2'),
9694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ])
9704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        del foo
9714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # foo has survived.
9724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._assertTruesurvival()
9734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # foo has retained its settings.
9744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        bar = logging.getLogger("foo")
9754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        bar.debug(self.next_message())
9764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assert_log_lines([
9774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('foo', 'DEBUG', '2'),
9784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ('foo', 'DEBUG', '3'),
9794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ])
9804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass EncodingTest(BaseTest):
9834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_encoding_plain_file(self):
9844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # In Python 2.x, a plain file object is treated as having no encoding.
9854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        log = logging.getLogger("test")
9864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        fn = tempfile.mktemp(".log")
9874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # the non-ascii data we write to the log.
9884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        data = "foo\x80"
9894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
9904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            handler = logging.FileHandler(fn)
9914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            log.addHandler(handler)
9924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
9934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # write non-ascii data to the log.
9944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                log.warning(data)
9954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            finally:
9964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                log.removeHandler(handler)
9974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                handler.close()
9984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # check we wrote exactly those bytes, ignoring trailing \n etc
9994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f = open(fn)
10004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
10014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(f.read().rstrip(), data)
10024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            finally:
10034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                f.close()
10044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
10054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if os.path.isfile(fn):
10064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                os.remove(fn)
10074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_encoding_cyrillic_unicode(self):
10094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        log = logging.getLogger("test")
10104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #Get a message in Unicode: Do svidanya in Cyrillic (meaning goodbye)
10114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        message = u'\u0434\u043e \u0441\u0432\u0438\u0434\u0430\u043d\u0438\u044f'
10124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #Ensure it's written in a Cyrillic encoding
10134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        writer_class = codecs.getwriter('cp1251')
10144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        writer_class.encoding = 'cp1251'
10154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        stream = cStringIO.StringIO()
10164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        writer = writer_class(stream, 'strict')
10174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        handler = logging.StreamHandler(writer)
10184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        log.addHandler(handler)
10194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
10204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            log.warning(message)
10214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
10224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            log.removeHandler(handler)
10234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            handler.close()
10244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # check we wrote exactly those bytes, ignoring trailing \n etc
10254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s = stream.getvalue()
10264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #Compare against what the data should be when encoded in CP-1251
10274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(s, '\xe4\xee \xf1\xe2\xe8\xe4\xe0\xed\xe8\xff\n')
10284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass WarningsTest(BaseTest):
10314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_warnings(self):
10334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with warnings.catch_warnings():
10344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logging.captureWarnings(True)
10354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
10364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                warnings.filterwarnings("always", category=UserWarning)
10374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                file = cStringIO.StringIO()
10384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                h = logging.StreamHandler(file)
10394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                logger = logging.getLogger("py.warnings")
10404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                logger.addHandler(h)
10414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                warnings.warn("I'm warning you...")
10424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                logger.removeHandler(h)
10434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                s = file.getvalue()
10444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                h.close()
10454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertTrue(s.find("UserWarning: I'm warning you...\n") > 0)
10464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                #See if an explicit file uses the original implementation
10484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                file = cStringIO.StringIO()
10494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                warnings.showwarning("Explicit", UserWarning, "dummy.py", 42,
10504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                        file, "Dummy line")
10514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                s = file.getvalue()
10524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                file.close()
10534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(s,
10544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "dummy.py:42: UserWarning: Explicit\n  Dummy line\n")
10554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            finally:
10564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                logging.captureWarnings(False)
10574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef formatFunc(format, datefmt=None):
10604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return logging.Formatter(format, datefmt)
10614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef handlerFunc():
10634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return logging.StreamHandler()
10644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass CustomHandler(logging.StreamHandler):
10664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pass
10674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass ConfigDictTest(BaseTest):
10694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Reading logging config from a dictionary."""
10714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    expected_log_pat = r"^([\w]+) \+\+ ([\w]+)$"
10734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config0 is a standard configuration.
10754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config0 = {
10764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
10774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters': {
10784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
10794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
10804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
10814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
10824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
10834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
10844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
10854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
10864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
10874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
10884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
10894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
10904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
10914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'WARNING',
10924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'handlers' : ['hand1'],
10934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
10944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
10954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config1 adds a little to the standard configuration.
10974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config1 = {
10984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
10994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters': {
11004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
11014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
11024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
11034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
11044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
11054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
11064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
11074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
11084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
11094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
11104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
11114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
11124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
11134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.parser' : {
11144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'DEBUG',
11154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
11164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
11174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
11184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
11194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'WARNING',
11204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
11214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
11224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config2 has a subtle configuration error that should be reported
11244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config2 = {
11254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
11264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters': {
11274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
11284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
11294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
11304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
11314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
11324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
11334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
11344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
11354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
11364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdbout',
11374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
11384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
11394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
11404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.parser' : {
11414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'DEBUG',
11424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
11434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
11444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
11454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
11464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'WARNING',
11474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
11484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
11494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    #As config1 but with a misspelt level on a handler
11514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config2a = {
11524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
11534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters': {
11544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
11554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
11564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
11574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
11584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
11594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
11604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
11614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
11624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NTOSET',
11634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
11644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
11654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
11664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
11674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.parser' : {
11684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'DEBUG',
11694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
11704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
11714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
11724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
11734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'WARNING',
11744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
11754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
11764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    #As config1 but with a misspelt level on a logger
11794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config2b = {
11804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
11814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters': {
11824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
11834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
11844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
11854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
11864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
11874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
11884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
11894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
11904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
11914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
11924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
11934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
11944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
11954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.parser' : {
11964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'DEBUG',
11974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
11984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
11994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
12004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
12014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'WRANING',
12024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
12034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
12044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config3 has a less subtle configuration error
12064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config3 = {
12074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
12084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters': {
12094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
12104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
12114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
12124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
12134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
12144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
12154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
12164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'misspelled_name',
12174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
12184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
12194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
12204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
12214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
12224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.parser' : {
12234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'DEBUG',
12244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
12254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
12264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
12274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
12284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'WARNING',
12294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
12304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
12314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config4 specifies a custom formatter class to be loaded
12334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config4 = {
12344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
12354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters': {
12364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
12374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                '()' : __name__ + '.ExceptionFormatter',
12384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s:%(name)s:%(message)s',
12394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
12404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
12414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
12424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
12434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
12444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
12454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
12464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
12474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
12484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
12494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
12504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'NOTSET',
12514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
12524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
12534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
12544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # As config4 but using an actual callable rather than a string
12564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config4a = {
12574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
12584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters': {
12594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
12604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                '()' : ExceptionFormatter,
12614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s:%(name)s:%(message)s',
12624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
12634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form2' : {
12644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                '()' : __name__ + '.formatFunc',
12654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s:%(name)s:%(message)s',
12664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
12674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form3' : {
12684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                '()' : formatFunc,
12694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s:%(name)s:%(message)s',
12704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
12714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
12724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
12734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
12744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
12754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
12764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
12774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
12784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
12794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand2' : {
12804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                '()' : handlerFunc,
12814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
12824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
12834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
12844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'NOTSET',
12854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
12864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
12874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
12884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config5 specifies a custom handler class to be loaded
12904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config5 = {
12914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
12924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters': {
12934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
12944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
12954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
12964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
12974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
12984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
12994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : __name__ + '.CustomHandler',
13004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
13014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
13024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
13034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
13044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
13054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
13064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.parser' : {
13074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'DEBUG',
13084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
13094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
13104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
13114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
13124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'WARNING',
13134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
13144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
13154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # config6 specifies a custom handler class to be loaded
13174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # but has bad arguments
13184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config6 = {
13194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
13204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters': {
13214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
13224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
13234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
13244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
13254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
13264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
13274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : __name__ + '.CustomHandler',
13284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
13294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
13304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
13314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                '9' : 'invalid parameter name',
13324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
13334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
13344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
13354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.parser' : {
13364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'DEBUG',
13374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
13384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
13394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
13404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
13414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'WARNING',
13424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
13434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
13444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    #config 7 does not define compiler.parser but defines compiler.lexer
13464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    #so compiler.parser should be disabled after applying it
13474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config7 = {
13484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
13494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters': {
13504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
13514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
13524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
13534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
13544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
13554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
13564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
13574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
13584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
13594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
13604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
13614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
13624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
13634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.lexer' : {
13644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'DEBUG',
13654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
13664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
13674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
13684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
13694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'WARNING',
13704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
13714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
13724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config8 = {
13744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
13754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'disable_existing_loggers' : False,
13764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters': {
13774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
13784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
13794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
13804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
13814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
13824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
13834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
13844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
13854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
13864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
13874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
13884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
13894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
13904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler' : {
13914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'DEBUG',
13924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
13934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
13944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.lexer' : {
13954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
13964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
13974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
13984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'WARNING',
13994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
14004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
14014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config9 = {
14034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
14044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters': {
14054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
14064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
14074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
14084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
14094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
14104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
14114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
14124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
14134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'WARNING',
14144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
14154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
14164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
14174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
14184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.parser' : {
14194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'WARNING',
14204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
14214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
14224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
14234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
14244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'NOTSET',
14254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
14264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
14274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config9a = {
14294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
14304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'incremental' : True,
14314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
14324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
14334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'WARNING',
14344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
14354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
14364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
14374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.parser' : {
14384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'INFO',
14394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
14404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
14414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
14424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config9b = {
14444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
14454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'incremental' : True,
14464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
14474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
14484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'INFO',
14494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
14504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
14514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
14524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.parser' : {
14534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'INFO',
14544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
14554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
14564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
14574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    #As config1 but with a filter added
14594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config10 = {
14604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
14614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters': {
14624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
14634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
14644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
14654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
14664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'filters' : {
14674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'filt1' : {
14684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'name' : 'compiler.parser',
14694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
14704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
14714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
14724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
14734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
14744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
14754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
14764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
14774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'filters' : ['filt1'],
14784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
14794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
14804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
14814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.parser' : {
14824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'DEBUG',
14834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'filters' : ['filt1'],
14844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
14854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
14864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
14874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'WARNING',
14884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'handlers' : ['hand1'],
14894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
14904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
14914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    #As config1 but using cfg:// references
14934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config11 = {
14944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 1,
14954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'true_formatters': {
14964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
14974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
14984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
14994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handler_configs': {
15014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
15024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
15034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
15044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
15054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
15064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
15074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters' : 'cfg://true_formatters',
15094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
15104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : 'cfg://handler_configs[hand1]',
15114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
15134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.parser' : {
15144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'DEBUG',
15154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
15164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
15174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
15194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'WARNING',
15204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
15224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    #As config11 but missing the version key
15244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config12 = {
15254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'true_formatters': {
15264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
15274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
15284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
15294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handler_configs': {
15314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
15324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
15334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
15344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
15354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
15364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
15374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters' : 'cfg://true_formatters',
15394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
15404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : 'cfg://handler_configs[hand1]',
15414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
15434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.parser' : {
15444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'DEBUG',
15454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
15464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
15474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
15494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'WARNING',
15504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
15524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    #As config11 but using an unsupported version
15544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    config13 = {
15554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'version': 2,
15564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'true_formatters': {
15574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'form1' : {
15584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'format' : '%(levelname)s ++ %(message)s',
15594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
15604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handler_configs': {
15624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : {
15634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'class' : 'logging.StreamHandler',
15644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'formatter' : 'form1',
15654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'NOTSET',
15664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'stream'  : 'ext://sys.stdout',
15674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
15684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'formatters' : 'cfg://true_formatters',
15704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'handlers' : {
15714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'hand1' : 'cfg://handler_configs[hand1]',
15724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'loggers' : {
15744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'compiler.parser' : {
15754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'level' : 'DEBUG',
15764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'handlers' : ['hand1'],
15774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            },
15784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        'root' : {
15804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'level' : 'WARNING',
15814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        },
15824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
15834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def apply_config(self, conf):
15854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        logging.config.dictConfig(conf)
15864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config0_ok(self):
15884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A simple config which overrides the default settings.
15894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
15904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config0)
15914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger()
15924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Won't output anything
15934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
15944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Outputs a message
15954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
15964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
15974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '2'),
15984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ], stream=output)
15994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Original logger output is empty.
16004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([])
16014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config1_ok(self, config=config1):
16034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A config defining a sub-parser as well.
16044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
16054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(config)
16064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.parser")
16074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Both will output a message
16084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
16094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
16104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
16114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('INFO', '1'),
16124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '2'),
16134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ], stream=output)
16144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Original logger output is empty.
16154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([])
16164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config2_failure(self):
16184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A simple config which overrides the default settings.
16194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(StandardError, self.apply_config, self.config2)
16204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config2a_failure(self):
16224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A simple config which overrides the default settings.
16234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(StandardError, self.apply_config, self.config2a)
16244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config2b_failure(self):
16264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A simple config which overrides the default settings.
16274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(StandardError, self.apply_config, self.config2b)
16284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config3_failure(self):
16304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A simple config which overrides the default settings.
16314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(StandardError, self.apply_config, self.config3)
16324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config4_ok(self):
16344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A config specifying a custom formatter class.
16354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
16364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config4)
16374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #logger = logging.getLogger()
16384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
16394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                raise RuntimeError()
16404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except RuntimeError:
16414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                logging.exception("just testing")
16424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            sys.stdout.seek(0)
16434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(output.getvalue(),
16444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                "ERROR:root:just testing\nGot a [RuntimeError]\n")
16454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Original logger output is empty
16464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([])
16474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config4a_ok(self):
16494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A config specifying a custom formatter class.
16504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
16514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config4a)
16524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #logger = logging.getLogger()
16534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
16544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                raise RuntimeError()
16554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except RuntimeError:
16564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                logging.exception("just testing")
16574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            sys.stdout.seek(0)
16584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(output.getvalue(),
16594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                "ERROR:root:just testing\nGot a [RuntimeError]\n")
16604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Original logger output is empty
16614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([])
16624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config5_ok(self):
16644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.test_config1_ok(config=self.config5)
16654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config6_failure(self):
16674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(StandardError, self.apply_config, self.config6)
16684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config7_ok(self):
16704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
16714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config1)
16724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.parser")
16734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Both will output a message
16744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
16754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
16764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
16774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('INFO', '1'),
16784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '2'),
16794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ], stream=output)
16804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Original logger output is empty.
16814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([])
16824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
16834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config7)
16844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.parser")
16854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(logger.disabled)
16864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.lexer")
16874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Both will output a message
16884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
16894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
16904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
16914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('INFO', '3'),
16924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '4'),
16934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ], stream=output)
16944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Original logger output is empty.
16954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([])
16964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    #Same as test_config_7_ok but don't disable old loggers.
16984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config_8_ok(self):
16994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
17004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config1)
17014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.parser")
17024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Both will output a message
17034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
17044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
17054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
17064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('INFO', '1'),
17074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '2'),
17084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ], stream=output)
17094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Original logger output is empty.
17104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([])
17114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
17124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config8)
17134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.parser")
17144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertFalse(logger.disabled)
17154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Both will output a message
17164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
17174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
17184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.lexer")
17194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Both will output a message
17204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
17214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
17224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
17234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('INFO', '3'),
17244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '4'),
17254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('INFO', '5'),
17264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '6'),
17274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ], stream=output)
17284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Original logger output is empty.
17294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([])
17304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config_9_ok(self):
17324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
17334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config9)
17344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.parser")
17354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #Nothing will be output since both handler and logger are set to WARNING
17364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
17374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([], stream=output)
17384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config9a)
17394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #Nothing will be output since both handler is still set to WARNING
17404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
17414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([], stream=output)
17424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config9b)
17434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #Message should now be output
17444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
17454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
17464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('INFO', '3'),
17474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ], stream=output)
17484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config_10_ok(self):
17504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
17514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.apply_config(self.config10)
17524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.parser")
17534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.warning(self.next_message())
17544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger('compiler')
17554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #Not output, because filtered
17564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.warning(self.next_message())
17574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger('compiler.lexer')
17584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #Not output, because filtered
17594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.warning(self.next_message())
17604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.parser.codegen")
17614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #Output, as not filtered
17624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
17634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
17644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('WARNING', '1'),
17654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '4'),
17664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ], stream=output)
17674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config11_ok(self):
17694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.test_config1_ok(self.config11)
17704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config12_failure(self):
17724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(StandardError, self.apply_config, self.config12)
17734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_config13_failure(self):
17754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(StandardError, self.apply_config, self.config13)
17764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    @unittest.skipUnless(threading, 'listen() needs threading to work')
17784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setup_via_listener(self, text):
17794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ask for a randomly assigned port (by using port 0)
17804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = logging.config.listen(0)
17814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t.start()
17824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t.ready.wait()
17834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Now get the port allocated
17844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        port = t.port
17854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t.ready.clear()
17864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
17874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
17884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            sock.settimeout(2.0)
17894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            sock.connect(('localhost', port))
17904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            slen = struct.pack('>L', len(text))
17924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s = slen + text
17934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            sentsofar = 0
17944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            left = len(s)
17954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            while left > 0:
17964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                sent = sock.send(s[sentsofar:])
17974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                sentsofar += sent
17984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                left -= sent
17994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            sock.close()
18004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
18014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            t.ready.wait(2.0)
18024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logging.config.stopListening()
18034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            t.join(2.0)
18044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_listen_config_10_ok(self):
18064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
18074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.setup_via_listener(json.dumps(self.config10))
18084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.parser")
18094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.warning(self.next_message())
18104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger('compiler')
18114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #Not output, because filtered
18124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.warning(self.next_message())
18134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger('compiler.lexer')
18144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #Not output, because filtered
18154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.warning(self.next_message())
18164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.parser.codegen")
18174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #Output, as not filtered
18184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
18194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
18204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('WARNING', '1'),
18214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '4'),
18224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ], stream=output)
18234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_listen_config_1_ok(self):
18254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with captured_stdout() as output:
18264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.setup_via_listener(textwrap.dedent(ConfigFileTest.config1))
18274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger = logging.getLogger("compiler.parser")
18284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Both will output a message
18294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.info(self.next_message())
18304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            logger.error(self.next_message())
18314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([
18324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('INFO', '1'),
18334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ('ERROR', '2'),
18344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ], stream=output)
18354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Original logger output is empty.
18364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assert_log_lines([])
18374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass ManagerTest(BaseTest):
18404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_manager_loggerclass(self):
18414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        logged = []
18424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class MyLogger(logging.Logger):
18444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def _log(self, level, msg, args, exc_info=None, extra=None):
18454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                logged.append(msg)
18464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        man = logging.Manager(None)
18484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, man.setLoggerClass, int)
18494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        man.setLoggerClass(MyLogger)
18504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        logger = man.getLogger('test')
18514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        logger.warning('should appear in logged')
18524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        logging.warning('should not appear in logged')
18534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(logged, ['should appear in logged'])
18554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass ChildLoggerTest(BaseTest):
18584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_child_loggers(self):
18594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        r = logging.getLogger()
18604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        l1 = logging.getLogger('abc')
18614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        l2 = logging.getLogger('def.ghi')
18624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        c1 = r.getChild('xyz')
18634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        c2 = r.getChild('uvw.xyz')
18644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(c1 is logging.getLogger('xyz'))
18654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(c2 is logging.getLogger('uvw.xyz'))
18664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        c1 = l1.getChild('def')
18674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        c2 = c1.getChild('ghi')
18684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        c3 = l1.getChild('def.ghi')
18694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(c1 is logging.getLogger('abc.def'))
18704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(c2 is logging.getLogger('abc.def.ghi'))
18714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(c2 is c3)
18724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Set the locale to the platform-dependent default.  I have no idea
18754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# why the test does this, but in any case we save the current locale
18764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# first and restore it at the end.
18774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm@run_with_locale('LC_ALL', '')
18784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef test_main():
18794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    run_unittest(BuiltinLevelsTest, BasicFilterTest,
18804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                 CustomLevelsAndFiltersTest, MemoryHandlerTest,
18814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                 ConfigFileTest, SocketHandlerTest, MemoryTest,
18824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                 EncodingTest, WarningsTest, ConfigDictTest, ManagerTest,
18834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                 ChildLoggerTest)
18844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmif __name__ == "__main__":
18864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    test_main()
1887