17db96d56Sopenharmony_ci# Copyright 2001-2022 by Vinay Sajip. All Rights Reserved. 27db96d56Sopenharmony_ci# 37db96d56Sopenharmony_ci# Permission to use, copy, modify, and distribute this software and its 47db96d56Sopenharmony_ci# documentation for any purpose and without fee is hereby granted, 57db96d56Sopenharmony_ci# provided that the above copyright notice appear in all copies and that 67db96d56Sopenharmony_ci# both that copyright notice and this permission notice appear in 77db96d56Sopenharmony_ci# supporting documentation, and that the name of Vinay Sajip 87db96d56Sopenharmony_ci# not be used in advertising or publicity pertaining to distribution 97db96d56Sopenharmony_ci# of the software without specific, written prior permission. 107db96d56Sopenharmony_ci# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 117db96d56Sopenharmony_ci# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 127db96d56Sopenharmony_ci# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 137db96d56Sopenharmony_ci# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 147db96d56Sopenharmony_ci# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 157db96d56Sopenharmony_ci# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ci"""Test harness for the logging module. Run all tests. 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_ciCopyright (C) 2001-2022 Vinay Sajip. All Rights Reserved. 207db96d56Sopenharmony_ci""" 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_ciimport logging 237db96d56Sopenharmony_ciimport logging.handlers 247db96d56Sopenharmony_ciimport logging.config 257db96d56Sopenharmony_ci 267db96d56Sopenharmony_ciimport codecs 277db96d56Sopenharmony_ciimport configparser 287db96d56Sopenharmony_ciimport copy 297db96d56Sopenharmony_ciimport datetime 307db96d56Sopenharmony_ciimport pathlib 317db96d56Sopenharmony_ciimport pickle 327db96d56Sopenharmony_ciimport io 337db96d56Sopenharmony_ciimport gc 347db96d56Sopenharmony_ciimport json 357db96d56Sopenharmony_ciimport os 367db96d56Sopenharmony_ciimport queue 377db96d56Sopenharmony_ciimport random 387db96d56Sopenharmony_ciimport re 397db96d56Sopenharmony_ciimport shutil 407db96d56Sopenharmony_ciimport socket 417db96d56Sopenharmony_ciimport struct 427db96d56Sopenharmony_ciimport sys 437db96d56Sopenharmony_ciimport tempfile 447db96d56Sopenharmony_cifrom test.support.script_helper import assert_python_ok, assert_python_failure 457db96d56Sopenharmony_cifrom test import support 467db96d56Sopenharmony_cifrom test.support import os_helper 477db96d56Sopenharmony_cifrom test.support import socket_helper 487db96d56Sopenharmony_cifrom test.support import threading_helper 497db96d56Sopenharmony_cifrom test.support import warnings_helper 507db96d56Sopenharmony_cifrom test.support.logging_helper import TestHandler 517db96d56Sopenharmony_ciimport textwrap 527db96d56Sopenharmony_ciimport threading 537db96d56Sopenharmony_ciimport time 547db96d56Sopenharmony_ciimport unittest 557db96d56Sopenharmony_ciimport warnings 567db96d56Sopenharmony_ciimport weakref 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_cifrom http.server import HTTPServer, BaseHTTPRequestHandler 597db96d56Sopenharmony_cifrom urllib.parse import urlparse, parse_qs 607db96d56Sopenharmony_cifrom socketserver import (ThreadingUDPServer, DatagramRequestHandler, 617db96d56Sopenharmony_ci ThreadingTCPServer, StreamRequestHandler) 627db96d56Sopenharmony_ci 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ciasyncore = warnings_helper.import_deprecated('asyncore') 657db96d56Sopenharmony_cismtpd = warnings_helper.import_deprecated('smtpd') 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_ci 687db96d56Sopenharmony_citry: 697db96d56Sopenharmony_ci import win32evtlog, win32evtlogutil, pywintypes 707db96d56Sopenharmony_ciexcept ImportError: 717db96d56Sopenharmony_ci win32evtlog = win32evtlogutil = pywintypes = None 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_citry: 747db96d56Sopenharmony_ci import zlib 757db96d56Sopenharmony_ciexcept ImportError: 767db96d56Sopenharmony_ci pass 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_ci 797db96d56Sopenharmony_ciclass BaseTest(unittest.TestCase): 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_ci """Base class for logging tests.""" 827db96d56Sopenharmony_ci 837db96d56Sopenharmony_ci log_format = "%(name)s -> %(levelname)s: %(message)s" 847db96d56Sopenharmony_ci expected_log_pat = r"^([\w.]+) -> (\w+): (\d+)$" 857db96d56Sopenharmony_ci message_num = 0 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ci def setUp(self): 887db96d56Sopenharmony_ci """Setup the default logging stream to an internal StringIO instance, 897db96d56Sopenharmony_ci so that we can examine log output as we want.""" 907db96d56Sopenharmony_ci self._threading_key = threading_helper.threading_setup() 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ci logger_dict = logging.getLogger().manager.loggerDict 937db96d56Sopenharmony_ci logging._acquireLock() 947db96d56Sopenharmony_ci try: 957db96d56Sopenharmony_ci self.saved_handlers = logging._handlers.copy() 967db96d56Sopenharmony_ci self.saved_handler_list = logging._handlerList[:] 977db96d56Sopenharmony_ci self.saved_loggers = saved_loggers = logger_dict.copy() 987db96d56Sopenharmony_ci self.saved_name_to_level = logging._nameToLevel.copy() 997db96d56Sopenharmony_ci self.saved_level_to_name = logging._levelToName.copy() 1007db96d56Sopenharmony_ci self.logger_states = logger_states = {} 1017db96d56Sopenharmony_ci for name in saved_loggers: 1027db96d56Sopenharmony_ci logger_states[name] = getattr(saved_loggers[name], 1037db96d56Sopenharmony_ci 'disabled', None) 1047db96d56Sopenharmony_ci finally: 1057db96d56Sopenharmony_ci logging._releaseLock() 1067db96d56Sopenharmony_ci 1077db96d56Sopenharmony_ci # Set two unused loggers 1087db96d56Sopenharmony_ci self.logger1 = logging.getLogger("\xab\xd7\xbb") 1097db96d56Sopenharmony_ci self.logger2 = logging.getLogger("\u013f\u00d6\u0047") 1107db96d56Sopenharmony_ci 1117db96d56Sopenharmony_ci self.root_logger = logging.getLogger("") 1127db96d56Sopenharmony_ci self.original_logging_level = self.root_logger.getEffectiveLevel() 1137db96d56Sopenharmony_ci 1147db96d56Sopenharmony_ci self.stream = io.StringIO() 1157db96d56Sopenharmony_ci self.root_logger.setLevel(logging.DEBUG) 1167db96d56Sopenharmony_ci self.root_hdlr = logging.StreamHandler(self.stream) 1177db96d56Sopenharmony_ci self.root_formatter = logging.Formatter(self.log_format) 1187db96d56Sopenharmony_ci self.root_hdlr.setFormatter(self.root_formatter) 1197db96d56Sopenharmony_ci if self.logger1.hasHandlers(): 1207db96d56Sopenharmony_ci hlist = self.logger1.handlers + self.root_logger.handlers 1217db96d56Sopenharmony_ci raise AssertionError('Unexpected handlers: %s' % hlist) 1227db96d56Sopenharmony_ci if self.logger2.hasHandlers(): 1237db96d56Sopenharmony_ci hlist = self.logger2.handlers + self.root_logger.handlers 1247db96d56Sopenharmony_ci raise AssertionError('Unexpected handlers: %s' % hlist) 1257db96d56Sopenharmony_ci self.root_logger.addHandler(self.root_hdlr) 1267db96d56Sopenharmony_ci self.assertTrue(self.logger1.hasHandlers()) 1277db96d56Sopenharmony_ci self.assertTrue(self.logger2.hasHandlers()) 1287db96d56Sopenharmony_ci 1297db96d56Sopenharmony_ci def tearDown(self): 1307db96d56Sopenharmony_ci """Remove our logging stream, and restore the original logging 1317db96d56Sopenharmony_ci level.""" 1327db96d56Sopenharmony_ci self.stream.close() 1337db96d56Sopenharmony_ci self.root_logger.removeHandler(self.root_hdlr) 1347db96d56Sopenharmony_ci while self.root_logger.handlers: 1357db96d56Sopenharmony_ci h = self.root_logger.handlers[0] 1367db96d56Sopenharmony_ci self.root_logger.removeHandler(h) 1377db96d56Sopenharmony_ci h.close() 1387db96d56Sopenharmony_ci self.root_logger.setLevel(self.original_logging_level) 1397db96d56Sopenharmony_ci logging._acquireLock() 1407db96d56Sopenharmony_ci try: 1417db96d56Sopenharmony_ci logging._levelToName.clear() 1427db96d56Sopenharmony_ci logging._levelToName.update(self.saved_level_to_name) 1437db96d56Sopenharmony_ci logging._nameToLevel.clear() 1447db96d56Sopenharmony_ci logging._nameToLevel.update(self.saved_name_to_level) 1457db96d56Sopenharmony_ci logging._handlers.clear() 1467db96d56Sopenharmony_ci logging._handlers.update(self.saved_handlers) 1477db96d56Sopenharmony_ci logging._handlerList[:] = self.saved_handler_list 1487db96d56Sopenharmony_ci manager = logging.getLogger().manager 1497db96d56Sopenharmony_ci manager.disable = 0 1507db96d56Sopenharmony_ci loggerDict = manager.loggerDict 1517db96d56Sopenharmony_ci loggerDict.clear() 1527db96d56Sopenharmony_ci loggerDict.update(self.saved_loggers) 1537db96d56Sopenharmony_ci logger_states = self.logger_states 1547db96d56Sopenharmony_ci for name in self.logger_states: 1557db96d56Sopenharmony_ci if logger_states[name] is not None: 1567db96d56Sopenharmony_ci self.saved_loggers[name].disabled = logger_states[name] 1577db96d56Sopenharmony_ci finally: 1587db96d56Sopenharmony_ci logging._releaseLock() 1597db96d56Sopenharmony_ci 1607db96d56Sopenharmony_ci self.doCleanups() 1617db96d56Sopenharmony_ci threading_helper.threading_cleanup(*self._threading_key) 1627db96d56Sopenharmony_ci 1637db96d56Sopenharmony_ci def assert_log_lines(self, expected_values, stream=None, pat=None): 1647db96d56Sopenharmony_ci """Match the collected log lines against the regular expression 1657db96d56Sopenharmony_ci self.expected_log_pat, and compare the extracted group values to 1667db96d56Sopenharmony_ci the expected_values list of tuples.""" 1677db96d56Sopenharmony_ci stream = stream or self.stream 1687db96d56Sopenharmony_ci pat = re.compile(pat or self.expected_log_pat) 1697db96d56Sopenharmony_ci actual_lines = stream.getvalue().splitlines() 1707db96d56Sopenharmony_ci self.assertEqual(len(actual_lines), len(expected_values)) 1717db96d56Sopenharmony_ci for actual, expected in zip(actual_lines, expected_values): 1727db96d56Sopenharmony_ci match = pat.search(actual) 1737db96d56Sopenharmony_ci if not match: 1747db96d56Sopenharmony_ci self.fail("Log line does not match expected pattern:\n" + 1757db96d56Sopenharmony_ci actual) 1767db96d56Sopenharmony_ci self.assertEqual(tuple(match.groups()), expected) 1777db96d56Sopenharmony_ci s = stream.read() 1787db96d56Sopenharmony_ci if s: 1797db96d56Sopenharmony_ci self.fail("Remaining output at end of log stream:\n" + s) 1807db96d56Sopenharmony_ci 1817db96d56Sopenharmony_ci def next_message(self): 1827db96d56Sopenharmony_ci """Generate a message consisting solely of an auto-incrementing 1837db96d56Sopenharmony_ci integer.""" 1847db96d56Sopenharmony_ci self.message_num += 1 1857db96d56Sopenharmony_ci return "%d" % self.message_num 1867db96d56Sopenharmony_ci 1877db96d56Sopenharmony_ci 1887db96d56Sopenharmony_ciclass BuiltinLevelsTest(BaseTest): 1897db96d56Sopenharmony_ci """Test builtin levels and their inheritance.""" 1907db96d56Sopenharmony_ci 1917db96d56Sopenharmony_ci def test_flat(self): 1927db96d56Sopenharmony_ci # Logging levels in a flat logger namespace. 1937db96d56Sopenharmony_ci m = self.next_message 1947db96d56Sopenharmony_ci 1957db96d56Sopenharmony_ci ERR = logging.getLogger("ERR") 1967db96d56Sopenharmony_ci ERR.setLevel(logging.ERROR) 1977db96d56Sopenharmony_ci INF = logging.LoggerAdapter(logging.getLogger("INF"), {}) 1987db96d56Sopenharmony_ci INF.setLevel(logging.INFO) 1997db96d56Sopenharmony_ci DEB = logging.getLogger("DEB") 2007db96d56Sopenharmony_ci DEB.setLevel(logging.DEBUG) 2017db96d56Sopenharmony_ci 2027db96d56Sopenharmony_ci # These should log. 2037db96d56Sopenharmony_ci ERR.log(logging.CRITICAL, m()) 2047db96d56Sopenharmony_ci ERR.error(m()) 2057db96d56Sopenharmony_ci 2067db96d56Sopenharmony_ci INF.log(logging.CRITICAL, m()) 2077db96d56Sopenharmony_ci INF.error(m()) 2087db96d56Sopenharmony_ci INF.warning(m()) 2097db96d56Sopenharmony_ci INF.info(m()) 2107db96d56Sopenharmony_ci 2117db96d56Sopenharmony_ci DEB.log(logging.CRITICAL, m()) 2127db96d56Sopenharmony_ci DEB.error(m()) 2137db96d56Sopenharmony_ci DEB.warning(m()) 2147db96d56Sopenharmony_ci DEB.info(m()) 2157db96d56Sopenharmony_ci DEB.debug(m()) 2167db96d56Sopenharmony_ci 2177db96d56Sopenharmony_ci # These should not log. 2187db96d56Sopenharmony_ci ERR.warning(m()) 2197db96d56Sopenharmony_ci ERR.info(m()) 2207db96d56Sopenharmony_ci ERR.debug(m()) 2217db96d56Sopenharmony_ci 2227db96d56Sopenharmony_ci INF.debug(m()) 2237db96d56Sopenharmony_ci 2247db96d56Sopenharmony_ci self.assert_log_lines([ 2257db96d56Sopenharmony_ci ('ERR', 'CRITICAL', '1'), 2267db96d56Sopenharmony_ci ('ERR', 'ERROR', '2'), 2277db96d56Sopenharmony_ci ('INF', 'CRITICAL', '3'), 2287db96d56Sopenharmony_ci ('INF', 'ERROR', '4'), 2297db96d56Sopenharmony_ci ('INF', 'WARNING', '5'), 2307db96d56Sopenharmony_ci ('INF', 'INFO', '6'), 2317db96d56Sopenharmony_ci ('DEB', 'CRITICAL', '7'), 2327db96d56Sopenharmony_ci ('DEB', 'ERROR', '8'), 2337db96d56Sopenharmony_ci ('DEB', 'WARNING', '9'), 2347db96d56Sopenharmony_ci ('DEB', 'INFO', '10'), 2357db96d56Sopenharmony_ci ('DEB', 'DEBUG', '11'), 2367db96d56Sopenharmony_ci ]) 2377db96d56Sopenharmony_ci 2387db96d56Sopenharmony_ci def test_nested_explicit(self): 2397db96d56Sopenharmony_ci # Logging levels in a nested namespace, all explicitly set. 2407db96d56Sopenharmony_ci m = self.next_message 2417db96d56Sopenharmony_ci 2427db96d56Sopenharmony_ci INF = logging.getLogger("INF") 2437db96d56Sopenharmony_ci INF.setLevel(logging.INFO) 2447db96d56Sopenharmony_ci INF_ERR = logging.getLogger("INF.ERR") 2457db96d56Sopenharmony_ci INF_ERR.setLevel(logging.ERROR) 2467db96d56Sopenharmony_ci 2477db96d56Sopenharmony_ci # These should log. 2487db96d56Sopenharmony_ci INF_ERR.log(logging.CRITICAL, m()) 2497db96d56Sopenharmony_ci INF_ERR.error(m()) 2507db96d56Sopenharmony_ci 2517db96d56Sopenharmony_ci # These should not log. 2527db96d56Sopenharmony_ci INF_ERR.warning(m()) 2537db96d56Sopenharmony_ci INF_ERR.info(m()) 2547db96d56Sopenharmony_ci INF_ERR.debug(m()) 2557db96d56Sopenharmony_ci 2567db96d56Sopenharmony_ci self.assert_log_lines([ 2577db96d56Sopenharmony_ci ('INF.ERR', 'CRITICAL', '1'), 2587db96d56Sopenharmony_ci ('INF.ERR', 'ERROR', '2'), 2597db96d56Sopenharmony_ci ]) 2607db96d56Sopenharmony_ci 2617db96d56Sopenharmony_ci def test_nested_inherited(self): 2627db96d56Sopenharmony_ci # Logging levels in a nested namespace, inherited from parent loggers. 2637db96d56Sopenharmony_ci m = self.next_message 2647db96d56Sopenharmony_ci 2657db96d56Sopenharmony_ci INF = logging.getLogger("INF") 2667db96d56Sopenharmony_ci INF.setLevel(logging.INFO) 2677db96d56Sopenharmony_ci INF_ERR = logging.getLogger("INF.ERR") 2687db96d56Sopenharmony_ci INF_ERR.setLevel(logging.ERROR) 2697db96d56Sopenharmony_ci INF_UNDEF = logging.getLogger("INF.UNDEF") 2707db96d56Sopenharmony_ci INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF") 2717db96d56Sopenharmony_ci UNDEF = logging.getLogger("UNDEF") 2727db96d56Sopenharmony_ci 2737db96d56Sopenharmony_ci # These should log. 2747db96d56Sopenharmony_ci INF_UNDEF.log(logging.CRITICAL, m()) 2757db96d56Sopenharmony_ci INF_UNDEF.error(m()) 2767db96d56Sopenharmony_ci INF_UNDEF.warning(m()) 2777db96d56Sopenharmony_ci INF_UNDEF.info(m()) 2787db96d56Sopenharmony_ci INF_ERR_UNDEF.log(logging.CRITICAL, m()) 2797db96d56Sopenharmony_ci INF_ERR_UNDEF.error(m()) 2807db96d56Sopenharmony_ci 2817db96d56Sopenharmony_ci # These should not log. 2827db96d56Sopenharmony_ci INF_UNDEF.debug(m()) 2837db96d56Sopenharmony_ci INF_ERR_UNDEF.warning(m()) 2847db96d56Sopenharmony_ci INF_ERR_UNDEF.info(m()) 2857db96d56Sopenharmony_ci INF_ERR_UNDEF.debug(m()) 2867db96d56Sopenharmony_ci 2877db96d56Sopenharmony_ci self.assert_log_lines([ 2887db96d56Sopenharmony_ci ('INF.UNDEF', 'CRITICAL', '1'), 2897db96d56Sopenharmony_ci ('INF.UNDEF', 'ERROR', '2'), 2907db96d56Sopenharmony_ci ('INF.UNDEF', 'WARNING', '3'), 2917db96d56Sopenharmony_ci ('INF.UNDEF', 'INFO', '4'), 2927db96d56Sopenharmony_ci ('INF.ERR.UNDEF', 'CRITICAL', '5'), 2937db96d56Sopenharmony_ci ('INF.ERR.UNDEF', 'ERROR', '6'), 2947db96d56Sopenharmony_ci ]) 2957db96d56Sopenharmony_ci 2967db96d56Sopenharmony_ci def test_nested_with_virtual_parent(self): 2977db96d56Sopenharmony_ci # Logging levels when some parent does not exist yet. 2987db96d56Sopenharmony_ci m = self.next_message 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ci INF = logging.getLogger("INF") 3017db96d56Sopenharmony_ci GRANDCHILD = logging.getLogger("INF.BADPARENT.UNDEF") 3027db96d56Sopenharmony_ci CHILD = logging.getLogger("INF.BADPARENT") 3037db96d56Sopenharmony_ci INF.setLevel(logging.INFO) 3047db96d56Sopenharmony_ci 3057db96d56Sopenharmony_ci # These should log. 3067db96d56Sopenharmony_ci GRANDCHILD.log(logging.FATAL, m()) 3077db96d56Sopenharmony_ci GRANDCHILD.info(m()) 3087db96d56Sopenharmony_ci CHILD.log(logging.FATAL, m()) 3097db96d56Sopenharmony_ci CHILD.info(m()) 3107db96d56Sopenharmony_ci 3117db96d56Sopenharmony_ci # These should not log. 3127db96d56Sopenharmony_ci GRANDCHILD.debug(m()) 3137db96d56Sopenharmony_ci CHILD.debug(m()) 3147db96d56Sopenharmony_ci 3157db96d56Sopenharmony_ci self.assert_log_lines([ 3167db96d56Sopenharmony_ci ('INF.BADPARENT.UNDEF', 'CRITICAL', '1'), 3177db96d56Sopenharmony_ci ('INF.BADPARENT.UNDEF', 'INFO', '2'), 3187db96d56Sopenharmony_ci ('INF.BADPARENT', 'CRITICAL', '3'), 3197db96d56Sopenharmony_ci ('INF.BADPARENT', 'INFO', '4'), 3207db96d56Sopenharmony_ci ]) 3217db96d56Sopenharmony_ci 3227db96d56Sopenharmony_ci def test_regression_22386(self): 3237db96d56Sopenharmony_ci """See issue #22386 for more information.""" 3247db96d56Sopenharmony_ci self.assertEqual(logging.getLevelName('INFO'), logging.INFO) 3257db96d56Sopenharmony_ci self.assertEqual(logging.getLevelName(logging.INFO), 'INFO') 3267db96d56Sopenharmony_ci 3277db96d56Sopenharmony_ci def test_issue27935(self): 3287db96d56Sopenharmony_ci fatal = logging.getLevelName('FATAL') 3297db96d56Sopenharmony_ci self.assertEqual(fatal, logging.FATAL) 3307db96d56Sopenharmony_ci 3317db96d56Sopenharmony_ci def test_regression_29220(self): 3327db96d56Sopenharmony_ci """See issue #29220 for more information.""" 3337db96d56Sopenharmony_ci logging.addLevelName(logging.INFO, '') 3347db96d56Sopenharmony_ci self.addCleanup(logging.addLevelName, logging.INFO, 'INFO') 3357db96d56Sopenharmony_ci self.assertEqual(logging.getLevelName(logging.INFO), '') 3367db96d56Sopenharmony_ci self.assertEqual(logging.getLevelName(logging.NOTSET), 'NOTSET') 3377db96d56Sopenharmony_ci self.assertEqual(logging.getLevelName('NOTSET'), logging.NOTSET) 3387db96d56Sopenharmony_ci 3397db96d56Sopenharmony_ciclass BasicFilterTest(BaseTest): 3407db96d56Sopenharmony_ci 3417db96d56Sopenharmony_ci """Test the bundled Filter class.""" 3427db96d56Sopenharmony_ci 3437db96d56Sopenharmony_ci def test_filter(self): 3447db96d56Sopenharmony_ci # Only messages satisfying the specified criteria pass through the 3457db96d56Sopenharmony_ci # filter. 3467db96d56Sopenharmony_ci filter_ = logging.Filter("spam.eggs") 3477db96d56Sopenharmony_ci handler = self.root_logger.handlers[0] 3487db96d56Sopenharmony_ci try: 3497db96d56Sopenharmony_ci handler.addFilter(filter_) 3507db96d56Sopenharmony_ci spam = logging.getLogger("spam") 3517db96d56Sopenharmony_ci spam_eggs = logging.getLogger("spam.eggs") 3527db96d56Sopenharmony_ci spam_eggs_fish = logging.getLogger("spam.eggs.fish") 3537db96d56Sopenharmony_ci spam_bakedbeans = logging.getLogger("spam.bakedbeans") 3547db96d56Sopenharmony_ci 3557db96d56Sopenharmony_ci spam.info(self.next_message()) 3567db96d56Sopenharmony_ci spam_eggs.info(self.next_message()) # Good. 3577db96d56Sopenharmony_ci spam_eggs_fish.info(self.next_message()) # Good. 3587db96d56Sopenharmony_ci spam_bakedbeans.info(self.next_message()) 3597db96d56Sopenharmony_ci 3607db96d56Sopenharmony_ci self.assert_log_lines([ 3617db96d56Sopenharmony_ci ('spam.eggs', 'INFO', '2'), 3627db96d56Sopenharmony_ci ('spam.eggs.fish', 'INFO', '3'), 3637db96d56Sopenharmony_ci ]) 3647db96d56Sopenharmony_ci finally: 3657db96d56Sopenharmony_ci handler.removeFilter(filter_) 3667db96d56Sopenharmony_ci 3677db96d56Sopenharmony_ci def test_callable_filter(self): 3687db96d56Sopenharmony_ci # Only messages satisfying the specified criteria pass through the 3697db96d56Sopenharmony_ci # filter. 3707db96d56Sopenharmony_ci 3717db96d56Sopenharmony_ci def filterfunc(record): 3727db96d56Sopenharmony_ci parts = record.name.split('.') 3737db96d56Sopenharmony_ci prefix = '.'.join(parts[:2]) 3747db96d56Sopenharmony_ci return prefix == 'spam.eggs' 3757db96d56Sopenharmony_ci 3767db96d56Sopenharmony_ci handler = self.root_logger.handlers[0] 3777db96d56Sopenharmony_ci try: 3787db96d56Sopenharmony_ci handler.addFilter(filterfunc) 3797db96d56Sopenharmony_ci spam = logging.getLogger("spam") 3807db96d56Sopenharmony_ci spam_eggs = logging.getLogger("spam.eggs") 3817db96d56Sopenharmony_ci spam_eggs_fish = logging.getLogger("spam.eggs.fish") 3827db96d56Sopenharmony_ci spam_bakedbeans = logging.getLogger("spam.bakedbeans") 3837db96d56Sopenharmony_ci 3847db96d56Sopenharmony_ci spam.info(self.next_message()) 3857db96d56Sopenharmony_ci spam_eggs.info(self.next_message()) # Good. 3867db96d56Sopenharmony_ci spam_eggs_fish.info(self.next_message()) # Good. 3877db96d56Sopenharmony_ci spam_bakedbeans.info(self.next_message()) 3887db96d56Sopenharmony_ci 3897db96d56Sopenharmony_ci self.assert_log_lines([ 3907db96d56Sopenharmony_ci ('spam.eggs', 'INFO', '2'), 3917db96d56Sopenharmony_ci ('spam.eggs.fish', 'INFO', '3'), 3927db96d56Sopenharmony_ci ]) 3937db96d56Sopenharmony_ci finally: 3947db96d56Sopenharmony_ci handler.removeFilter(filterfunc) 3957db96d56Sopenharmony_ci 3967db96d56Sopenharmony_ci def test_empty_filter(self): 3977db96d56Sopenharmony_ci f = logging.Filter() 3987db96d56Sopenharmony_ci r = logging.makeLogRecord({'name': 'spam.eggs'}) 3997db96d56Sopenharmony_ci self.assertTrue(f.filter(r)) 4007db96d56Sopenharmony_ci 4017db96d56Sopenharmony_ci# 4027db96d56Sopenharmony_ci# First, we define our levels. There can be as many as you want - the only 4037db96d56Sopenharmony_ci# limitations are that they should be integers, the lowest should be > 0 and 4047db96d56Sopenharmony_ci# larger values mean less information being logged. If you need specific 4057db96d56Sopenharmony_ci# level values which do not fit into these limitations, you can use a 4067db96d56Sopenharmony_ci# mapping dictionary to convert between your application levels and the 4077db96d56Sopenharmony_ci# logging system. 4087db96d56Sopenharmony_ci# 4097db96d56Sopenharmony_ciSILENT = 120 4107db96d56Sopenharmony_ciTACITURN = 119 4117db96d56Sopenharmony_ciTERSE = 118 4127db96d56Sopenharmony_ciEFFUSIVE = 117 4137db96d56Sopenharmony_ciSOCIABLE = 116 4147db96d56Sopenharmony_ciVERBOSE = 115 4157db96d56Sopenharmony_ciTALKATIVE = 114 4167db96d56Sopenharmony_ciGARRULOUS = 113 4177db96d56Sopenharmony_ciCHATTERBOX = 112 4187db96d56Sopenharmony_ciBORING = 111 4197db96d56Sopenharmony_ci 4207db96d56Sopenharmony_ciLEVEL_RANGE = range(BORING, SILENT + 1) 4217db96d56Sopenharmony_ci 4227db96d56Sopenharmony_ci# 4237db96d56Sopenharmony_ci# Next, we define names for our levels. You don't need to do this - in which 4247db96d56Sopenharmony_ci# case the system will use "Level n" to denote the text for the level. 4257db96d56Sopenharmony_ci# 4267db96d56Sopenharmony_cimy_logging_levels = { 4277db96d56Sopenharmony_ci SILENT : 'Silent', 4287db96d56Sopenharmony_ci TACITURN : 'Taciturn', 4297db96d56Sopenharmony_ci TERSE : 'Terse', 4307db96d56Sopenharmony_ci EFFUSIVE : 'Effusive', 4317db96d56Sopenharmony_ci SOCIABLE : 'Sociable', 4327db96d56Sopenharmony_ci VERBOSE : 'Verbose', 4337db96d56Sopenharmony_ci TALKATIVE : 'Talkative', 4347db96d56Sopenharmony_ci GARRULOUS : 'Garrulous', 4357db96d56Sopenharmony_ci CHATTERBOX : 'Chatterbox', 4367db96d56Sopenharmony_ci BORING : 'Boring', 4377db96d56Sopenharmony_ci} 4387db96d56Sopenharmony_ci 4397db96d56Sopenharmony_ciclass GarrulousFilter(logging.Filter): 4407db96d56Sopenharmony_ci 4417db96d56Sopenharmony_ci """A filter which blocks garrulous messages.""" 4427db96d56Sopenharmony_ci 4437db96d56Sopenharmony_ci def filter(self, record): 4447db96d56Sopenharmony_ci return record.levelno != GARRULOUS 4457db96d56Sopenharmony_ci 4467db96d56Sopenharmony_ciclass VerySpecificFilter(logging.Filter): 4477db96d56Sopenharmony_ci 4487db96d56Sopenharmony_ci """A filter which blocks sociable and taciturn messages.""" 4497db96d56Sopenharmony_ci 4507db96d56Sopenharmony_ci def filter(self, record): 4517db96d56Sopenharmony_ci return record.levelno not in [SOCIABLE, TACITURN] 4527db96d56Sopenharmony_ci 4537db96d56Sopenharmony_ci 4547db96d56Sopenharmony_ciclass CustomLevelsAndFiltersTest(BaseTest): 4557db96d56Sopenharmony_ci 4567db96d56Sopenharmony_ci """Test various filtering possibilities with custom logging levels.""" 4577db96d56Sopenharmony_ci 4587db96d56Sopenharmony_ci # Skip the logger name group. 4597db96d56Sopenharmony_ci expected_log_pat = r"^[\w.]+ -> (\w+): (\d+)$" 4607db96d56Sopenharmony_ci 4617db96d56Sopenharmony_ci def setUp(self): 4627db96d56Sopenharmony_ci BaseTest.setUp(self) 4637db96d56Sopenharmony_ci for k, v in my_logging_levels.items(): 4647db96d56Sopenharmony_ci logging.addLevelName(k, v) 4657db96d56Sopenharmony_ci 4667db96d56Sopenharmony_ci def log_at_all_levels(self, logger): 4677db96d56Sopenharmony_ci for lvl in LEVEL_RANGE: 4687db96d56Sopenharmony_ci logger.log(lvl, self.next_message()) 4697db96d56Sopenharmony_ci 4707db96d56Sopenharmony_ci def test_logger_filter(self): 4717db96d56Sopenharmony_ci # Filter at logger level. 4727db96d56Sopenharmony_ci self.root_logger.setLevel(VERBOSE) 4737db96d56Sopenharmony_ci # Levels >= 'Verbose' are good. 4747db96d56Sopenharmony_ci self.log_at_all_levels(self.root_logger) 4757db96d56Sopenharmony_ci self.assert_log_lines([ 4767db96d56Sopenharmony_ci ('Verbose', '5'), 4777db96d56Sopenharmony_ci ('Sociable', '6'), 4787db96d56Sopenharmony_ci ('Effusive', '7'), 4797db96d56Sopenharmony_ci ('Terse', '8'), 4807db96d56Sopenharmony_ci ('Taciturn', '9'), 4817db96d56Sopenharmony_ci ('Silent', '10'), 4827db96d56Sopenharmony_ci ]) 4837db96d56Sopenharmony_ci 4847db96d56Sopenharmony_ci def test_handler_filter(self): 4857db96d56Sopenharmony_ci # Filter at handler level. 4867db96d56Sopenharmony_ci self.root_logger.handlers[0].setLevel(SOCIABLE) 4877db96d56Sopenharmony_ci try: 4887db96d56Sopenharmony_ci # Levels >= 'Sociable' are good. 4897db96d56Sopenharmony_ci self.log_at_all_levels(self.root_logger) 4907db96d56Sopenharmony_ci self.assert_log_lines([ 4917db96d56Sopenharmony_ci ('Sociable', '6'), 4927db96d56Sopenharmony_ci ('Effusive', '7'), 4937db96d56Sopenharmony_ci ('Terse', '8'), 4947db96d56Sopenharmony_ci ('Taciturn', '9'), 4957db96d56Sopenharmony_ci ('Silent', '10'), 4967db96d56Sopenharmony_ci ]) 4977db96d56Sopenharmony_ci finally: 4987db96d56Sopenharmony_ci self.root_logger.handlers[0].setLevel(logging.NOTSET) 4997db96d56Sopenharmony_ci 5007db96d56Sopenharmony_ci def test_specific_filters(self): 5017db96d56Sopenharmony_ci # Set a specific filter object on the handler, and then add another 5027db96d56Sopenharmony_ci # filter object on the logger itself. 5037db96d56Sopenharmony_ci handler = self.root_logger.handlers[0] 5047db96d56Sopenharmony_ci specific_filter = None 5057db96d56Sopenharmony_ci garr = GarrulousFilter() 5067db96d56Sopenharmony_ci handler.addFilter(garr) 5077db96d56Sopenharmony_ci try: 5087db96d56Sopenharmony_ci self.log_at_all_levels(self.root_logger) 5097db96d56Sopenharmony_ci first_lines = [ 5107db96d56Sopenharmony_ci # Notice how 'Garrulous' is missing 5117db96d56Sopenharmony_ci ('Boring', '1'), 5127db96d56Sopenharmony_ci ('Chatterbox', '2'), 5137db96d56Sopenharmony_ci ('Talkative', '4'), 5147db96d56Sopenharmony_ci ('Verbose', '5'), 5157db96d56Sopenharmony_ci ('Sociable', '6'), 5167db96d56Sopenharmony_ci ('Effusive', '7'), 5177db96d56Sopenharmony_ci ('Terse', '8'), 5187db96d56Sopenharmony_ci ('Taciturn', '9'), 5197db96d56Sopenharmony_ci ('Silent', '10'), 5207db96d56Sopenharmony_ci ] 5217db96d56Sopenharmony_ci self.assert_log_lines(first_lines) 5227db96d56Sopenharmony_ci 5237db96d56Sopenharmony_ci specific_filter = VerySpecificFilter() 5247db96d56Sopenharmony_ci self.root_logger.addFilter(specific_filter) 5257db96d56Sopenharmony_ci self.log_at_all_levels(self.root_logger) 5267db96d56Sopenharmony_ci self.assert_log_lines(first_lines + [ 5277db96d56Sopenharmony_ci # Not only 'Garrulous' is still missing, but also 'Sociable' 5287db96d56Sopenharmony_ci # and 'Taciturn' 5297db96d56Sopenharmony_ci ('Boring', '11'), 5307db96d56Sopenharmony_ci ('Chatterbox', '12'), 5317db96d56Sopenharmony_ci ('Talkative', '14'), 5327db96d56Sopenharmony_ci ('Verbose', '15'), 5337db96d56Sopenharmony_ci ('Effusive', '17'), 5347db96d56Sopenharmony_ci ('Terse', '18'), 5357db96d56Sopenharmony_ci ('Silent', '20'), 5367db96d56Sopenharmony_ci ]) 5377db96d56Sopenharmony_ci finally: 5387db96d56Sopenharmony_ci if specific_filter: 5397db96d56Sopenharmony_ci self.root_logger.removeFilter(specific_filter) 5407db96d56Sopenharmony_ci handler.removeFilter(garr) 5417db96d56Sopenharmony_ci 5427db96d56Sopenharmony_ci 5437db96d56Sopenharmony_ciclass HandlerTest(BaseTest): 5447db96d56Sopenharmony_ci def test_name(self): 5457db96d56Sopenharmony_ci h = logging.Handler() 5467db96d56Sopenharmony_ci h.name = 'generic' 5477db96d56Sopenharmony_ci self.assertEqual(h.name, 'generic') 5487db96d56Sopenharmony_ci h.name = 'anothergeneric' 5497db96d56Sopenharmony_ci self.assertEqual(h.name, 'anothergeneric') 5507db96d56Sopenharmony_ci self.assertRaises(NotImplementedError, h.emit, None) 5517db96d56Sopenharmony_ci 5527db96d56Sopenharmony_ci def test_builtin_handlers(self): 5537db96d56Sopenharmony_ci # We can't actually *use* too many handlers in the tests, 5547db96d56Sopenharmony_ci # but we can try instantiating them with various options 5557db96d56Sopenharmony_ci if sys.platform in ('linux', 'darwin'): 5567db96d56Sopenharmony_ci for existing in (True, False): 5577db96d56Sopenharmony_ci fd, fn = tempfile.mkstemp() 5587db96d56Sopenharmony_ci os.close(fd) 5597db96d56Sopenharmony_ci if not existing: 5607db96d56Sopenharmony_ci os.unlink(fn) 5617db96d56Sopenharmony_ci h = logging.handlers.WatchedFileHandler(fn, encoding='utf-8', delay=True) 5627db96d56Sopenharmony_ci if existing: 5637db96d56Sopenharmony_ci dev, ino = h.dev, h.ino 5647db96d56Sopenharmony_ci self.assertEqual(dev, -1) 5657db96d56Sopenharmony_ci self.assertEqual(ino, -1) 5667db96d56Sopenharmony_ci r = logging.makeLogRecord({'msg': 'Test'}) 5677db96d56Sopenharmony_ci h.handle(r) 5687db96d56Sopenharmony_ci # Now remove the file. 5697db96d56Sopenharmony_ci os.unlink(fn) 5707db96d56Sopenharmony_ci self.assertFalse(os.path.exists(fn)) 5717db96d56Sopenharmony_ci # The next call should recreate the file. 5727db96d56Sopenharmony_ci h.handle(r) 5737db96d56Sopenharmony_ci self.assertTrue(os.path.exists(fn)) 5747db96d56Sopenharmony_ci else: 5757db96d56Sopenharmony_ci self.assertEqual(h.dev, -1) 5767db96d56Sopenharmony_ci self.assertEqual(h.ino, -1) 5777db96d56Sopenharmony_ci h.close() 5787db96d56Sopenharmony_ci if existing: 5797db96d56Sopenharmony_ci os.unlink(fn) 5807db96d56Sopenharmony_ci if sys.platform == 'darwin': 5817db96d56Sopenharmony_ci sockname = '/var/run/syslog' 5827db96d56Sopenharmony_ci else: 5837db96d56Sopenharmony_ci sockname = '/dev/log' 5847db96d56Sopenharmony_ci try: 5857db96d56Sopenharmony_ci h = logging.handlers.SysLogHandler(sockname) 5867db96d56Sopenharmony_ci self.assertEqual(h.facility, h.LOG_USER) 5877db96d56Sopenharmony_ci self.assertTrue(h.unixsocket) 5887db96d56Sopenharmony_ci h.close() 5897db96d56Sopenharmony_ci except OSError: # syslogd might not be available 5907db96d56Sopenharmony_ci pass 5917db96d56Sopenharmony_ci for method in ('GET', 'POST', 'PUT'): 5927db96d56Sopenharmony_ci if method == 'PUT': 5937db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.handlers.HTTPHandler, 5947db96d56Sopenharmony_ci 'localhost', '/log', method) 5957db96d56Sopenharmony_ci else: 5967db96d56Sopenharmony_ci h = logging.handlers.HTTPHandler('localhost', '/log', method) 5977db96d56Sopenharmony_ci h.close() 5987db96d56Sopenharmony_ci h = logging.handlers.BufferingHandler(0) 5997db96d56Sopenharmony_ci r = logging.makeLogRecord({}) 6007db96d56Sopenharmony_ci self.assertTrue(h.shouldFlush(r)) 6017db96d56Sopenharmony_ci h.close() 6027db96d56Sopenharmony_ci h = logging.handlers.BufferingHandler(1) 6037db96d56Sopenharmony_ci self.assertFalse(h.shouldFlush(r)) 6047db96d56Sopenharmony_ci h.close() 6057db96d56Sopenharmony_ci 6067db96d56Sopenharmony_ci def test_path_objects(self): 6077db96d56Sopenharmony_ci """ 6087db96d56Sopenharmony_ci Test that Path objects are accepted as filename arguments to handlers. 6097db96d56Sopenharmony_ci 6107db96d56Sopenharmony_ci See Issue #27493. 6117db96d56Sopenharmony_ci """ 6127db96d56Sopenharmony_ci fd, fn = tempfile.mkstemp() 6137db96d56Sopenharmony_ci os.close(fd) 6147db96d56Sopenharmony_ci os.unlink(fn) 6157db96d56Sopenharmony_ci pfn = pathlib.Path(fn) 6167db96d56Sopenharmony_ci cases = ( 6177db96d56Sopenharmony_ci (logging.FileHandler, (pfn, 'w')), 6187db96d56Sopenharmony_ci (logging.handlers.RotatingFileHandler, (pfn, 'a')), 6197db96d56Sopenharmony_ci (logging.handlers.TimedRotatingFileHandler, (pfn, 'h')), 6207db96d56Sopenharmony_ci ) 6217db96d56Sopenharmony_ci if sys.platform in ('linux', 'darwin'): 6227db96d56Sopenharmony_ci cases += ((logging.handlers.WatchedFileHandler, (pfn, 'w')),) 6237db96d56Sopenharmony_ci for cls, args in cases: 6247db96d56Sopenharmony_ci h = cls(*args, encoding="utf-8") 6257db96d56Sopenharmony_ci self.assertTrue(os.path.exists(fn)) 6267db96d56Sopenharmony_ci h.close() 6277db96d56Sopenharmony_ci os.unlink(fn) 6287db96d56Sopenharmony_ci 6297db96d56Sopenharmony_ci @unittest.skipIf(os.name == 'nt', 'WatchedFileHandler not appropriate for Windows.') 6307db96d56Sopenharmony_ci @unittest.skipIf( 6317db96d56Sopenharmony_ci support.is_emscripten, "Emscripten cannot fstat unlinked files." 6327db96d56Sopenharmony_ci ) 6337db96d56Sopenharmony_ci @threading_helper.requires_working_threading() 6347db96d56Sopenharmony_ci def test_race(self): 6357db96d56Sopenharmony_ci # Issue #14632 refers. 6367db96d56Sopenharmony_ci def remove_loop(fname, tries): 6377db96d56Sopenharmony_ci for _ in range(tries): 6387db96d56Sopenharmony_ci try: 6397db96d56Sopenharmony_ci os.unlink(fname) 6407db96d56Sopenharmony_ci self.deletion_time = time.time() 6417db96d56Sopenharmony_ci except OSError: 6427db96d56Sopenharmony_ci pass 6437db96d56Sopenharmony_ci time.sleep(0.004 * random.randint(0, 4)) 6447db96d56Sopenharmony_ci 6457db96d56Sopenharmony_ci del_count = 500 6467db96d56Sopenharmony_ci log_count = 500 6477db96d56Sopenharmony_ci 6487db96d56Sopenharmony_ci self.handle_time = None 6497db96d56Sopenharmony_ci self.deletion_time = None 6507db96d56Sopenharmony_ci 6517db96d56Sopenharmony_ci for delay in (False, True): 6527db96d56Sopenharmony_ci fd, fn = tempfile.mkstemp('.log', 'test_logging-3-') 6537db96d56Sopenharmony_ci os.close(fd) 6547db96d56Sopenharmony_ci remover = threading.Thread(target=remove_loop, args=(fn, del_count)) 6557db96d56Sopenharmony_ci remover.daemon = True 6567db96d56Sopenharmony_ci remover.start() 6577db96d56Sopenharmony_ci h = logging.handlers.WatchedFileHandler(fn, encoding='utf-8', delay=delay) 6587db96d56Sopenharmony_ci f = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s') 6597db96d56Sopenharmony_ci h.setFormatter(f) 6607db96d56Sopenharmony_ci try: 6617db96d56Sopenharmony_ci for _ in range(log_count): 6627db96d56Sopenharmony_ci time.sleep(0.005) 6637db96d56Sopenharmony_ci r = logging.makeLogRecord({'msg': 'testing' }) 6647db96d56Sopenharmony_ci try: 6657db96d56Sopenharmony_ci self.handle_time = time.time() 6667db96d56Sopenharmony_ci h.handle(r) 6677db96d56Sopenharmony_ci except Exception: 6687db96d56Sopenharmony_ci print('Deleted at %s, ' 6697db96d56Sopenharmony_ci 'opened at %s' % (self.deletion_time, 6707db96d56Sopenharmony_ci self.handle_time)) 6717db96d56Sopenharmony_ci raise 6727db96d56Sopenharmony_ci finally: 6737db96d56Sopenharmony_ci remover.join() 6747db96d56Sopenharmony_ci h.close() 6757db96d56Sopenharmony_ci if os.path.exists(fn): 6767db96d56Sopenharmony_ci os.unlink(fn) 6777db96d56Sopenharmony_ci 6787db96d56Sopenharmony_ci # The implementation relies on os.register_at_fork existing, but we test 6797db96d56Sopenharmony_ci # based on os.fork existing because that is what users and this test use. 6807db96d56Sopenharmony_ci # This helps ensure that when fork exists (the important concept) that the 6817db96d56Sopenharmony_ci # register_at_fork mechanism is also present and used. 6827db96d56Sopenharmony_ci @support.requires_fork() 6837db96d56Sopenharmony_ci @threading_helper.requires_working_threading() 6847db96d56Sopenharmony_ci def test_post_fork_child_no_deadlock(self): 6857db96d56Sopenharmony_ci """Ensure child logging locks are not held; bpo-6721 & bpo-36533.""" 6867db96d56Sopenharmony_ci class _OurHandler(logging.Handler): 6877db96d56Sopenharmony_ci def __init__(self): 6887db96d56Sopenharmony_ci super().__init__() 6897db96d56Sopenharmony_ci self.sub_handler = logging.StreamHandler( 6907db96d56Sopenharmony_ci stream=open('/dev/null', 'wt', encoding='utf-8')) 6917db96d56Sopenharmony_ci 6927db96d56Sopenharmony_ci def emit(self, record): 6937db96d56Sopenharmony_ci self.sub_handler.acquire() 6947db96d56Sopenharmony_ci try: 6957db96d56Sopenharmony_ci self.sub_handler.emit(record) 6967db96d56Sopenharmony_ci finally: 6977db96d56Sopenharmony_ci self.sub_handler.release() 6987db96d56Sopenharmony_ci 6997db96d56Sopenharmony_ci self.assertEqual(len(logging._handlers), 0) 7007db96d56Sopenharmony_ci refed_h = _OurHandler() 7017db96d56Sopenharmony_ci self.addCleanup(refed_h.sub_handler.stream.close) 7027db96d56Sopenharmony_ci refed_h.name = 'because we need at least one for this test' 7037db96d56Sopenharmony_ci self.assertGreater(len(logging._handlers), 0) 7047db96d56Sopenharmony_ci self.assertGreater(len(logging._at_fork_reinit_lock_weakset), 1) 7057db96d56Sopenharmony_ci test_logger = logging.getLogger('test_post_fork_child_no_deadlock') 7067db96d56Sopenharmony_ci test_logger.addHandler(refed_h) 7077db96d56Sopenharmony_ci test_logger.setLevel(logging.DEBUG) 7087db96d56Sopenharmony_ci 7097db96d56Sopenharmony_ci locks_held__ready_to_fork = threading.Event() 7107db96d56Sopenharmony_ci fork_happened__release_locks_and_end_thread = threading.Event() 7117db96d56Sopenharmony_ci 7127db96d56Sopenharmony_ci def lock_holder_thread_fn(): 7137db96d56Sopenharmony_ci logging._acquireLock() 7147db96d56Sopenharmony_ci try: 7157db96d56Sopenharmony_ci refed_h.acquire() 7167db96d56Sopenharmony_ci try: 7177db96d56Sopenharmony_ci # Tell the main thread to do the fork. 7187db96d56Sopenharmony_ci locks_held__ready_to_fork.set() 7197db96d56Sopenharmony_ci 7207db96d56Sopenharmony_ci # If the deadlock bug exists, the fork will happen 7217db96d56Sopenharmony_ci # without dealing with the locks we hold, deadlocking 7227db96d56Sopenharmony_ci # the child. 7237db96d56Sopenharmony_ci 7247db96d56Sopenharmony_ci # Wait for a successful fork or an unreasonable amount of 7257db96d56Sopenharmony_ci # time before releasing our locks. To avoid a timing based 7267db96d56Sopenharmony_ci # test we'd need communication from os.fork() as to when it 7277db96d56Sopenharmony_ci # has actually happened. Given this is a regression test 7287db96d56Sopenharmony_ci # for a fixed issue, potentially less reliably detecting 7297db96d56Sopenharmony_ci # regression via timing is acceptable for simplicity. 7307db96d56Sopenharmony_ci # The test will always take at least this long. :( 7317db96d56Sopenharmony_ci fork_happened__release_locks_and_end_thread.wait(0.5) 7327db96d56Sopenharmony_ci finally: 7337db96d56Sopenharmony_ci refed_h.release() 7347db96d56Sopenharmony_ci finally: 7357db96d56Sopenharmony_ci logging._releaseLock() 7367db96d56Sopenharmony_ci 7377db96d56Sopenharmony_ci lock_holder_thread = threading.Thread( 7387db96d56Sopenharmony_ci target=lock_holder_thread_fn, 7397db96d56Sopenharmony_ci name='test_post_fork_child_no_deadlock lock holder') 7407db96d56Sopenharmony_ci lock_holder_thread.start() 7417db96d56Sopenharmony_ci 7427db96d56Sopenharmony_ci locks_held__ready_to_fork.wait() 7437db96d56Sopenharmony_ci pid = os.fork() 7447db96d56Sopenharmony_ci if pid == 0: 7457db96d56Sopenharmony_ci # Child process 7467db96d56Sopenharmony_ci try: 7477db96d56Sopenharmony_ci test_logger.info(r'Child process did not deadlock. \o/') 7487db96d56Sopenharmony_ci finally: 7497db96d56Sopenharmony_ci os._exit(0) 7507db96d56Sopenharmony_ci else: 7517db96d56Sopenharmony_ci # Parent process 7527db96d56Sopenharmony_ci test_logger.info(r'Parent process returned from fork. \o/') 7537db96d56Sopenharmony_ci fork_happened__release_locks_and_end_thread.set() 7547db96d56Sopenharmony_ci lock_holder_thread.join() 7557db96d56Sopenharmony_ci 7567db96d56Sopenharmony_ci support.wait_process(pid, exitcode=0) 7577db96d56Sopenharmony_ci 7587db96d56Sopenharmony_ci 7597db96d56Sopenharmony_ciclass BadStream(object): 7607db96d56Sopenharmony_ci def write(self, data): 7617db96d56Sopenharmony_ci raise RuntimeError('deliberate mistake') 7627db96d56Sopenharmony_ci 7637db96d56Sopenharmony_ciclass TestStreamHandler(logging.StreamHandler): 7647db96d56Sopenharmony_ci def handleError(self, record): 7657db96d56Sopenharmony_ci self.error_record = record 7667db96d56Sopenharmony_ci 7677db96d56Sopenharmony_ciclass StreamWithIntName(object): 7687db96d56Sopenharmony_ci level = logging.NOTSET 7697db96d56Sopenharmony_ci name = 2 7707db96d56Sopenharmony_ci 7717db96d56Sopenharmony_ciclass StreamHandlerTest(BaseTest): 7727db96d56Sopenharmony_ci def test_error_handling(self): 7737db96d56Sopenharmony_ci h = TestStreamHandler(BadStream()) 7747db96d56Sopenharmony_ci r = logging.makeLogRecord({}) 7757db96d56Sopenharmony_ci old_raise = logging.raiseExceptions 7767db96d56Sopenharmony_ci 7777db96d56Sopenharmony_ci try: 7787db96d56Sopenharmony_ci h.handle(r) 7797db96d56Sopenharmony_ci self.assertIs(h.error_record, r) 7807db96d56Sopenharmony_ci 7817db96d56Sopenharmony_ci h = logging.StreamHandler(BadStream()) 7827db96d56Sopenharmony_ci with support.captured_stderr() as stderr: 7837db96d56Sopenharmony_ci h.handle(r) 7847db96d56Sopenharmony_ci msg = '\nRuntimeError: deliberate mistake\n' 7857db96d56Sopenharmony_ci self.assertIn(msg, stderr.getvalue()) 7867db96d56Sopenharmony_ci 7877db96d56Sopenharmony_ci logging.raiseExceptions = False 7887db96d56Sopenharmony_ci with support.captured_stderr() as stderr: 7897db96d56Sopenharmony_ci h.handle(r) 7907db96d56Sopenharmony_ci self.assertEqual('', stderr.getvalue()) 7917db96d56Sopenharmony_ci finally: 7927db96d56Sopenharmony_ci logging.raiseExceptions = old_raise 7937db96d56Sopenharmony_ci 7947db96d56Sopenharmony_ci def test_stream_setting(self): 7957db96d56Sopenharmony_ci """ 7967db96d56Sopenharmony_ci Test setting the handler's stream 7977db96d56Sopenharmony_ci """ 7987db96d56Sopenharmony_ci h = logging.StreamHandler() 7997db96d56Sopenharmony_ci stream = io.StringIO() 8007db96d56Sopenharmony_ci old = h.setStream(stream) 8017db96d56Sopenharmony_ci self.assertIs(old, sys.stderr) 8027db96d56Sopenharmony_ci actual = h.setStream(old) 8037db96d56Sopenharmony_ci self.assertIs(actual, stream) 8047db96d56Sopenharmony_ci # test that setting to existing value returns None 8057db96d56Sopenharmony_ci actual = h.setStream(old) 8067db96d56Sopenharmony_ci self.assertIsNone(actual) 8077db96d56Sopenharmony_ci 8087db96d56Sopenharmony_ci def test_can_represent_stream_with_int_name(self): 8097db96d56Sopenharmony_ci h = logging.StreamHandler(StreamWithIntName()) 8107db96d56Sopenharmony_ci self.assertEqual(repr(h), '<StreamHandler 2 (NOTSET)>') 8117db96d56Sopenharmony_ci 8127db96d56Sopenharmony_ci# -- The following section could be moved into a server_helper.py module 8137db96d56Sopenharmony_ci# -- if it proves to be of wider utility than just test_logging 8147db96d56Sopenharmony_ci 8157db96d56Sopenharmony_ciclass TestSMTPServer(smtpd.SMTPServer): 8167db96d56Sopenharmony_ci """ 8177db96d56Sopenharmony_ci This class implements a test SMTP server. 8187db96d56Sopenharmony_ci 8197db96d56Sopenharmony_ci :param addr: A (host, port) tuple which the server listens on. 8207db96d56Sopenharmony_ci You can specify a port value of zero: the server's 8217db96d56Sopenharmony_ci *port* attribute will hold the actual port number 8227db96d56Sopenharmony_ci used, which can be used in client connections. 8237db96d56Sopenharmony_ci :param handler: A callable which will be called to process 8247db96d56Sopenharmony_ci incoming messages. The handler will be passed 8257db96d56Sopenharmony_ci the client address tuple, who the message is from, 8267db96d56Sopenharmony_ci a list of recipients and the message data. 8277db96d56Sopenharmony_ci :param poll_interval: The interval, in seconds, used in the underlying 8287db96d56Sopenharmony_ci :func:`select` or :func:`poll` call by 8297db96d56Sopenharmony_ci :func:`asyncore.loop`. 8307db96d56Sopenharmony_ci :param sockmap: A dictionary which will be used to hold 8317db96d56Sopenharmony_ci :class:`asyncore.dispatcher` instances used by 8327db96d56Sopenharmony_ci :func:`asyncore.loop`. This avoids changing the 8337db96d56Sopenharmony_ci :mod:`asyncore` module's global state. 8347db96d56Sopenharmony_ci """ 8357db96d56Sopenharmony_ci 8367db96d56Sopenharmony_ci def __init__(self, addr, handler, poll_interval, sockmap): 8377db96d56Sopenharmony_ci smtpd.SMTPServer.__init__(self, addr, None, map=sockmap, 8387db96d56Sopenharmony_ci decode_data=True) 8397db96d56Sopenharmony_ci self.port = self.socket.getsockname()[1] 8407db96d56Sopenharmony_ci self._handler = handler 8417db96d56Sopenharmony_ci self._thread = None 8427db96d56Sopenharmony_ci self._quit = False 8437db96d56Sopenharmony_ci self.poll_interval = poll_interval 8447db96d56Sopenharmony_ci 8457db96d56Sopenharmony_ci def process_message(self, peer, mailfrom, rcpttos, data): 8467db96d56Sopenharmony_ci """ 8477db96d56Sopenharmony_ci Delegates to the handler passed in to the server's constructor. 8487db96d56Sopenharmony_ci 8497db96d56Sopenharmony_ci Typically, this will be a test case method. 8507db96d56Sopenharmony_ci :param peer: The client (host, port) tuple. 8517db96d56Sopenharmony_ci :param mailfrom: The address of the sender. 8527db96d56Sopenharmony_ci :param rcpttos: The addresses of the recipients. 8537db96d56Sopenharmony_ci :param data: The message. 8547db96d56Sopenharmony_ci """ 8557db96d56Sopenharmony_ci self._handler(peer, mailfrom, rcpttos, data) 8567db96d56Sopenharmony_ci 8577db96d56Sopenharmony_ci def start(self): 8587db96d56Sopenharmony_ci """ 8597db96d56Sopenharmony_ci Start the server running on a separate daemon thread. 8607db96d56Sopenharmony_ci """ 8617db96d56Sopenharmony_ci self._thread = t = threading.Thread(target=self.serve_forever, 8627db96d56Sopenharmony_ci args=(self.poll_interval,)) 8637db96d56Sopenharmony_ci t.daemon = True 8647db96d56Sopenharmony_ci t.start() 8657db96d56Sopenharmony_ci 8667db96d56Sopenharmony_ci def serve_forever(self, poll_interval): 8677db96d56Sopenharmony_ci """ 8687db96d56Sopenharmony_ci Run the :mod:`asyncore` loop until normal termination 8697db96d56Sopenharmony_ci conditions arise. 8707db96d56Sopenharmony_ci :param poll_interval: The interval, in seconds, used in the underlying 8717db96d56Sopenharmony_ci :func:`select` or :func:`poll` call by 8727db96d56Sopenharmony_ci :func:`asyncore.loop`. 8737db96d56Sopenharmony_ci """ 8747db96d56Sopenharmony_ci while not self._quit: 8757db96d56Sopenharmony_ci asyncore.loop(poll_interval, map=self._map, count=1) 8767db96d56Sopenharmony_ci 8777db96d56Sopenharmony_ci def stop(self): 8787db96d56Sopenharmony_ci """ 8797db96d56Sopenharmony_ci Stop the thread by closing the server instance. 8807db96d56Sopenharmony_ci Wait for the server thread to terminate. 8817db96d56Sopenharmony_ci """ 8827db96d56Sopenharmony_ci self._quit = True 8837db96d56Sopenharmony_ci threading_helper.join_thread(self._thread) 8847db96d56Sopenharmony_ci self._thread = None 8857db96d56Sopenharmony_ci self.close() 8867db96d56Sopenharmony_ci asyncore.close_all(map=self._map, ignore_all=True) 8877db96d56Sopenharmony_ci 8887db96d56Sopenharmony_ci 8897db96d56Sopenharmony_ciclass ControlMixin(object): 8907db96d56Sopenharmony_ci """ 8917db96d56Sopenharmony_ci This mixin is used to start a server on a separate thread, and 8927db96d56Sopenharmony_ci shut it down programmatically. Request handling is simplified - instead 8937db96d56Sopenharmony_ci of needing to derive a suitable RequestHandler subclass, you just 8947db96d56Sopenharmony_ci provide a callable which will be passed each received request to be 8957db96d56Sopenharmony_ci processed. 8967db96d56Sopenharmony_ci 8977db96d56Sopenharmony_ci :param handler: A handler callable which will be called with a 8987db96d56Sopenharmony_ci single parameter - the request - in order to 8997db96d56Sopenharmony_ci process the request. This handler is called on the 9007db96d56Sopenharmony_ci server thread, effectively meaning that requests are 9017db96d56Sopenharmony_ci processed serially. While not quite web scale ;-), 9027db96d56Sopenharmony_ci this should be fine for testing applications. 9037db96d56Sopenharmony_ci :param poll_interval: The polling interval in seconds. 9047db96d56Sopenharmony_ci """ 9057db96d56Sopenharmony_ci def __init__(self, handler, poll_interval): 9067db96d56Sopenharmony_ci self._thread = None 9077db96d56Sopenharmony_ci self.poll_interval = poll_interval 9087db96d56Sopenharmony_ci self._handler = handler 9097db96d56Sopenharmony_ci self.ready = threading.Event() 9107db96d56Sopenharmony_ci 9117db96d56Sopenharmony_ci def start(self): 9127db96d56Sopenharmony_ci """ 9137db96d56Sopenharmony_ci Create a daemon thread to run the server, and start it. 9147db96d56Sopenharmony_ci """ 9157db96d56Sopenharmony_ci self._thread = t = threading.Thread(target=self.serve_forever, 9167db96d56Sopenharmony_ci args=(self.poll_interval,)) 9177db96d56Sopenharmony_ci t.daemon = True 9187db96d56Sopenharmony_ci t.start() 9197db96d56Sopenharmony_ci 9207db96d56Sopenharmony_ci def serve_forever(self, poll_interval): 9217db96d56Sopenharmony_ci """ 9227db96d56Sopenharmony_ci Run the server. Set the ready flag before entering the 9237db96d56Sopenharmony_ci service loop. 9247db96d56Sopenharmony_ci """ 9257db96d56Sopenharmony_ci self.ready.set() 9267db96d56Sopenharmony_ci super(ControlMixin, self).serve_forever(poll_interval) 9277db96d56Sopenharmony_ci 9287db96d56Sopenharmony_ci def stop(self): 9297db96d56Sopenharmony_ci """ 9307db96d56Sopenharmony_ci Tell the server thread to stop, and wait for it to do so. 9317db96d56Sopenharmony_ci """ 9327db96d56Sopenharmony_ci self.shutdown() 9337db96d56Sopenharmony_ci if self._thread is not None: 9347db96d56Sopenharmony_ci threading_helper.join_thread(self._thread) 9357db96d56Sopenharmony_ci self._thread = None 9367db96d56Sopenharmony_ci self.server_close() 9377db96d56Sopenharmony_ci self.ready.clear() 9387db96d56Sopenharmony_ci 9397db96d56Sopenharmony_ciclass TestHTTPServer(ControlMixin, HTTPServer): 9407db96d56Sopenharmony_ci """ 9417db96d56Sopenharmony_ci An HTTP server which is controllable using :class:`ControlMixin`. 9427db96d56Sopenharmony_ci 9437db96d56Sopenharmony_ci :param addr: A tuple with the IP address and port to listen on. 9447db96d56Sopenharmony_ci :param handler: A handler callable which will be called with a 9457db96d56Sopenharmony_ci single parameter - the request - in order to 9467db96d56Sopenharmony_ci process the request. 9477db96d56Sopenharmony_ci :param poll_interval: The polling interval in seconds. 9487db96d56Sopenharmony_ci :param log: Pass ``True`` to enable log messages. 9497db96d56Sopenharmony_ci """ 9507db96d56Sopenharmony_ci def __init__(self, addr, handler, poll_interval=0.5, 9517db96d56Sopenharmony_ci log=False, sslctx=None): 9527db96d56Sopenharmony_ci class DelegatingHTTPRequestHandler(BaseHTTPRequestHandler): 9537db96d56Sopenharmony_ci def __getattr__(self, name, default=None): 9547db96d56Sopenharmony_ci if name.startswith('do_'): 9557db96d56Sopenharmony_ci return self.process_request 9567db96d56Sopenharmony_ci raise AttributeError(name) 9577db96d56Sopenharmony_ci 9587db96d56Sopenharmony_ci def process_request(self): 9597db96d56Sopenharmony_ci self.server._handler(self) 9607db96d56Sopenharmony_ci 9617db96d56Sopenharmony_ci def log_message(self, format, *args): 9627db96d56Sopenharmony_ci if log: 9637db96d56Sopenharmony_ci super(DelegatingHTTPRequestHandler, 9647db96d56Sopenharmony_ci self).log_message(format, *args) 9657db96d56Sopenharmony_ci HTTPServer.__init__(self, addr, DelegatingHTTPRequestHandler) 9667db96d56Sopenharmony_ci ControlMixin.__init__(self, handler, poll_interval) 9677db96d56Sopenharmony_ci self.sslctx = sslctx 9687db96d56Sopenharmony_ci 9697db96d56Sopenharmony_ci def get_request(self): 9707db96d56Sopenharmony_ci try: 9717db96d56Sopenharmony_ci sock, addr = self.socket.accept() 9727db96d56Sopenharmony_ci if self.sslctx: 9737db96d56Sopenharmony_ci sock = self.sslctx.wrap_socket(sock, server_side=True) 9747db96d56Sopenharmony_ci except OSError as e: 9757db96d56Sopenharmony_ci # socket errors are silenced by the caller, print them here 9767db96d56Sopenharmony_ci sys.stderr.write("Got an error:\n%s\n" % e) 9777db96d56Sopenharmony_ci raise 9787db96d56Sopenharmony_ci return sock, addr 9797db96d56Sopenharmony_ci 9807db96d56Sopenharmony_ciclass TestTCPServer(ControlMixin, ThreadingTCPServer): 9817db96d56Sopenharmony_ci """ 9827db96d56Sopenharmony_ci A TCP server which is controllable using :class:`ControlMixin`. 9837db96d56Sopenharmony_ci 9847db96d56Sopenharmony_ci :param addr: A tuple with the IP address and port to listen on. 9857db96d56Sopenharmony_ci :param handler: A handler callable which will be called with a single 9867db96d56Sopenharmony_ci parameter - the request - in order to process the request. 9877db96d56Sopenharmony_ci :param poll_interval: The polling interval in seconds. 9887db96d56Sopenharmony_ci :bind_and_activate: If True (the default), binds the server and starts it 9897db96d56Sopenharmony_ci listening. If False, you need to call 9907db96d56Sopenharmony_ci :meth:`server_bind` and :meth:`server_activate` at 9917db96d56Sopenharmony_ci some later time before calling :meth:`start`, so that 9927db96d56Sopenharmony_ci the server will set up the socket and listen on it. 9937db96d56Sopenharmony_ci """ 9947db96d56Sopenharmony_ci 9957db96d56Sopenharmony_ci allow_reuse_address = True 9967db96d56Sopenharmony_ci 9977db96d56Sopenharmony_ci def __init__(self, addr, handler, poll_interval=0.5, 9987db96d56Sopenharmony_ci bind_and_activate=True): 9997db96d56Sopenharmony_ci class DelegatingTCPRequestHandler(StreamRequestHandler): 10007db96d56Sopenharmony_ci 10017db96d56Sopenharmony_ci def handle(self): 10027db96d56Sopenharmony_ci self.server._handler(self) 10037db96d56Sopenharmony_ci ThreadingTCPServer.__init__(self, addr, DelegatingTCPRequestHandler, 10047db96d56Sopenharmony_ci bind_and_activate) 10057db96d56Sopenharmony_ci ControlMixin.__init__(self, handler, poll_interval) 10067db96d56Sopenharmony_ci 10077db96d56Sopenharmony_ci def server_bind(self): 10087db96d56Sopenharmony_ci super(TestTCPServer, self).server_bind() 10097db96d56Sopenharmony_ci self.port = self.socket.getsockname()[1] 10107db96d56Sopenharmony_ci 10117db96d56Sopenharmony_ciclass TestUDPServer(ControlMixin, ThreadingUDPServer): 10127db96d56Sopenharmony_ci """ 10137db96d56Sopenharmony_ci A UDP server which is controllable using :class:`ControlMixin`. 10147db96d56Sopenharmony_ci 10157db96d56Sopenharmony_ci :param addr: A tuple with the IP address and port to listen on. 10167db96d56Sopenharmony_ci :param handler: A handler callable which will be called with a 10177db96d56Sopenharmony_ci single parameter - the request - in order to 10187db96d56Sopenharmony_ci process the request. 10197db96d56Sopenharmony_ci :param poll_interval: The polling interval for shutdown requests, 10207db96d56Sopenharmony_ci in seconds. 10217db96d56Sopenharmony_ci :bind_and_activate: If True (the default), binds the server and 10227db96d56Sopenharmony_ci starts it listening. If False, you need to 10237db96d56Sopenharmony_ci call :meth:`server_bind` and 10247db96d56Sopenharmony_ci :meth:`server_activate` at some later time 10257db96d56Sopenharmony_ci before calling :meth:`start`, so that the server will 10267db96d56Sopenharmony_ci set up the socket and listen on it. 10277db96d56Sopenharmony_ci """ 10287db96d56Sopenharmony_ci def __init__(self, addr, handler, poll_interval=0.5, 10297db96d56Sopenharmony_ci bind_and_activate=True): 10307db96d56Sopenharmony_ci class DelegatingUDPRequestHandler(DatagramRequestHandler): 10317db96d56Sopenharmony_ci 10327db96d56Sopenharmony_ci def handle(self): 10337db96d56Sopenharmony_ci self.server._handler(self) 10347db96d56Sopenharmony_ci 10357db96d56Sopenharmony_ci def finish(self): 10367db96d56Sopenharmony_ci data = self.wfile.getvalue() 10377db96d56Sopenharmony_ci if data: 10387db96d56Sopenharmony_ci try: 10397db96d56Sopenharmony_ci super(DelegatingUDPRequestHandler, self).finish() 10407db96d56Sopenharmony_ci except OSError: 10417db96d56Sopenharmony_ci if not self.server._closed: 10427db96d56Sopenharmony_ci raise 10437db96d56Sopenharmony_ci 10447db96d56Sopenharmony_ci ThreadingUDPServer.__init__(self, addr, 10457db96d56Sopenharmony_ci DelegatingUDPRequestHandler, 10467db96d56Sopenharmony_ci bind_and_activate) 10477db96d56Sopenharmony_ci ControlMixin.__init__(self, handler, poll_interval) 10487db96d56Sopenharmony_ci self._closed = False 10497db96d56Sopenharmony_ci 10507db96d56Sopenharmony_ci def server_bind(self): 10517db96d56Sopenharmony_ci super(TestUDPServer, self).server_bind() 10527db96d56Sopenharmony_ci self.port = self.socket.getsockname()[1] 10537db96d56Sopenharmony_ci 10547db96d56Sopenharmony_ci def server_close(self): 10557db96d56Sopenharmony_ci super(TestUDPServer, self).server_close() 10567db96d56Sopenharmony_ci self._closed = True 10577db96d56Sopenharmony_ci 10587db96d56Sopenharmony_ciif hasattr(socket, "AF_UNIX"): 10597db96d56Sopenharmony_ci class TestUnixStreamServer(TestTCPServer): 10607db96d56Sopenharmony_ci address_family = socket.AF_UNIX 10617db96d56Sopenharmony_ci 10627db96d56Sopenharmony_ci class TestUnixDatagramServer(TestUDPServer): 10637db96d56Sopenharmony_ci address_family = socket.AF_UNIX 10647db96d56Sopenharmony_ci 10657db96d56Sopenharmony_ci# - end of server_helper section 10667db96d56Sopenharmony_ci 10677db96d56Sopenharmony_ci@support.requires_working_socket() 10687db96d56Sopenharmony_ci@threading_helper.requires_working_threading() 10697db96d56Sopenharmony_ciclass SMTPHandlerTest(BaseTest): 10707db96d56Sopenharmony_ci # bpo-14314, bpo-19665, bpo-34092: don't wait forever 10717db96d56Sopenharmony_ci TIMEOUT = support.LONG_TIMEOUT 10727db96d56Sopenharmony_ci 10737db96d56Sopenharmony_ci def test_basic(self): 10747db96d56Sopenharmony_ci sockmap = {} 10757db96d56Sopenharmony_ci server = TestSMTPServer((socket_helper.HOST, 0), self.process_message, 0.001, 10767db96d56Sopenharmony_ci sockmap) 10777db96d56Sopenharmony_ci server.start() 10787db96d56Sopenharmony_ci addr = (socket_helper.HOST, server.port) 10797db96d56Sopenharmony_ci h = logging.handlers.SMTPHandler(addr, 'me', 'you', 'Log', 10807db96d56Sopenharmony_ci timeout=self.TIMEOUT) 10817db96d56Sopenharmony_ci self.assertEqual(h.toaddrs, ['you']) 10827db96d56Sopenharmony_ci self.messages = [] 10837db96d56Sopenharmony_ci r = logging.makeLogRecord({'msg': 'Hello \u2713'}) 10847db96d56Sopenharmony_ci self.handled = threading.Event() 10857db96d56Sopenharmony_ci h.handle(r) 10867db96d56Sopenharmony_ci self.handled.wait(self.TIMEOUT) 10877db96d56Sopenharmony_ci server.stop() 10887db96d56Sopenharmony_ci self.assertTrue(self.handled.is_set()) 10897db96d56Sopenharmony_ci self.assertEqual(len(self.messages), 1) 10907db96d56Sopenharmony_ci peer, mailfrom, rcpttos, data = self.messages[0] 10917db96d56Sopenharmony_ci self.assertEqual(mailfrom, 'me') 10927db96d56Sopenharmony_ci self.assertEqual(rcpttos, ['you']) 10937db96d56Sopenharmony_ci self.assertIn('\nSubject: Log\n', data) 10947db96d56Sopenharmony_ci self.assertTrue(data.endswith('\n\nHello \u2713')) 10957db96d56Sopenharmony_ci h.close() 10967db96d56Sopenharmony_ci 10977db96d56Sopenharmony_ci def process_message(self, *args): 10987db96d56Sopenharmony_ci self.messages.append(args) 10997db96d56Sopenharmony_ci self.handled.set() 11007db96d56Sopenharmony_ci 11017db96d56Sopenharmony_ciclass MemoryHandlerTest(BaseTest): 11027db96d56Sopenharmony_ci 11037db96d56Sopenharmony_ci """Tests for the MemoryHandler.""" 11047db96d56Sopenharmony_ci 11057db96d56Sopenharmony_ci # Do not bother with a logger name group. 11067db96d56Sopenharmony_ci expected_log_pat = r"^[\w.]+ -> (\w+): (\d+)$" 11077db96d56Sopenharmony_ci 11087db96d56Sopenharmony_ci def setUp(self): 11097db96d56Sopenharmony_ci BaseTest.setUp(self) 11107db96d56Sopenharmony_ci self.mem_hdlr = logging.handlers.MemoryHandler(10, logging.WARNING, 11117db96d56Sopenharmony_ci self.root_hdlr) 11127db96d56Sopenharmony_ci self.mem_logger = logging.getLogger('mem') 11137db96d56Sopenharmony_ci self.mem_logger.propagate = 0 11147db96d56Sopenharmony_ci self.mem_logger.addHandler(self.mem_hdlr) 11157db96d56Sopenharmony_ci 11167db96d56Sopenharmony_ci def tearDown(self): 11177db96d56Sopenharmony_ci self.mem_hdlr.close() 11187db96d56Sopenharmony_ci BaseTest.tearDown(self) 11197db96d56Sopenharmony_ci 11207db96d56Sopenharmony_ci def test_flush(self): 11217db96d56Sopenharmony_ci # The memory handler flushes to its target handler based on specific 11227db96d56Sopenharmony_ci # criteria (message count and message level). 11237db96d56Sopenharmony_ci self.mem_logger.debug(self.next_message()) 11247db96d56Sopenharmony_ci self.assert_log_lines([]) 11257db96d56Sopenharmony_ci self.mem_logger.info(self.next_message()) 11267db96d56Sopenharmony_ci self.assert_log_lines([]) 11277db96d56Sopenharmony_ci # This will flush because the level is >= logging.WARNING 11287db96d56Sopenharmony_ci self.mem_logger.warning(self.next_message()) 11297db96d56Sopenharmony_ci lines = [ 11307db96d56Sopenharmony_ci ('DEBUG', '1'), 11317db96d56Sopenharmony_ci ('INFO', '2'), 11327db96d56Sopenharmony_ci ('WARNING', '3'), 11337db96d56Sopenharmony_ci ] 11347db96d56Sopenharmony_ci self.assert_log_lines(lines) 11357db96d56Sopenharmony_ci for n in (4, 14): 11367db96d56Sopenharmony_ci for i in range(9): 11377db96d56Sopenharmony_ci self.mem_logger.debug(self.next_message()) 11387db96d56Sopenharmony_ci self.assert_log_lines(lines) 11397db96d56Sopenharmony_ci # This will flush because it's the 10th message since the last 11407db96d56Sopenharmony_ci # flush. 11417db96d56Sopenharmony_ci self.mem_logger.debug(self.next_message()) 11427db96d56Sopenharmony_ci lines = lines + [('DEBUG', str(i)) for i in range(n, n + 10)] 11437db96d56Sopenharmony_ci self.assert_log_lines(lines) 11447db96d56Sopenharmony_ci 11457db96d56Sopenharmony_ci self.mem_logger.debug(self.next_message()) 11467db96d56Sopenharmony_ci self.assert_log_lines(lines) 11477db96d56Sopenharmony_ci 11487db96d56Sopenharmony_ci def test_flush_on_close(self): 11497db96d56Sopenharmony_ci """ 11507db96d56Sopenharmony_ci Test that the flush-on-close configuration works as expected. 11517db96d56Sopenharmony_ci """ 11527db96d56Sopenharmony_ci self.mem_logger.debug(self.next_message()) 11537db96d56Sopenharmony_ci self.assert_log_lines([]) 11547db96d56Sopenharmony_ci self.mem_logger.info(self.next_message()) 11557db96d56Sopenharmony_ci self.assert_log_lines([]) 11567db96d56Sopenharmony_ci self.mem_logger.removeHandler(self.mem_hdlr) 11577db96d56Sopenharmony_ci # Default behaviour is to flush on close. Check that it happens. 11587db96d56Sopenharmony_ci self.mem_hdlr.close() 11597db96d56Sopenharmony_ci lines = [ 11607db96d56Sopenharmony_ci ('DEBUG', '1'), 11617db96d56Sopenharmony_ci ('INFO', '2'), 11627db96d56Sopenharmony_ci ] 11637db96d56Sopenharmony_ci self.assert_log_lines(lines) 11647db96d56Sopenharmony_ci # Now configure for flushing not to be done on close. 11657db96d56Sopenharmony_ci self.mem_hdlr = logging.handlers.MemoryHandler(10, logging.WARNING, 11667db96d56Sopenharmony_ci self.root_hdlr, 11677db96d56Sopenharmony_ci False) 11687db96d56Sopenharmony_ci self.mem_logger.addHandler(self.mem_hdlr) 11697db96d56Sopenharmony_ci self.mem_logger.debug(self.next_message()) 11707db96d56Sopenharmony_ci self.assert_log_lines(lines) # no change 11717db96d56Sopenharmony_ci self.mem_logger.info(self.next_message()) 11727db96d56Sopenharmony_ci self.assert_log_lines(lines) # no change 11737db96d56Sopenharmony_ci self.mem_logger.removeHandler(self.mem_hdlr) 11747db96d56Sopenharmony_ci self.mem_hdlr.close() 11757db96d56Sopenharmony_ci # assert that no new lines have been added 11767db96d56Sopenharmony_ci self.assert_log_lines(lines) # no change 11777db96d56Sopenharmony_ci 11787db96d56Sopenharmony_ci @threading_helper.requires_working_threading() 11797db96d56Sopenharmony_ci def test_race_between_set_target_and_flush(self): 11807db96d56Sopenharmony_ci class MockRaceConditionHandler: 11817db96d56Sopenharmony_ci def __init__(self, mem_hdlr): 11827db96d56Sopenharmony_ci self.mem_hdlr = mem_hdlr 11837db96d56Sopenharmony_ci self.threads = [] 11847db96d56Sopenharmony_ci 11857db96d56Sopenharmony_ci def removeTarget(self): 11867db96d56Sopenharmony_ci self.mem_hdlr.setTarget(None) 11877db96d56Sopenharmony_ci 11887db96d56Sopenharmony_ci def handle(self, msg): 11897db96d56Sopenharmony_ci thread = threading.Thread(target=self.removeTarget) 11907db96d56Sopenharmony_ci self.threads.append(thread) 11917db96d56Sopenharmony_ci thread.start() 11927db96d56Sopenharmony_ci 11937db96d56Sopenharmony_ci target = MockRaceConditionHandler(self.mem_hdlr) 11947db96d56Sopenharmony_ci try: 11957db96d56Sopenharmony_ci self.mem_hdlr.setTarget(target) 11967db96d56Sopenharmony_ci 11977db96d56Sopenharmony_ci for _ in range(10): 11987db96d56Sopenharmony_ci time.sleep(0.005) 11997db96d56Sopenharmony_ci self.mem_logger.info("not flushed") 12007db96d56Sopenharmony_ci self.mem_logger.warning("flushed") 12017db96d56Sopenharmony_ci finally: 12027db96d56Sopenharmony_ci for thread in target.threads: 12037db96d56Sopenharmony_ci threading_helper.join_thread(thread) 12047db96d56Sopenharmony_ci 12057db96d56Sopenharmony_ci 12067db96d56Sopenharmony_ciclass ExceptionFormatter(logging.Formatter): 12077db96d56Sopenharmony_ci """A special exception formatter.""" 12087db96d56Sopenharmony_ci def formatException(self, ei): 12097db96d56Sopenharmony_ci return "Got a [%s]" % ei[0].__name__ 12107db96d56Sopenharmony_ci 12117db96d56Sopenharmony_ci 12127db96d56Sopenharmony_ciclass ConfigFileTest(BaseTest): 12137db96d56Sopenharmony_ci 12147db96d56Sopenharmony_ci """Reading logging config from a .ini-style config file.""" 12157db96d56Sopenharmony_ci 12167db96d56Sopenharmony_ci check_no_resource_warning = warnings_helper.check_no_resource_warning 12177db96d56Sopenharmony_ci expected_log_pat = r"^(\w+) \+\+ (\w+)$" 12187db96d56Sopenharmony_ci 12197db96d56Sopenharmony_ci # config0 is a standard configuration. 12207db96d56Sopenharmony_ci config0 = """ 12217db96d56Sopenharmony_ci [loggers] 12227db96d56Sopenharmony_ci keys=root 12237db96d56Sopenharmony_ci 12247db96d56Sopenharmony_ci [handlers] 12257db96d56Sopenharmony_ci keys=hand1 12267db96d56Sopenharmony_ci 12277db96d56Sopenharmony_ci [formatters] 12287db96d56Sopenharmony_ci keys=form1 12297db96d56Sopenharmony_ci 12307db96d56Sopenharmony_ci [logger_root] 12317db96d56Sopenharmony_ci level=WARNING 12327db96d56Sopenharmony_ci handlers=hand1 12337db96d56Sopenharmony_ci 12347db96d56Sopenharmony_ci [handler_hand1] 12357db96d56Sopenharmony_ci class=StreamHandler 12367db96d56Sopenharmony_ci level=NOTSET 12377db96d56Sopenharmony_ci formatter=form1 12387db96d56Sopenharmony_ci args=(sys.stdout,) 12397db96d56Sopenharmony_ci 12407db96d56Sopenharmony_ci [formatter_form1] 12417db96d56Sopenharmony_ci format=%(levelname)s ++ %(message)s 12427db96d56Sopenharmony_ci datefmt= 12437db96d56Sopenharmony_ci """ 12447db96d56Sopenharmony_ci 12457db96d56Sopenharmony_ci # config1 adds a little to the standard configuration. 12467db96d56Sopenharmony_ci config1 = """ 12477db96d56Sopenharmony_ci [loggers] 12487db96d56Sopenharmony_ci keys=root,parser 12497db96d56Sopenharmony_ci 12507db96d56Sopenharmony_ci [handlers] 12517db96d56Sopenharmony_ci keys=hand1 12527db96d56Sopenharmony_ci 12537db96d56Sopenharmony_ci [formatters] 12547db96d56Sopenharmony_ci keys=form1 12557db96d56Sopenharmony_ci 12567db96d56Sopenharmony_ci [logger_root] 12577db96d56Sopenharmony_ci level=WARNING 12587db96d56Sopenharmony_ci handlers= 12597db96d56Sopenharmony_ci 12607db96d56Sopenharmony_ci [logger_parser] 12617db96d56Sopenharmony_ci level=DEBUG 12627db96d56Sopenharmony_ci handlers=hand1 12637db96d56Sopenharmony_ci propagate=1 12647db96d56Sopenharmony_ci qualname=compiler.parser 12657db96d56Sopenharmony_ci 12667db96d56Sopenharmony_ci [handler_hand1] 12677db96d56Sopenharmony_ci class=StreamHandler 12687db96d56Sopenharmony_ci level=NOTSET 12697db96d56Sopenharmony_ci formatter=form1 12707db96d56Sopenharmony_ci args=(sys.stdout,) 12717db96d56Sopenharmony_ci 12727db96d56Sopenharmony_ci [formatter_form1] 12737db96d56Sopenharmony_ci format=%(levelname)s ++ %(message)s 12747db96d56Sopenharmony_ci datefmt= 12757db96d56Sopenharmony_ci """ 12767db96d56Sopenharmony_ci 12777db96d56Sopenharmony_ci # config1a moves the handler to the root. 12787db96d56Sopenharmony_ci config1a = """ 12797db96d56Sopenharmony_ci [loggers] 12807db96d56Sopenharmony_ci keys=root,parser 12817db96d56Sopenharmony_ci 12827db96d56Sopenharmony_ci [handlers] 12837db96d56Sopenharmony_ci keys=hand1 12847db96d56Sopenharmony_ci 12857db96d56Sopenharmony_ci [formatters] 12867db96d56Sopenharmony_ci keys=form1 12877db96d56Sopenharmony_ci 12887db96d56Sopenharmony_ci [logger_root] 12897db96d56Sopenharmony_ci level=WARNING 12907db96d56Sopenharmony_ci handlers=hand1 12917db96d56Sopenharmony_ci 12927db96d56Sopenharmony_ci [logger_parser] 12937db96d56Sopenharmony_ci level=DEBUG 12947db96d56Sopenharmony_ci handlers= 12957db96d56Sopenharmony_ci propagate=1 12967db96d56Sopenharmony_ci qualname=compiler.parser 12977db96d56Sopenharmony_ci 12987db96d56Sopenharmony_ci [handler_hand1] 12997db96d56Sopenharmony_ci class=StreamHandler 13007db96d56Sopenharmony_ci level=NOTSET 13017db96d56Sopenharmony_ci formatter=form1 13027db96d56Sopenharmony_ci args=(sys.stdout,) 13037db96d56Sopenharmony_ci 13047db96d56Sopenharmony_ci [formatter_form1] 13057db96d56Sopenharmony_ci format=%(levelname)s ++ %(message)s 13067db96d56Sopenharmony_ci datefmt= 13077db96d56Sopenharmony_ci """ 13087db96d56Sopenharmony_ci 13097db96d56Sopenharmony_ci # config2 has a subtle configuration error that should be reported 13107db96d56Sopenharmony_ci config2 = config1.replace("sys.stdout", "sys.stbout") 13117db96d56Sopenharmony_ci 13127db96d56Sopenharmony_ci # config3 has a less subtle configuration error 13137db96d56Sopenharmony_ci config3 = config1.replace("formatter=form1", "formatter=misspelled_name") 13147db96d56Sopenharmony_ci 13157db96d56Sopenharmony_ci # config4 specifies a custom formatter class to be loaded 13167db96d56Sopenharmony_ci config4 = """ 13177db96d56Sopenharmony_ci [loggers] 13187db96d56Sopenharmony_ci keys=root 13197db96d56Sopenharmony_ci 13207db96d56Sopenharmony_ci [handlers] 13217db96d56Sopenharmony_ci keys=hand1 13227db96d56Sopenharmony_ci 13237db96d56Sopenharmony_ci [formatters] 13247db96d56Sopenharmony_ci keys=form1 13257db96d56Sopenharmony_ci 13267db96d56Sopenharmony_ci [logger_root] 13277db96d56Sopenharmony_ci level=NOTSET 13287db96d56Sopenharmony_ci handlers=hand1 13297db96d56Sopenharmony_ci 13307db96d56Sopenharmony_ci [handler_hand1] 13317db96d56Sopenharmony_ci class=StreamHandler 13327db96d56Sopenharmony_ci level=NOTSET 13337db96d56Sopenharmony_ci formatter=form1 13347db96d56Sopenharmony_ci args=(sys.stdout,) 13357db96d56Sopenharmony_ci 13367db96d56Sopenharmony_ci [formatter_form1] 13377db96d56Sopenharmony_ci class=""" + __name__ + """.ExceptionFormatter 13387db96d56Sopenharmony_ci format=%(levelname)s:%(name)s:%(message)s 13397db96d56Sopenharmony_ci datefmt= 13407db96d56Sopenharmony_ci """ 13417db96d56Sopenharmony_ci 13427db96d56Sopenharmony_ci # config5 specifies a custom handler class to be loaded 13437db96d56Sopenharmony_ci config5 = config1.replace('class=StreamHandler', 'class=logging.StreamHandler') 13447db96d56Sopenharmony_ci 13457db96d56Sopenharmony_ci # config6 uses ', ' delimiters in the handlers and formatters sections 13467db96d56Sopenharmony_ci config6 = """ 13477db96d56Sopenharmony_ci [loggers] 13487db96d56Sopenharmony_ci keys=root,parser 13497db96d56Sopenharmony_ci 13507db96d56Sopenharmony_ci [handlers] 13517db96d56Sopenharmony_ci keys=hand1, hand2 13527db96d56Sopenharmony_ci 13537db96d56Sopenharmony_ci [formatters] 13547db96d56Sopenharmony_ci keys=form1, form2 13557db96d56Sopenharmony_ci 13567db96d56Sopenharmony_ci [logger_root] 13577db96d56Sopenharmony_ci level=WARNING 13587db96d56Sopenharmony_ci handlers= 13597db96d56Sopenharmony_ci 13607db96d56Sopenharmony_ci [logger_parser] 13617db96d56Sopenharmony_ci level=DEBUG 13627db96d56Sopenharmony_ci handlers=hand1 13637db96d56Sopenharmony_ci propagate=1 13647db96d56Sopenharmony_ci qualname=compiler.parser 13657db96d56Sopenharmony_ci 13667db96d56Sopenharmony_ci [handler_hand1] 13677db96d56Sopenharmony_ci class=StreamHandler 13687db96d56Sopenharmony_ci level=NOTSET 13697db96d56Sopenharmony_ci formatter=form1 13707db96d56Sopenharmony_ci args=(sys.stdout,) 13717db96d56Sopenharmony_ci 13727db96d56Sopenharmony_ci [handler_hand2] 13737db96d56Sopenharmony_ci class=StreamHandler 13747db96d56Sopenharmony_ci level=NOTSET 13757db96d56Sopenharmony_ci formatter=form1 13767db96d56Sopenharmony_ci args=(sys.stderr,) 13777db96d56Sopenharmony_ci 13787db96d56Sopenharmony_ci [formatter_form1] 13797db96d56Sopenharmony_ci format=%(levelname)s ++ %(message)s 13807db96d56Sopenharmony_ci datefmt= 13817db96d56Sopenharmony_ci 13827db96d56Sopenharmony_ci [formatter_form2] 13837db96d56Sopenharmony_ci format=%(message)s 13847db96d56Sopenharmony_ci datefmt= 13857db96d56Sopenharmony_ci """ 13867db96d56Sopenharmony_ci 13877db96d56Sopenharmony_ci # config7 adds a compiler logger, and uses kwargs instead of args. 13887db96d56Sopenharmony_ci config7 = """ 13897db96d56Sopenharmony_ci [loggers] 13907db96d56Sopenharmony_ci keys=root,parser,compiler 13917db96d56Sopenharmony_ci 13927db96d56Sopenharmony_ci [handlers] 13937db96d56Sopenharmony_ci keys=hand1 13947db96d56Sopenharmony_ci 13957db96d56Sopenharmony_ci [formatters] 13967db96d56Sopenharmony_ci keys=form1 13977db96d56Sopenharmony_ci 13987db96d56Sopenharmony_ci [logger_root] 13997db96d56Sopenharmony_ci level=WARNING 14007db96d56Sopenharmony_ci handlers=hand1 14017db96d56Sopenharmony_ci 14027db96d56Sopenharmony_ci [logger_compiler] 14037db96d56Sopenharmony_ci level=DEBUG 14047db96d56Sopenharmony_ci handlers= 14057db96d56Sopenharmony_ci propagate=1 14067db96d56Sopenharmony_ci qualname=compiler 14077db96d56Sopenharmony_ci 14087db96d56Sopenharmony_ci [logger_parser] 14097db96d56Sopenharmony_ci level=DEBUG 14107db96d56Sopenharmony_ci handlers= 14117db96d56Sopenharmony_ci propagate=1 14127db96d56Sopenharmony_ci qualname=compiler.parser 14137db96d56Sopenharmony_ci 14147db96d56Sopenharmony_ci [handler_hand1] 14157db96d56Sopenharmony_ci class=StreamHandler 14167db96d56Sopenharmony_ci level=NOTSET 14177db96d56Sopenharmony_ci formatter=form1 14187db96d56Sopenharmony_ci kwargs={'stream': sys.stdout,} 14197db96d56Sopenharmony_ci 14207db96d56Sopenharmony_ci [formatter_form1] 14217db96d56Sopenharmony_ci format=%(levelname)s ++ %(message)s 14227db96d56Sopenharmony_ci datefmt= 14237db96d56Sopenharmony_ci """ 14247db96d56Sopenharmony_ci 14257db96d56Sopenharmony_ci # config 8, check for resource warning 14267db96d56Sopenharmony_ci config8 = r""" 14277db96d56Sopenharmony_ci [loggers] 14287db96d56Sopenharmony_ci keys=root 14297db96d56Sopenharmony_ci 14307db96d56Sopenharmony_ci [handlers] 14317db96d56Sopenharmony_ci keys=file 14327db96d56Sopenharmony_ci 14337db96d56Sopenharmony_ci [formatters] 14347db96d56Sopenharmony_ci keys= 14357db96d56Sopenharmony_ci 14367db96d56Sopenharmony_ci [logger_root] 14377db96d56Sopenharmony_ci level=DEBUG 14387db96d56Sopenharmony_ci handlers=file 14397db96d56Sopenharmony_ci 14407db96d56Sopenharmony_ci [handler_file] 14417db96d56Sopenharmony_ci class=FileHandler 14427db96d56Sopenharmony_ci level=DEBUG 14437db96d56Sopenharmony_ci args=("{tempfile}",) 14447db96d56Sopenharmony_ci kwargs={{"encoding": "utf-8"}} 14457db96d56Sopenharmony_ci """ 14467db96d56Sopenharmony_ci 14477db96d56Sopenharmony_ci disable_test = """ 14487db96d56Sopenharmony_ci [loggers] 14497db96d56Sopenharmony_ci keys=root 14507db96d56Sopenharmony_ci 14517db96d56Sopenharmony_ci [handlers] 14527db96d56Sopenharmony_ci keys=screen 14537db96d56Sopenharmony_ci 14547db96d56Sopenharmony_ci [formatters] 14557db96d56Sopenharmony_ci keys= 14567db96d56Sopenharmony_ci 14577db96d56Sopenharmony_ci [logger_root] 14587db96d56Sopenharmony_ci level=DEBUG 14597db96d56Sopenharmony_ci handlers=screen 14607db96d56Sopenharmony_ci 14617db96d56Sopenharmony_ci [handler_screen] 14627db96d56Sopenharmony_ci level=DEBUG 14637db96d56Sopenharmony_ci class=StreamHandler 14647db96d56Sopenharmony_ci args=(sys.stdout,) 14657db96d56Sopenharmony_ci formatter= 14667db96d56Sopenharmony_ci """ 14677db96d56Sopenharmony_ci 14687db96d56Sopenharmony_ci def apply_config(self, conf, **kwargs): 14697db96d56Sopenharmony_ci file = io.StringIO(textwrap.dedent(conf)) 14707db96d56Sopenharmony_ci logging.config.fileConfig(file, encoding="utf-8", **kwargs) 14717db96d56Sopenharmony_ci 14727db96d56Sopenharmony_ci def test_config0_ok(self): 14737db96d56Sopenharmony_ci # A simple config file which overrides the default settings. 14747db96d56Sopenharmony_ci with support.captured_stdout() as output: 14757db96d56Sopenharmony_ci self.apply_config(self.config0) 14767db96d56Sopenharmony_ci logger = logging.getLogger() 14777db96d56Sopenharmony_ci # Won't output anything 14787db96d56Sopenharmony_ci logger.info(self.next_message()) 14797db96d56Sopenharmony_ci # Outputs a message 14807db96d56Sopenharmony_ci logger.error(self.next_message()) 14817db96d56Sopenharmony_ci self.assert_log_lines([ 14827db96d56Sopenharmony_ci ('ERROR', '2'), 14837db96d56Sopenharmony_ci ], stream=output) 14847db96d56Sopenharmony_ci # Original logger output is empty. 14857db96d56Sopenharmony_ci self.assert_log_lines([]) 14867db96d56Sopenharmony_ci 14877db96d56Sopenharmony_ci def test_config0_using_cp_ok(self): 14887db96d56Sopenharmony_ci # A simple config file which overrides the default settings. 14897db96d56Sopenharmony_ci with support.captured_stdout() as output: 14907db96d56Sopenharmony_ci file = io.StringIO(textwrap.dedent(self.config0)) 14917db96d56Sopenharmony_ci cp = configparser.ConfigParser() 14927db96d56Sopenharmony_ci cp.read_file(file) 14937db96d56Sopenharmony_ci logging.config.fileConfig(cp) 14947db96d56Sopenharmony_ci logger = logging.getLogger() 14957db96d56Sopenharmony_ci # Won't output anything 14967db96d56Sopenharmony_ci logger.info(self.next_message()) 14977db96d56Sopenharmony_ci # Outputs a message 14987db96d56Sopenharmony_ci logger.error(self.next_message()) 14997db96d56Sopenharmony_ci self.assert_log_lines([ 15007db96d56Sopenharmony_ci ('ERROR', '2'), 15017db96d56Sopenharmony_ci ], stream=output) 15027db96d56Sopenharmony_ci # Original logger output is empty. 15037db96d56Sopenharmony_ci self.assert_log_lines([]) 15047db96d56Sopenharmony_ci 15057db96d56Sopenharmony_ci def test_config1_ok(self, config=config1): 15067db96d56Sopenharmony_ci # A config file defining a sub-parser as well. 15077db96d56Sopenharmony_ci with support.captured_stdout() as output: 15087db96d56Sopenharmony_ci self.apply_config(config) 15097db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 15107db96d56Sopenharmony_ci # Both will output a message 15117db96d56Sopenharmony_ci logger.info(self.next_message()) 15127db96d56Sopenharmony_ci logger.error(self.next_message()) 15137db96d56Sopenharmony_ci self.assert_log_lines([ 15147db96d56Sopenharmony_ci ('INFO', '1'), 15157db96d56Sopenharmony_ci ('ERROR', '2'), 15167db96d56Sopenharmony_ci ], stream=output) 15177db96d56Sopenharmony_ci # Original logger output is empty. 15187db96d56Sopenharmony_ci self.assert_log_lines([]) 15197db96d56Sopenharmony_ci 15207db96d56Sopenharmony_ci def test_config2_failure(self): 15217db96d56Sopenharmony_ci # A simple config file which overrides the default settings. 15227db96d56Sopenharmony_ci self.assertRaises(Exception, self.apply_config, self.config2) 15237db96d56Sopenharmony_ci 15247db96d56Sopenharmony_ci def test_config3_failure(self): 15257db96d56Sopenharmony_ci # A simple config file which overrides the default settings. 15267db96d56Sopenharmony_ci self.assertRaises(Exception, self.apply_config, self.config3) 15277db96d56Sopenharmony_ci 15287db96d56Sopenharmony_ci def test_config4_ok(self): 15297db96d56Sopenharmony_ci # A config file specifying a custom formatter class. 15307db96d56Sopenharmony_ci with support.captured_stdout() as output: 15317db96d56Sopenharmony_ci self.apply_config(self.config4) 15327db96d56Sopenharmony_ci logger = logging.getLogger() 15337db96d56Sopenharmony_ci try: 15347db96d56Sopenharmony_ci raise RuntimeError() 15357db96d56Sopenharmony_ci except RuntimeError: 15367db96d56Sopenharmony_ci logging.exception("just testing") 15377db96d56Sopenharmony_ci sys.stdout.seek(0) 15387db96d56Sopenharmony_ci self.assertEqual(output.getvalue(), 15397db96d56Sopenharmony_ci "ERROR:root:just testing\nGot a [RuntimeError]\n") 15407db96d56Sopenharmony_ci # Original logger output is empty 15417db96d56Sopenharmony_ci self.assert_log_lines([]) 15427db96d56Sopenharmony_ci 15437db96d56Sopenharmony_ci def test_config5_ok(self): 15447db96d56Sopenharmony_ci self.test_config1_ok(config=self.config5) 15457db96d56Sopenharmony_ci 15467db96d56Sopenharmony_ci def test_config6_ok(self): 15477db96d56Sopenharmony_ci self.test_config1_ok(config=self.config6) 15487db96d56Sopenharmony_ci 15497db96d56Sopenharmony_ci def test_config7_ok(self): 15507db96d56Sopenharmony_ci with support.captured_stdout() as output: 15517db96d56Sopenharmony_ci self.apply_config(self.config1a) 15527db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 15537db96d56Sopenharmony_ci # See issue #11424. compiler-hyphenated sorts 15547db96d56Sopenharmony_ci # between compiler and compiler.xyz and this 15557db96d56Sopenharmony_ci # was preventing compiler.xyz from being included 15567db96d56Sopenharmony_ci # in the child loggers of compiler because of an 15577db96d56Sopenharmony_ci # overzealous loop termination condition. 15587db96d56Sopenharmony_ci hyphenated = logging.getLogger('compiler-hyphenated') 15597db96d56Sopenharmony_ci # All will output a message 15607db96d56Sopenharmony_ci logger.info(self.next_message()) 15617db96d56Sopenharmony_ci logger.error(self.next_message()) 15627db96d56Sopenharmony_ci hyphenated.critical(self.next_message()) 15637db96d56Sopenharmony_ci self.assert_log_lines([ 15647db96d56Sopenharmony_ci ('INFO', '1'), 15657db96d56Sopenharmony_ci ('ERROR', '2'), 15667db96d56Sopenharmony_ci ('CRITICAL', '3'), 15677db96d56Sopenharmony_ci ], stream=output) 15687db96d56Sopenharmony_ci # Original logger output is empty. 15697db96d56Sopenharmony_ci self.assert_log_lines([]) 15707db96d56Sopenharmony_ci with support.captured_stdout() as output: 15717db96d56Sopenharmony_ci self.apply_config(self.config7) 15727db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 15737db96d56Sopenharmony_ci self.assertFalse(logger.disabled) 15747db96d56Sopenharmony_ci # Both will output a message 15757db96d56Sopenharmony_ci logger.info(self.next_message()) 15767db96d56Sopenharmony_ci logger.error(self.next_message()) 15777db96d56Sopenharmony_ci logger = logging.getLogger("compiler.lexer") 15787db96d56Sopenharmony_ci # Both will output a message 15797db96d56Sopenharmony_ci logger.info(self.next_message()) 15807db96d56Sopenharmony_ci logger.error(self.next_message()) 15817db96d56Sopenharmony_ci # Will not appear 15827db96d56Sopenharmony_ci hyphenated.critical(self.next_message()) 15837db96d56Sopenharmony_ci self.assert_log_lines([ 15847db96d56Sopenharmony_ci ('INFO', '4'), 15857db96d56Sopenharmony_ci ('ERROR', '5'), 15867db96d56Sopenharmony_ci ('INFO', '6'), 15877db96d56Sopenharmony_ci ('ERROR', '7'), 15887db96d56Sopenharmony_ci ], stream=output) 15897db96d56Sopenharmony_ci # Original logger output is empty. 15907db96d56Sopenharmony_ci self.assert_log_lines([]) 15917db96d56Sopenharmony_ci 15927db96d56Sopenharmony_ci def test_config8_ok(self): 15937db96d56Sopenharmony_ci 15947db96d56Sopenharmony_ci def cleanup(h1, fn): 15957db96d56Sopenharmony_ci h1.close() 15967db96d56Sopenharmony_ci os.remove(fn) 15977db96d56Sopenharmony_ci 15987db96d56Sopenharmony_ci with self.check_no_resource_warning(): 15997db96d56Sopenharmony_ci fd, fn = tempfile.mkstemp(".log", "test_logging-X-") 16007db96d56Sopenharmony_ci os.close(fd) 16017db96d56Sopenharmony_ci 16027db96d56Sopenharmony_ci # Replace single backslash with double backslash in windows 16037db96d56Sopenharmony_ci # to avoid unicode error during string formatting 16047db96d56Sopenharmony_ci if os.name == "nt": 16057db96d56Sopenharmony_ci fn = fn.replace("\\", "\\\\") 16067db96d56Sopenharmony_ci 16077db96d56Sopenharmony_ci config8 = self.config8.format(tempfile=fn) 16087db96d56Sopenharmony_ci 16097db96d56Sopenharmony_ci self.apply_config(config8) 16107db96d56Sopenharmony_ci self.apply_config(config8) 16117db96d56Sopenharmony_ci 16127db96d56Sopenharmony_ci handler = logging.root.handlers[0] 16137db96d56Sopenharmony_ci self.addCleanup(cleanup, handler, fn) 16147db96d56Sopenharmony_ci 16157db96d56Sopenharmony_ci def test_logger_disabling(self): 16167db96d56Sopenharmony_ci self.apply_config(self.disable_test) 16177db96d56Sopenharmony_ci logger = logging.getLogger('some_pristine_logger') 16187db96d56Sopenharmony_ci self.assertFalse(logger.disabled) 16197db96d56Sopenharmony_ci self.apply_config(self.disable_test) 16207db96d56Sopenharmony_ci self.assertTrue(logger.disabled) 16217db96d56Sopenharmony_ci self.apply_config(self.disable_test, disable_existing_loggers=False) 16227db96d56Sopenharmony_ci self.assertFalse(logger.disabled) 16237db96d56Sopenharmony_ci 16247db96d56Sopenharmony_ci def test_config_set_handler_names(self): 16257db96d56Sopenharmony_ci test_config = """ 16267db96d56Sopenharmony_ci [loggers] 16277db96d56Sopenharmony_ci keys=root 16287db96d56Sopenharmony_ci 16297db96d56Sopenharmony_ci [handlers] 16307db96d56Sopenharmony_ci keys=hand1 16317db96d56Sopenharmony_ci 16327db96d56Sopenharmony_ci [formatters] 16337db96d56Sopenharmony_ci keys=form1 16347db96d56Sopenharmony_ci 16357db96d56Sopenharmony_ci [logger_root] 16367db96d56Sopenharmony_ci handlers=hand1 16377db96d56Sopenharmony_ci 16387db96d56Sopenharmony_ci [handler_hand1] 16397db96d56Sopenharmony_ci class=StreamHandler 16407db96d56Sopenharmony_ci formatter=form1 16417db96d56Sopenharmony_ci 16427db96d56Sopenharmony_ci [formatter_form1] 16437db96d56Sopenharmony_ci format=%(levelname)s ++ %(message)s 16447db96d56Sopenharmony_ci """ 16457db96d56Sopenharmony_ci self.apply_config(test_config) 16467db96d56Sopenharmony_ci self.assertEqual(logging.getLogger().handlers[0].name, 'hand1') 16477db96d56Sopenharmony_ci 16487db96d56Sopenharmony_ci def test_exception_if_confg_file_is_invalid(self): 16497db96d56Sopenharmony_ci test_config = """ 16507db96d56Sopenharmony_ci [loggers] 16517db96d56Sopenharmony_ci keys=root 16527db96d56Sopenharmony_ci 16537db96d56Sopenharmony_ci [handlers] 16547db96d56Sopenharmony_ci keys=hand1 16557db96d56Sopenharmony_ci 16567db96d56Sopenharmony_ci [formatters] 16577db96d56Sopenharmony_ci keys=form1 16587db96d56Sopenharmony_ci 16597db96d56Sopenharmony_ci [logger_root] 16607db96d56Sopenharmony_ci handlers=hand1 16617db96d56Sopenharmony_ci 16627db96d56Sopenharmony_ci [handler_hand1] 16637db96d56Sopenharmony_ci class=StreamHandler 16647db96d56Sopenharmony_ci formatter=form1 16657db96d56Sopenharmony_ci 16667db96d56Sopenharmony_ci [formatter_form1] 16677db96d56Sopenharmony_ci format=%(levelname)s ++ %(message)s 16687db96d56Sopenharmony_ci 16697db96d56Sopenharmony_ci prince 16707db96d56Sopenharmony_ci """ 16717db96d56Sopenharmony_ci 16727db96d56Sopenharmony_ci file = io.StringIO(textwrap.dedent(test_config)) 16737db96d56Sopenharmony_ci self.assertRaises(RuntimeError, logging.config.fileConfig, file) 16747db96d56Sopenharmony_ci 16757db96d56Sopenharmony_ci def test_exception_if_confg_file_is_empty(self): 16767db96d56Sopenharmony_ci fd, fn = tempfile.mkstemp(prefix='test_empty_', suffix='.ini') 16777db96d56Sopenharmony_ci os.close(fd) 16787db96d56Sopenharmony_ci self.assertRaises(RuntimeError, logging.config.fileConfig, fn) 16797db96d56Sopenharmony_ci os.remove(fn) 16807db96d56Sopenharmony_ci 16817db96d56Sopenharmony_ci def test_exception_if_config_file_does_not_exist(self): 16827db96d56Sopenharmony_ci self.assertRaises(FileNotFoundError, logging.config.fileConfig, 'filenotfound') 16837db96d56Sopenharmony_ci 16847db96d56Sopenharmony_ci def test_defaults_do_no_interpolation(self): 16857db96d56Sopenharmony_ci """bpo-33802 defaults should not get interpolated""" 16867db96d56Sopenharmony_ci ini = textwrap.dedent(""" 16877db96d56Sopenharmony_ci [formatters] 16887db96d56Sopenharmony_ci keys=default 16897db96d56Sopenharmony_ci 16907db96d56Sopenharmony_ci [formatter_default] 16917db96d56Sopenharmony_ci 16927db96d56Sopenharmony_ci [handlers] 16937db96d56Sopenharmony_ci keys=console 16947db96d56Sopenharmony_ci 16957db96d56Sopenharmony_ci [handler_console] 16967db96d56Sopenharmony_ci class=logging.StreamHandler 16977db96d56Sopenharmony_ci args=tuple() 16987db96d56Sopenharmony_ci 16997db96d56Sopenharmony_ci [loggers] 17007db96d56Sopenharmony_ci keys=root 17017db96d56Sopenharmony_ci 17027db96d56Sopenharmony_ci [logger_root] 17037db96d56Sopenharmony_ci formatter=default 17047db96d56Sopenharmony_ci handlers=console 17057db96d56Sopenharmony_ci """).strip() 17067db96d56Sopenharmony_ci fd, fn = tempfile.mkstemp(prefix='test_logging_', suffix='.ini') 17077db96d56Sopenharmony_ci try: 17087db96d56Sopenharmony_ci os.write(fd, ini.encode('ascii')) 17097db96d56Sopenharmony_ci os.close(fd) 17107db96d56Sopenharmony_ci logging.config.fileConfig( 17117db96d56Sopenharmony_ci fn, 17127db96d56Sopenharmony_ci encoding="utf-8", 17137db96d56Sopenharmony_ci defaults=dict( 17147db96d56Sopenharmony_ci version=1, 17157db96d56Sopenharmony_ci disable_existing_loggers=False, 17167db96d56Sopenharmony_ci formatters={ 17177db96d56Sopenharmony_ci "generic": { 17187db96d56Sopenharmony_ci "format": "%(asctime)s [%(process)d] [%(levelname)s] %(message)s", 17197db96d56Sopenharmony_ci "datefmt": "[%Y-%m-%d %H:%M:%S %z]", 17207db96d56Sopenharmony_ci "class": "logging.Formatter" 17217db96d56Sopenharmony_ci }, 17227db96d56Sopenharmony_ci }, 17237db96d56Sopenharmony_ci ) 17247db96d56Sopenharmony_ci ) 17257db96d56Sopenharmony_ci finally: 17267db96d56Sopenharmony_ci os.unlink(fn) 17277db96d56Sopenharmony_ci 17287db96d56Sopenharmony_ci 17297db96d56Sopenharmony_ci@support.requires_working_socket() 17307db96d56Sopenharmony_ci@threading_helper.requires_working_threading() 17317db96d56Sopenharmony_ciclass SocketHandlerTest(BaseTest): 17327db96d56Sopenharmony_ci 17337db96d56Sopenharmony_ci """Test for SocketHandler objects.""" 17347db96d56Sopenharmony_ci 17357db96d56Sopenharmony_ci server_class = TestTCPServer 17367db96d56Sopenharmony_ci address = ('localhost', 0) 17377db96d56Sopenharmony_ci 17387db96d56Sopenharmony_ci def setUp(self): 17397db96d56Sopenharmony_ci """Set up a TCP server to receive log messages, and a SocketHandler 17407db96d56Sopenharmony_ci pointing to that server's address and port.""" 17417db96d56Sopenharmony_ci BaseTest.setUp(self) 17427db96d56Sopenharmony_ci # Issue #29177: deal with errors that happen during setup 17437db96d56Sopenharmony_ci self.server = self.sock_hdlr = self.server_exception = None 17447db96d56Sopenharmony_ci try: 17457db96d56Sopenharmony_ci self.server = server = self.server_class(self.address, 17467db96d56Sopenharmony_ci self.handle_socket, 0.01) 17477db96d56Sopenharmony_ci server.start() 17487db96d56Sopenharmony_ci # Uncomment next line to test error recovery in setUp() 17497db96d56Sopenharmony_ci # raise OSError('dummy error raised') 17507db96d56Sopenharmony_ci except OSError as e: 17517db96d56Sopenharmony_ci self.server_exception = e 17527db96d56Sopenharmony_ci return 17537db96d56Sopenharmony_ci server.ready.wait() 17547db96d56Sopenharmony_ci hcls = logging.handlers.SocketHandler 17557db96d56Sopenharmony_ci if isinstance(server.server_address, tuple): 17567db96d56Sopenharmony_ci self.sock_hdlr = hcls('localhost', server.port) 17577db96d56Sopenharmony_ci else: 17587db96d56Sopenharmony_ci self.sock_hdlr = hcls(server.server_address, None) 17597db96d56Sopenharmony_ci self.log_output = '' 17607db96d56Sopenharmony_ci self.root_logger.removeHandler(self.root_logger.handlers[0]) 17617db96d56Sopenharmony_ci self.root_logger.addHandler(self.sock_hdlr) 17627db96d56Sopenharmony_ci self.handled = threading.Semaphore(0) 17637db96d56Sopenharmony_ci 17647db96d56Sopenharmony_ci def tearDown(self): 17657db96d56Sopenharmony_ci """Shutdown the TCP server.""" 17667db96d56Sopenharmony_ci try: 17677db96d56Sopenharmony_ci if self.sock_hdlr: 17687db96d56Sopenharmony_ci self.root_logger.removeHandler(self.sock_hdlr) 17697db96d56Sopenharmony_ci self.sock_hdlr.close() 17707db96d56Sopenharmony_ci if self.server: 17717db96d56Sopenharmony_ci self.server.stop() 17727db96d56Sopenharmony_ci finally: 17737db96d56Sopenharmony_ci BaseTest.tearDown(self) 17747db96d56Sopenharmony_ci 17757db96d56Sopenharmony_ci def handle_socket(self, request): 17767db96d56Sopenharmony_ci conn = request.connection 17777db96d56Sopenharmony_ci while True: 17787db96d56Sopenharmony_ci chunk = conn.recv(4) 17797db96d56Sopenharmony_ci if len(chunk) < 4: 17807db96d56Sopenharmony_ci break 17817db96d56Sopenharmony_ci slen = struct.unpack(">L", chunk)[0] 17827db96d56Sopenharmony_ci chunk = conn.recv(slen) 17837db96d56Sopenharmony_ci while len(chunk) < slen: 17847db96d56Sopenharmony_ci chunk = chunk + conn.recv(slen - len(chunk)) 17857db96d56Sopenharmony_ci obj = pickle.loads(chunk) 17867db96d56Sopenharmony_ci record = logging.makeLogRecord(obj) 17877db96d56Sopenharmony_ci self.log_output += record.msg + '\n' 17887db96d56Sopenharmony_ci self.handled.release() 17897db96d56Sopenharmony_ci 17907db96d56Sopenharmony_ci def test_output(self): 17917db96d56Sopenharmony_ci # The log message sent to the SocketHandler is properly received. 17927db96d56Sopenharmony_ci if self.server_exception: 17937db96d56Sopenharmony_ci self.skipTest(self.server_exception) 17947db96d56Sopenharmony_ci logger = logging.getLogger("tcp") 17957db96d56Sopenharmony_ci logger.error("spam") 17967db96d56Sopenharmony_ci self.handled.acquire() 17977db96d56Sopenharmony_ci logger.debug("eggs") 17987db96d56Sopenharmony_ci self.handled.acquire() 17997db96d56Sopenharmony_ci self.assertEqual(self.log_output, "spam\neggs\n") 18007db96d56Sopenharmony_ci 18017db96d56Sopenharmony_ci def test_noserver(self): 18027db96d56Sopenharmony_ci if self.server_exception: 18037db96d56Sopenharmony_ci self.skipTest(self.server_exception) 18047db96d56Sopenharmony_ci # Avoid timing-related failures due to SocketHandler's own hard-wired 18057db96d56Sopenharmony_ci # one-second timeout on socket.create_connection() (issue #16264). 18067db96d56Sopenharmony_ci self.sock_hdlr.retryStart = 2.5 18077db96d56Sopenharmony_ci # Kill the server 18087db96d56Sopenharmony_ci self.server.stop() 18097db96d56Sopenharmony_ci # The logging call should try to connect, which should fail 18107db96d56Sopenharmony_ci try: 18117db96d56Sopenharmony_ci raise RuntimeError('Deliberate mistake') 18127db96d56Sopenharmony_ci except RuntimeError: 18137db96d56Sopenharmony_ci self.root_logger.exception('Never sent') 18147db96d56Sopenharmony_ci self.root_logger.error('Never sent, either') 18157db96d56Sopenharmony_ci now = time.time() 18167db96d56Sopenharmony_ci self.assertGreater(self.sock_hdlr.retryTime, now) 18177db96d56Sopenharmony_ci time.sleep(self.sock_hdlr.retryTime - now + 0.001) 18187db96d56Sopenharmony_ci self.root_logger.error('Nor this') 18197db96d56Sopenharmony_ci 18207db96d56Sopenharmony_cidef _get_temp_domain_socket(): 18217db96d56Sopenharmony_ci fd, fn = tempfile.mkstemp(prefix='test_logging_', suffix='.sock') 18227db96d56Sopenharmony_ci os.close(fd) 18237db96d56Sopenharmony_ci # just need a name - file can't be present, or we'll get an 18247db96d56Sopenharmony_ci # 'address already in use' error. 18257db96d56Sopenharmony_ci os.remove(fn) 18267db96d56Sopenharmony_ci return fn 18277db96d56Sopenharmony_ci 18287db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required") 18297db96d56Sopenharmony_ciclass UnixSocketHandlerTest(SocketHandlerTest): 18307db96d56Sopenharmony_ci 18317db96d56Sopenharmony_ci """Test for SocketHandler with unix sockets.""" 18327db96d56Sopenharmony_ci 18337db96d56Sopenharmony_ci if hasattr(socket, "AF_UNIX"): 18347db96d56Sopenharmony_ci server_class = TestUnixStreamServer 18357db96d56Sopenharmony_ci 18367db96d56Sopenharmony_ci def setUp(self): 18377db96d56Sopenharmony_ci # override the definition in the base class 18387db96d56Sopenharmony_ci self.address = _get_temp_domain_socket() 18397db96d56Sopenharmony_ci SocketHandlerTest.setUp(self) 18407db96d56Sopenharmony_ci 18417db96d56Sopenharmony_ci def tearDown(self): 18427db96d56Sopenharmony_ci SocketHandlerTest.tearDown(self) 18437db96d56Sopenharmony_ci os_helper.unlink(self.address) 18447db96d56Sopenharmony_ci 18457db96d56Sopenharmony_ci@support.requires_working_socket() 18467db96d56Sopenharmony_ci@threading_helper.requires_working_threading() 18477db96d56Sopenharmony_ciclass DatagramHandlerTest(BaseTest): 18487db96d56Sopenharmony_ci 18497db96d56Sopenharmony_ci """Test for DatagramHandler.""" 18507db96d56Sopenharmony_ci 18517db96d56Sopenharmony_ci server_class = TestUDPServer 18527db96d56Sopenharmony_ci address = ('localhost', 0) 18537db96d56Sopenharmony_ci 18547db96d56Sopenharmony_ci def setUp(self): 18557db96d56Sopenharmony_ci """Set up a UDP server to receive log messages, and a DatagramHandler 18567db96d56Sopenharmony_ci pointing to that server's address and port.""" 18577db96d56Sopenharmony_ci BaseTest.setUp(self) 18587db96d56Sopenharmony_ci # Issue #29177: deal with errors that happen during setup 18597db96d56Sopenharmony_ci self.server = self.sock_hdlr = self.server_exception = None 18607db96d56Sopenharmony_ci try: 18617db96d56Sopenharmony_ci self.server = server = self.server_class(self.address, 18627db96d56Sopenharmony_ci self.handle_datagram, 0.01) 18637db96d56Sopenharmony_ci server.start() 18647db96d56Sopenharmony_ci # Uncomment next line to test error recovery in setUp() 18657db96d56Sopenharmony_ci # raise OSError('dummy error raised') 18667db96d56Sopenharmony_ci except OSError as e: 18677db96d56Sopenharmony_ci self.server_exception = e 18687db96d56Sopenharmony_ci return 18697db96d56Sopenharmony_ci server.ready.wait() 18707db96d56Sopenharmony_ci hcls = logging.handlers.DatagramHandler 18717db96d56Sopenharmony_ci if isinstance(server.server_address, tuple): 18727db96d56Sopenharmony_ci self.sock_hdlr = hcls('localhost', server.port) 18737db96d56Sopenharmony_ci else: 18747db96d56Sopenharmony_ci self.sock_hdlr = hcls(server.server_address, None) 18757db96d56Sopenharmony_ci self.log_output = '' 18767db96d56Sopenharmony_ci self.root_logger.removeHandler(self.root_logger.handlers[0]) 18777db96d56Sopenharmony_ci self.root_logger.addHandler(self.sock_hdlr) 18787db96d56Sopenharmony_ci self.handled = threading.Event() 18797db96d56Sopenharmony_ci 18807db96d56Sopenharmony_ci def tearDown(self): 18817db96d56Sopenharmony_ci """Shutdown the UDP server.""" 18827db96d56Sopenharmony_ci try: 18837db96d56Sopenharmony_ci if self.server: 18847db96d56Sopenharmony_ci self.server.stop() 18857db96d56Sopenharmony_ci if self.sock_hdlr: 18867db96d56Sopenharmony_ci self.root_logger.removeHandler(self.sock_hdlr) 18877db96d56Sopenharmony_ci self.sock_hdlr.close() 18887db96d56Sopenharmony_ci finally: 18897db96d56Sopenharmony_ci BaseTest.tearDown(self) 18907db96d56Sopenharmony_ci 18917db96d56Sopenharmony_ci def handle_datagram(self, request): 18927db96d56Sopenharmony_ci slen = struct.pack('>L', 0) # length of prefix 18937db96d56Sopenharmony_ci packet = request.packet[len(slen):] 18947db96d56Sopenharmony_ci obj = pickle.loads(packet) 18957db96d56Sopenharmony_ci record = logging.makeLogRecord(obj) 18967db96d56Sopenharmony_ci self.log_output += record.msg + '\n' 18977db96d56Sopenharmony_ci self.handled.set() 18987db96d56Sopenharmony_ci 18997db96d56Sopenharmony_ci def test_output(self): 19007db96d56Sopenharmony_ci # The log message sent to the DatagramHandler is properly received. 19017db96d56Sopenharmony_ci if self.server_exception: 19027db96d56Sopenharmony_ci self.skipTest(self.server_exception) 19037db96d56Sopenharmony_ci logger = logging.getLogger("udp") 19047db96d56Sopenharmony_ci logger.error("spam") 19057db96d56Sopenharmony_ci self.handled.wait() 19067db96d56Sopenharmony_ci self.handled.clear() 19077db96d56Sopenharmony_ci logger.error("eggs") 19087db96d56Sopenharmony_ci self.handled.wait() 19097db96d56Sopenharmony_ci self.assertEqual(self.log_output, "spam\neggs\n") 19107db96d56Sopenharmony_ci 19117db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required") 19127db96d56Sopenharmony_ciclass UnixDatagramHandlerTest(DatagramHandlerTest): 19137db96d56Sopenharmony_ci 19147db96d56Sopenharmony_ci """Test for DatagramHandler using Unix sockets.""" 19157db96d56Sopenharmony_ci 19167db96d56Sopenharmony_ci if hasattr(socket, "AF_UNIX"): 19177db96d56Sopenharmony_ci server_class = TestUnixDatagramServer 19187db96d56Sopenharmony_ci 19197db96d56Sopenharmony_ci def setUp(self): 19207db96d56Sopenharmony_ci # override the definition in the base class 19217db96d56Sopenharmony_ci self.address = _get_temp_domain_socket() 19227db96d56Sopenharmony_ci DatagramHandlerTest.setUp(self) 19237db96d56Sopenharmony_ci 19247db96d56Sopenharmony_ci def tearDown(self): 19257db96d56Sopenharmony_ci DatagramHandlerTest.tearDown(self) 19267db96d56Sopenharmony_ci os_helper.unlink(self.address) 19277db96d56Sopenharmony_ci 19287db96d56Sopenharmony_ci@support.requires_working_socket() 19297db96d56Sopenharmony_ci@threading_helper.requires_working_threading() 19307db96d56Sopenharmony_ciclass SysLogHandlerTest(BaseTest): 19317db96d56Sopenharmony_ci 19327db96d56Sopenharmony_ci """Test for SysLogHandler using UDP.""" 19337db96d56Sopenharmony_ci 19347db96d56Sopenharmony_ci server_class = TestUDPServer 19357db96d56Sopenharmony_ci address = ('localhost', 0) 19367db96d56Sopenharmony_ci 19377db96d56Sopenharmony_ci def setUp(self): 19387db96d56Sopenharmony_ci """Set up a UDP server to receive log messages, and a SysLogHandler 19397db96d56Sopenharmony_ci pointing to that server's address and port.""" 19407db96d56Sopenharmony_ci BaseTest.setUp(self) 19417db96d56Sopenharmony_ci # Issue #29177: deal with errors that happen during setup 19427db96d56Sopenharmony_ci self.server = self.sl_hdlr = self.server_exception = None 19437db96d56Sopenharmony_ci try: 19447db96d56Sopenharmony_ci self.server = server = self.server_class(self.address, 19457db96d56Sopenharmony_ci self.handle_datagram, 0.01) 19467db96d56Sopenharmony_ci server.start() 19477db96d56Sopenharmony_ci # Uncomment next line to test error recovery in setUp() 19487db96d56Sopenharmony_ci # raise OSError('dummy error raised') 19497db96d56Sopenharmony_ci except OSError as e: 19507db96d56Sopenharmony_ci self.server_exception = e 19517db96d56Sopenharmony_ci return 19527db96d56Sopenharmony_ci server.ready.wait() 19537db96d56Sopenharmony_ci hcls = logging.handlers.SysLogHandler 19547db96d56Sopenharmony_ci if isinstance(server.server_address, tuple): 19557db96d56Sopenharmony_ci self.sl_hdlr = hcls((server.server_address[0], server.port)) 19567db96d56Sopenharmony_ci else: 19577db96d56Sopenharmony_ci self.sl_hdlr = hcls(server.server_address) 19587db96d56Sopenharmony_ci self.log_output = b'' 19597db96d56Sopenharmony_ci self.root_logger.removeHandler(self.root_logger.handlers[0]) 19607db96d56Sopenharmony_ci self.root_logger.addHandler(self.sl_hdlr) 19617db96d56Sopenharmony_ci self.handled = threading.Event() 19627db96d56Sopenharmony_ci 19637db96d56Sopenharmony_ci def tearDown(self): 19647db96d56Sopenharmony_ci """Shutdown the server.""" 19657db96d56Sopenharmony_ci try: 19667db96d56Sopenharmony_ci if self.server: 19677db96d56Sopenharmony_ci self.server.stop() 19687db96d56Sopenharmony_ci if self.sl_hdlr: 19697db96d56Sopenharmony_ci self.root_logger.removeHandler(self.sl_hdlr) 19707db96d56Sopenharmony_ci self.sl_hdlr.close() 19717db96d56Sopenharmony_ci finally: 19727db96d56Sopenharmony_ci BaseTest.tearDown(self) 19737db96d56Sopenharmony_ci 19747db96d56Sopenharmony_ci def handle_datagram(self, request): 19757db96d56Sopenharmony_ci self.log_output = request.packet 19767db96d56Sopenharmony_ci self.handled.set() 19777db96d56Sopenharmony_ci 19787db96d56Sopenharmony_ci def test_output(self): 19797db96d56Sopenharmony_ci if self.server_exception: 19807db96d56Sopenharmony_ci self.skipTest(self.server_exception) 19817db96d56Sopenharmony_ci # The log message sent to the SysLogHandler is properly received. 19827db96d56Sopenharmony_ci logger = logging.getLogger("slh") 19837db96d56Sopenharmony_ci logger.error("sp\xe4m") 19847db96d56Sopenharmony_ci self.handled.wait() 19857db96d56Sopenharmony_ci self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m\x00') 19867db96d56Sopenharmony_ci self.handled.clear() 19877db96d56Sopenharmony_ci self.sl_hdlr.append_nul = False 19887db96d56Sopenharmony_ci logger.error("sp\xe4m") 19897db96d56Sopenharmony_ci self.handled.wait() 19907db96d56Sopenharmony_ci self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m') 19917db96d56Sopenharmony_ci self.handled.clear() 19927db96d56Sopenharmony_ci self.sl_hdlr.ident = "h\xe4m-" 19937db96d56Sopenharmony_ci logger.error("sp\xe4m") 19947db96d56Sopenharmony_ci self.handled.wait() 19957db96d56Sopenharmony_ci self.assertEqual(self.log_output, b'<11>h\xc3\xa4m-sp\xc3\xa4m') 19967db96d56Sopenharmony_ci 19977db96d56Sopenharmony_ci def test_udp_reconnection(self): 19987db96d56Sopenharmony_ci logger = logging.getLogger("slh") 19997db96d56Sopenharmony_ci self.sl_hdlr.close() 20007db96d56Sopenharmony_ci self.handled.clear() 20017db96d56Sopenharmony_ci logger.error("sp\xe4m") 20027db96d56Sopenharmony_ci self.handled.wait(0.1) 20037db96d56Sopenharmony_ci self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m\x00') 20047db96d56Sopenharmony_ci 20057db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required") 20067db96d56Sopenharmony_ciclass UnixSysLogHandlerTest(SysLogHandlerTest): 20077db96d56Sopenharmony_ci 20087db96d56Sopenharmony_ci """Test for SysLogHandler with Unix sockets.""" 20097db96d56Sopenharmony_ci 20107db96d56Sopenharmony_ci if hasattr(socket, "AF_UNIX"): 20117db96d56Sopenharmony_ci server_class = TestUnixDatagramServer 20127db96d56Sopenharmony_ci 20137db96d56Sopenharmony_ci def setUp(self): 20147db96d56Sopenharmony_ci # override the definition in the base class 20157db96d56Sopenharmony_ci self.address = _get_temp_domain_socket() 20167db96d56Sopenharmony_ci SysLogHandlerTest.setUp(self) 20177db96d56Sopenharmony_ci 20187db96d56Sopenharmony_ci def tearDown(self): 20197db96d56Sopenharmony_ci SysLogHandlerTest.tearDown(self) 20207db96d56Sopenharmony_ci os_helper.unlink(self.address) 20217db96d56Sopenharmony_ci 20227db96d56Sopenharmony_ci@unittest.skipUnless(socket_helper.IPV6_ENABLED, 20237db96d56Sopenharmony_ci 'IPv6 support required for this test.') 20247db96d56Sopenharmony_ciclass IPv6SysLogHandlerTest(SysLogHandlerTest): 20257db96d56Sopenharmony_ci 20267db96d56Sopenharmony_ci """Test for SysLogHandler with IPv6 host.""" 20277db96d56Sopenharmony_ci 20287db96d56Sopenharmony_ci server_class = TestUDPServer 20297db96d56Sopenharmony_ci address = ('::1', 0) 20307db96d56Sopenharmony_ci 20317db96d56Sopenharmony_ci def setUp(self): 20327db96d56Sopenharmony_ci self.server_class.address_family = socket.AF_INET6 20337db96d56Sopenharmony_ci super(IPv6SysLogHandlerTest, self).setUp() 20347db96d56Sopenharmony_ci 20357db96d56Sopenharmony_ci def tearDown(self): 20367db96d56Sopenharmony_ci self.server_class.address_family = socket.AF_INET 20377db96d56Sopenharmony_ci super(IPv6SysLogHandlerTest, self).tearDown() 20387db96d56Sopenharmony_ci 20397db96d56Sopenharmony_ci@support.requires_working_socket() 20407db96d56Sopenharmony_ci@threading_helper.requires_working_threading() 20417db96d56Sopenharmony_ciclass HTTPHandlerTest(BaseTest): 20427db96d56Sopenharmony_ci """Test for HTTPHandler.""" 20437db96d56Sopenharmony_ci 20447db96d56Sopenharmony_ci def setUp(self): 20457db96d56Sopenharmony_ci """Set up an HTTP server to receive log messages, and a HTTPHandler 20467db96d56Sopenharmony_ci pointing to that server's address and port.""" 20477db96d56Sopenharmony_ci BaseTest.setUp(self) 20487db96d56Sopenharmony_ci self.handled = threading.Event() 20497db96d56Sopenharmony_ci 20507db96d56Sopenharmony_ci def handle_request(self, request): 20517db96d56Sopenharmony_ci self.command = request.command 20527db96d56Sopenharmony_ci self.log_data = urlparse(request.path) 20537db96d56Sopenharmony_ci if self.command == 'POST': 20547db96d56Sopenharmony_ci try: 20557db96d56Sopenharmony_ci rlen = int(request.headers['Content-Length']) 20567db96d56Sopenharmony_ci self.post_data = request.rfile.read(rlen) 20577db96d56Sopenharmony_ci except: 20587db96d56Sopenharmony_ci self.post_data = None 20597db96d56Sopenharmony_ci request.send_response(200) 20607db96d56Sopenharmony_ci request.end_headers() 20617db96d56Sopenharmony_ci self.handled.set() 20627db96d56Sopenharmony_ci 20637db96d56Sopenharmony_ci def test_output(self): 20647db96d56Sopenharmony_ci # The log message sent to the HTTPHandler is properly received. 20657db96d56Sopenharmony_ci logger = logging.getLogger("http") 20667db96d56Sopenharmony_ci root_logger = self.root_logger 20677db96d56Sopenharmony_ci root_logger.removeHandler(self.root_logger.handlers[0]) 20687db96d56Sopenharmony_ci for secure in (False, True): 20697db96d56Sopenharmony_ci addr = ('localhost', 0) 20707db96d56Sopenharmony_ci if secure: 20717db96d56Sopenharmony_ci try: 20727db96d56Sopenharmony_ci import ssl 20737db96d56Sopenharmony_ci except ImportError: 20747db96d56Sopenharmony_ci sslctx = None 20757db96d56Sopenharmony_ci else: 20767db96d56Sopenharmony_ci here = os.path.dirname(__file__) 20777db96d56Sopenharmony_ci localhost_cert = os.path.join(here, "keycert.pem") 20787db96d56Sopenharmony_ci sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) 20797db96d56Sopenharmony_ci sslctx.load_cert_chain(localhost_cert) 20807db96d56Sopenharmony_ci 20817db96d56Sopenharmony_ci context = ssl.create_default_context(cafile=localhost_cert) 20827db96d56Sopenharmony_ci else: 20837db96d56Sopenharmony_ci sslctx = None 20847db96d56Sopenharmony_ci context = None 20857db96d56Sopenharmony_ci self.server = server = TestHTTPServer(addr, self.handle_request, 20867db96d56Sopenharmony_ci 0.01, sslctx=sslctx) 20877db96d56Sopenharmony_ci server.start() 20887db96d56Sopenharmony_ci server.ready.wait() 20897db96d56Sopenharmony_ci host = 'localhost:%d' % server.server_port 20907db96d56Sopenharmony_ci secure_client = secure and sslctx 20917db96d56Sopenharmony_ci self.h_hdlr = logging.handlers.HTTPHandler(host, '/frob', 20927db96d56Sopenharmony_ci secure=secure_client, 20937db96d56Sopenharmony_ci context=context, 20947db96d56Sopenharmony_ci credentials=('foo', 'bar')) 20957db96d56Sopenharmony_ci self.log_data = None 20967db96d56Sopenharmony_ci root_logger.addHandler(self.h_hdlr) 20977db96d56Sopenharmony_ci 20987db96d56Sopenharmony_ci for method in ('GET', 'POST'): 20997db96d56Sopenharmony_ci self.h_hdlr.method = method 21007db96d56Sopenharmony_ci self.handled.clear() 21017db96d56Sopenharmony_ci msg = "sp\xe4m" 21027db96d56Sopenharmony_ci logger.error(msg) 21037db96d56Sopenharmony_ci self.handled.wait() 21047db96d56Sopenharmony_ci self.assertEqual(self.log_data.path, '/frob') 21057db96d56Sopenharmony_ci self.assertEqual(self.command, method) 21067db96d56Sopenharmony_ci if method == 'GET': 21077db96d56Sopenharmony_ci d = parse_qs(self.log_data.query) 21087db96d56Sopenharmony_ci else: 21097db96d56Sopenharmony_ci d = parse_qs(self.post_data.decode('utf-8')) 21107db96d56Sopenharmony_ci self.assertEqual(d['name'], ['http']) 21117db96d56Sopenharmony_ci self.assertEqual(d['funcName'], ['test_output']) 21127db96d56Sopenharmony_ci self.assertEqual(d['msg'], [msg]) 21137db96d56Sopenharmony_ci 21147db96d56Sopenharmony_ci self.server.stop() 21157db96d56Sopenharmony_ci self.root_logger.removeHandler(self.h_hdlr) 21167db96d56Sopenharmony_ci self.h_hdlr.close() 21177db96d56Sopenharmony_ci 21187db96d56Sopenharmony_ciclass MemoryTest(BaseTest): 21197db96d56Sopenharmony_ci 21207db96d56Sopenharmony_ci """Test memory persistence of logger objects.""" 21217db96d56Sopenharmony_ci 21227db96d56Sopenharmony_ci def setUp(self): 21237db96d56Sopenharmony_ci """Create a dict to remember potentially destroyed objects.""" 21247db96d56Sopenharmony_ci BaseTest.setUp(self) 21257db96d56Sopenharmony_ci self._survivors = {} 21267db96d56Sopenharmony_ci 21277db96d56Sopenharmony_ci def _watch_for_survival(self, *args): 21287db96d56Sopenharmony_ci """Watch the given objects for survival, by creating weakrefs to 21297db96d56Sopenharmony_ci them.""" 21307db96d56Sopenharmony_ci for obj in args: 21317db96d56Sopenharmony_ci key = id(obj), repr(obj) 21327db96d56Sopenharmony_ci self._survivors[key] = weakref.ref(obj) 21337db96d56Sopenharmony_ci 21347db96d56Sopenharmony_ci def _assertTruesurvival(self): 21357db96d56Sopenharmony_ci """Assert that all objects watched for survival have survived.""" 21367db96d56Sopenharmony_ci # Trigger cycle breaking. 21377db96d56Sopenharmony_ci gc.collect() 21387db96d56Sopenharmony_ci dead = [] 21397db96d56Sopenharmony_ci for (id_, repr_), ref in self._survivors.items(): 21407db96d56Sopenharmony_ci if ref() is None: 21417db96d56Sopenharmony_ci dead.append(repr_) 21427db96d56Sopenharmony_ci if dead: 21437db96d56Sopenharmony_ci self.fail("%d objects should have survived " 21447db96d56Sopenharmony_ci "but have been destroyed: %s" % (len(dead), ", ".join(dead))) 21457db96d56Sopenharmony_ci 21467db96d56Sopenharmony_ci def test_persistent_loggers(self): 21477db96d56Sopenharmony_ci # Logger objects are persistent and retain their configuration, even 21487db96d56Sopenharmony_ci # if visible references are destroyed. 21497db96d56Sopenharmony_ci self.root_logger.setLevel(logging.INFO) 21507db96d56Sopenharmony_ci foo = logging.getLogger("foo") 21517db96d56Sopenharmony_ci self._watch_for_survival(foo) 21527db96d56Sopenharmony_ci foo.setLevel(logging.DEBUG) 21537db96d56Sopenharmony_ci self.root_logger.debug(self.next_message()) 21547db96d56Sopenharmony_ci foo.debug(self.next_message()) 21557db96d56Sopenharmony_ci self.assert_log_lines([ 21567db96d56Sopenharmony_ci ('foo', 'DEBUG', '2'), 21577db96d56Sopenharmony_ci ]) 21587db96d56Sopenharmony_ci del foo 21597db96d56Sopenharmony_ci # foo has survived. 21607db96d56Sopenharmony_ci self._assertTruesurvival() 21617db96d56Sopenharmony_ci # foo has retained its settings. 21627db96d56Sopenharmony_ci bar = logging.getLogger("foo") 21637db96d56Sopenharmony_ci bar.debug(self.next_message()) 21647db96d56Sopenharmony_ci self.assert_log_lines([ 21657db96d56Sopenharmony_ci ('foo', 'DEBUG', '2'), 21667db96d56Sopenharmony_ci ('foo', 'DEBUG', '3'), 21677db96d56Sopenharmony_ci ]) 21687db96d56Sopenharmony_ci 21697db96d56Sopenharmony_ci 21707db96d56Sopenharmony_ciclass EncodingTest(BaseTest): 21717db96d56Sopenharmony_ci def test_encoding_plain_file(self): 21727db96d56Sopenharmony_ci # In Python 2.x, a plain file object is treated as having no encoding. 21737db96d56Sopenharmony_ci log = logging.getLogger("test") 21747db96d56Sopenharmony_ci fd, fn = tempfile.mkstemp(".log", "test_logging-1-") 21757db96d56Sopenharmony_ci os.close(fd) 21767db96d56Sopenharmony_ci # the non-ascii data we write to the log. 21777db96d56Sopenharmony_ci data = "foo\x80" 21787db96d56Sopenharmony_ci try: 21797db96d56Sopenharmony_ci handler = logging.FileHandler(fn, encoding="utf-8") 21807db96d56Sopenharmony_ci log.addHandler(handler) 21817db96d56Sopenharmony_ci try: 21827db96d56Sopenharmony_ci # write non-ascii data to the log. 21837db96d56Sopenharmony_ci log.warning(data) 21847db96d56Sopenharmony_ci finally: 21857db96d56Sopenharmony_ci log.removeHandler(handler) 21867db96d56Sopenharmony_ci handler.close() 21877db96d56Sopenharmony_ci # check we wrote exactly those bytes, ignoring trailing \n etc 21887db96d56Sopenharmony_ci f = open(fn, encoding="utf-8") 21897db96d56Sopenharmony_ci try: 21907db96d56Sopenharmony_ci self.assertEqual(f.read().rstrip(), data) 21917db96d56Sopenharmony_ci finally: 21927db96d56Sopenharmony_ci f.close() 21937db96d56Sopenharmony_ci finally: 21947db96d56Sopenharmony_ci if os.path.isfile(fn): 21957db96d56Sopenharmony_ci os.remove(fn) 21967db96d56Sopenharmony_ci 21977db96d56Sopenharmony_ci def test_encoding_cyrillic_unicode(self): 21987db96d56Sopenharmony_ci log = logging.getLogger("test") 21997db96d56Sopenharmony_ci # Get a message in Unicode: Do svidanya in Cyrillic (meaning goodbye) 22007db96d56Sopenharmony_ci message = '\u0434\u043e \u0441\u0432\u0438\u0434\u0430\u043d\u0438\u044f' 22017db96d56Sopenharmony_ci # Ensure it's written in a Cyrillic encoding 22027db96d56Sopenharmony_ci writer_class = codecs.getwriter('cp1251') 22037db96d56Sopenharmony_ci writer_class.encoding = 'cp1251' 22047db96d56Sopenharmony_ci stream = io.BytesIO() 22057db96d56Sopenharmony_ci writer = writer_class(stream, 'strict') 22067db96d56Sopenharmony_ci handler = logging.StreamHandler(writer) 22077db96d56Sopenharmony_ci log.addHandler(handler) 22087db96d56Sopenharmony_ci try: 22097db96d56Sopenharmony_ci log.warning(message) 22107db96d56Sopenharmony_ci finally: 22117db96d56Sopenharmony_ci log.removeHandler(handler) 22127db96d56Sopenharmony_ci handler.close() 22137db96d56Sopenharmony_ci # check we wrote exactly those bytes, ignoring trailing \n etc 22147db96d56Sopenharmony_ci s = stream.getvalue() 22157db96d56Sopenharmony_ci # Compare against what the data should be when encoded in CP-1251 22167db96d56Sopenharmony_ci self.assertEqual(s, b'\xe4\xee \xf1\xe2\xe8\xe4\xe0\xed\xe8\xff\n') 22177db96d56Sopenharmony_ci 22187db96d56Sopenharmony_ci 22197db96d56Sopenharmony_ciclass WarningsTest(BaseTest): 22207db96d56Sopenharmony_ci 22217db96d56Sopenharmony_ci def test_warnings(self): 22227db96d56Sopenharmony_ci with warnings.catch_warnings(): 22237db96d56Sopenharmony_ci logging.captureWarnings(True) 22247db96d56Sopenharmony_ci self.addCleanup(logging.captureWarnings, False) 22257db96d56Sopenharmony_ci warnings.filterwarnings("always", category=UserWarning) 22267db96d56Sopenharmony_ci stream = io.StringIO() 22277db96d56Sopenharmony_ci h = logging.StreamHandler(stream) 22287db96d56Sopenharmony_ci logger = logging.getLogger("py.warnings") 22297db96d56Sopenharmony_ci logger.addHandler(h) 22307db96d56Sopenharmony_ci warnings.warn("I'm warning you...") 22317db96d56Sopenharmony_ci logger.removeHandler(h) 22327db96d56Sopenharmony_ci s = stream.getvalue() 22337db96d56Sopenharmony_ci h.close() 22347db96d56Sopenharmony_ci self.assertGreater(s.find("UserWarning: I'm warning you...\n"), 0) 22357db96d56Sopenharmony_ci 22367db96d56Sopenharmony_ci # See if an explicit file uses the original implementation 22377db96d56Sopenharmony_ci a_file = io.StringIO() 22387db96d56Sopenharmony_ci warnings.showwarning("Explicit", UserWarning, "dummy.py", 42, 22397db96d56Sopenharmony_ci a_file, "Dummy line") 22407db96d56Sopenharmony_ci s = a_file.getvalue() 22417db96d56Sopenharmony_ci a_file.close() 22427db96d56Sopenharmony_ci self.assertEqual(s, 22437db96d56Sopenharmony_ci "dummy.py:42: UserWarning: Explicit\n Dummy line\n") 22447db96d56Sopenharmony_ci 22457db96d56Sopenharmony_ci def test_warnings_no_handlers(self): 22467db96d56Sopenharmony_ci with warnings.catch_warnings(): 22477db96d56Sopenharmony_ci logging.captureWarnings(True) 22487db96d56Sopenharmony_ci self.addCleanup(logging.captureWarnings, False) 22497db96d56Sopenharmony_ci 22507db96d56Sopenharmony_ci # confirm our assumption: no loggers are set 22517db96d56Sopenharmony_ci logger = logging.getLogger("py.warnings") 22527db96d56Sopenharmony_ci self.assertEqual(logger.handlers, []) 22537db96d56Sopenharmony_ci 22547db96d56Sopenharmony_ci warnings.showwarning("Explicit", UserWarning, "dummy.py", 42) 22557db96d56Sopenharmony_ci self.assertEqual(len(logger.handlers), 1) 22567db96d56Sopenharmony_ci self.assertIsInstance(logger.handlers[0], logging.NullHandler) 22577db96d56Sopenharmony_ci 22587db96d56Sopenharmony_ci 22597db96d56Sopenharmony_cidef formatFunc(format, datefmt=None): 22607db96d56Sopenharmony_ci return logging.Formatter(format, datefmt) 22617db96d56Sopenharmony_ci 22627db96d56Sopenharmony_ciclass myCustomFormatter: 22637db96d56Sopenharmony_ci def __init__(self, fmt, datefmt=None): 22647db96d56Sopenharmony_ci pass 22657db96d56Sopenharmony_ci 22667db96d56Sopenharmony_cidef handlerFunc(): 22677db96d56Sopenharmony_ci return logging.StreamHandler() 22687db96d56Sopenharmony_ci 22697db96d56Sopenharmony_ciclass CustomHandler(logging.StreamHandler): 22707db96d56Sopenharmony_ci pass 22717db96d56Sopenharmony_ci 22727db96d56Sopenharmony_ciclass ConfigDictTest(BaseTest): 22737db96d56Sopenharmony_ci 22747db96d56Sopenharmony_ci """Reading logging config from a dictionary.""" 22757db96d56Sopenharmony_ci 22767db96d56Sopenharmony_ci check_no_resource_warning = warnings_helper.check_no_resource_warning 22777db96d56Sopenharmony_ci expected_log_pat = r"^(\w+) \+\+ (\w+)$" 22787db96d56Sopenharmony_ci 22797db96d56Sopenharmony_ci # config0 is a standard configuration. 22807db96d56Sopenharmony_ci config0 = { 22817db96d56Sopenharmony_ci 'version': 1, 22827db96d56Sopenharmony_ci 'formatters': { 22837db96d56Sopenharmony_ci 'form1' : { 22847db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 22857db96d56Sopenharmony_ci }, 22867db96d56Sopenharmony_ci }, 22877db96d56Sopenharmony_ci 'handlers' : { 22887db96d56Sopenharmony_ci 'hand1' : { 22897db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 22907db96d56Sopenharmony_ci 'formatter' : 'form1', 22917db96d56Sopenharmony_ci 'level' : 'NOTSET', 22927db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 22937db96d56Sopenharmony_ci }, 22947db96d56Sopenharmony_ci }, 22957db96d56Sopenharmony_ci 'root' : { 22967db96d56Sopenharmony_ci 'level' : 'WARNING', 22977db96d56Sopenharmony_ci 'handlers' : ['hand1'], 22987db96d56Sopenharmony_ci }, 22997db96d56Sopenharmony_ci } 23007db96d56Sopenharmony_ci 23017db96d56Sopenharmony_ci # config1 adds a little to the standard configuration. 23027db96d56Sopenharmony_ci config1 = { 23037db96d56Sopenharmony_ci 'version': 1, 23047db96d56Sopenharmony_ci 'formatters': { 23057db96d56Sopenharmony_ci 'form1' : { 23067db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 23077db96d56Sopenharmony_ci }, 23087db96d56Sopenharmony_ci }, 23097db96d56Sopenharmony_ci 'handlers' : { 23107db96d56Sopenharmony_ci 'hand1' : { 23117db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 23127db96d56Sopenharmony_ci 'formatter' : 'form1', 23137db96d56Sopenharmony_ci 'level' : 'NOTSET', 23147db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 23157db96d56Sopenharmony_ci }, 23167db96d56Sopenharmony_ci }, 23177db96d56Sopenharmony_ci 'loggers' : { 23187db96d56Sopenharmony_ci 'compiler.parser' : { 23197db96d56Sopenharmony_ci 'level' : 'DEBUG', 23207db96d56Sopenharmony_ci 'handlers' : ['hand1'], 23217db96d56Sopenharmony_ci }, 23227db96d56Sopenharmony_ci }, 23237db96d56Sopenharmony_ci 'root' : { 23247db96d56Sopenharmony_ci 'level' : 'WARNING', 23257db96d56Sopenharmony_ci }, 23267db96d56Sopenharmony_ci } 23277db96d56Sopenharmony_ci 23287db96d56Sopenharmony_ci # config1a moves the handler to the root. Used with config8a 23297db96d56Sopenharmony_ci config1a = { 23307db96d56Sopenharmony_ci 'version': 1, 23317db96d56Sopenharmony_ci 'formatters': { 23327db96d56Sopenharmony_ci 'form1' : { 23337db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 23347db96d56Sopenharmony_ci }, 23357db96d56Sopenharmony_ci }, 23367db96d56Sopenharmony_ci 'handlers' : { 23377db96d56Sopenharmony_ci 'hand1' : { 23387db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 23397db96d56Sopenharmony_ci 'formatter' : 'form1', 23407db96d56Sopenharmony_ci 'level' : 'NOTSET', 23417db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 23427db96d56Sopenharmony_ci }, 23437db96d56Sopenharmony_ci }, 23447db96d56Sopenharmony_ci 'loggers' : { 23457db96d56Sopenharmony_ci 'compiler.parser' : { 23467db96d56Sopenharmony_ci 'level' : 'DEBUG', 23477db96d56Sopenharmony_ci }, 23487db96d56Sopenharmony_ci }, 23497db96d56Sopenharmony_ci 'root' : { 23507db96d56Sopenharmony_ci 'level' : 'WARNING', 23517db96d56Sopenharmony_ci 'handlers' : ['hand1'], 23527db96d56Sopenharmony_ci }, 23537db96d56Sopenharmony_ci } 23547db96d56Sopenharmony_ci 23557db96d56Sopenharmony_ci # config2 has a subtle configuration error that should be reported 23567db96d56Sopenharmony_ci config2 = { 23577db96d56Sopenharmony_ci 'version': 1, 23587db96d56Sopenharmony_ci 'formatters': { 23597db96d56Sopenharmony_ci 'form1' : { 23607db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 23617db96d56Sopenharmony_ci }, 23627db96d56Sopenharmony_ci }, 23637db96d56Sopenharmony_ci 'handlers' : { 23647db96d56Sopenharmony_ci 'hand1' : { 23657db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 23667db96d56Sopenharmony_ci 'formatter' : 'form1', 23677db96d56Sopenharmony_ci 'level' : 'NOTSET', 23687db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdbout', 23697db96d56Sopenharmony_ci }, 23707db96d56Sopenharmony_ci }, 23717db96d56Sopenharmony_ci 'loggers' : { 23727db96d56Sopenharmony_ci 'compiler.parser' : { 23737db96d56Sopenharmony_ci 'level' : 'DEBUG', 23747db96d56Sopenharmony_ci 'handlers' : ['hand1'], 23757db96d56Sopenharmony_ci }, 23767db96d56Sopenharmony_ci }, 23777db96d56Sopenharmony_ci 'root' : { 23787db96d56Sopenharmony_ci 'level' : 'WARNING', 23797db96d56Sopenharmony_ci }, 23807db96d56Sopenharmony_ci } 23817db96d56Sopenharmony_ci 23827db96d56Sopenharmony_ci # As config1 but with a misspelt level on a handler 23837db96d56Sopenharmony_ci config2a = { 23847db96d56Sopenharmony_ci 'version': 1, 23857db96d56Sopenharmony_ci 'formatters': { 23867db96d56Sopenharmony_ci 'form1' : { 23877db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 23887db96d56Sopenharmony_ci }, 23897db96d56Sopenharmony_ci }, 23907db96d56Sopenharmony_ci 'handlers' : { 23917db96d56Sopenharmony_ci 'hand1' : { 23927db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 23937db96d56Sopenharmony_ci 'formatter' : 'form1', 23947db96d56Sopenharmony_ci 'level' : 'NTOSET', 23957db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 23967db96d56Sopenharmony_ci }, 23977db96d56Sopenharmony_ci }, 23987db96d56Sopenharmony_ci 'loggers' : { 23997db96d56Sopenharmony_ci 'compiler.parser' : { 24007db96d56Sopenharmony_ci 'level' : 'DEBUG', 24017db96d56Sopenharmony_ci 'handlers' : ['hand1'], 24027db96d56Sopenharmony_ci }, 24037db96d56Sopenharmony_ci }, 24047db96d56Sopenharmony_ci 'root' : { 24057db96d56Sopenharmony_ci 'level' : 'WARNING', 24067db96d56Sopenharmony_ci }, 24077db96d56Sopenharmony_ci } 24087db96d56Sopenharmony_ci 24097db96d56Sopenharmony_ci 24107db96d56Sopenharmony_ci # As config1 but with a misspelt level on a logger 24117db96d56Sopenharmony_ci config2b = { 24127db96d56Sopenharmony_ci 'version': 1, 24137db96d56Sopenharmony_ci 'formatters': { 24147db96d56Sopenharmony_ci 'form1' : { 24157db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 24167db96d56Sopenharmony_ci }, 24177db96d56Sopenharmony_ci }, 24187db96d56Sopenharmony_ci 'handlers' : { 24197db96d56Sopenharmony_ci 'hand1' : { 24207db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 24217db96d56Sopenharmony_ci 'formatter' : 'form1', 24227db96d56Sopenharmony_ci 'level' : 'NOTSET', 24237db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 24247db96d56Sopenharmony_ci }, 24257db96d56Sopenharmony_ci }, 24267db96d56Sopenharmony_ci 'loggers' : { 24277db96d56Sopenharmony_ci 'compiler.parser' : { 24287db96d56Sopenharmony_ci 'level' : 'DEBUG', 24297db96d56Sopenharmony_ci 'handlers' : ['hand1'], 24307db96d56Sopenharmony_ci }, 24317db96d56Sopenharmony_ci }, 24327db96d56Sopenharmony_ci 'root' : { 24337db96d56Sopenharmony_ci 'level' : 'WRANING', 24347db96d56Sopenharmony_ci }, 24357db96d56Sopenharmony_ci } 24367db96d56Sopenharmony_ci 24377db96d56Sopenharmony_ci # config3 has a less subtle configuration error 24387db96d56Sopenharmony_ci config3 = { 24397db96d56Sopenharmony_ci 'version': 1, 24407db96d56Sopenharmony_ci 'formatters': { 24417db96d56Sopenharmony_ci 'form1' : { 24427db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 24437db96d56Sopenharmony_ci }, 24447db96d56Sopenharmony_ci }, 24457db96d56Sopenharmony_ci 'handlers' : { 24467db96d56Sopenharmony_ci 'hand1' : { 24477db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 24487db96d56Sopenharmony_ci 'formatter' : 'misspelled_name', 24497db96d56Sopenharmony_ci 'level' : 'NOTSET', 24507db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 24517db96d56Sopenharmony_ci }, 24527db96d56Sopenharmony_ci }, 24537db96d56Sopenharmony_ci 'loggers' : { 24547db96d56Sopenharmony_ci 'compiler.parser' : { 24557db96d56Sopenharmony_ci 'level' : 'DEBUG', 24567db96d56Sopenharmony_ci 'handlers' : ['hand1'], 24577db96d56Sopenharmony_ci }, 24587db96d56Sopenharmony_ci }, 24597db96d56Sopenharmony_ci 'root' : { 24607db96d56Sopenharmony_ci 'level' : 'WARNING', 24617db96d56Sopenharmony_ci }, 24627db96d56Sopenharmony_ci } 24637db96d56Sopenharmony_ci 24647db96d56Sopenharmony_ci # config4 specifies a custom formatter class to be loaded 24657db96d56Sopenharmony_ci config4 = { 24667db96d56Sopenharmony_ci 'version': 1, 24677db96d56Sopenharmony_ci 'formatters': { 24687db96d56Sopenharmony_ci 'form1' : { 24697db96d56Sopenharmony_ci '()' : __name__ + '.ExceptionFormatter', 24707db96d56Sopenharmony_ci 'format' : '%(levelname)s:%(name)s:%(message)s', 24717db96d56Sopenharmony_ci }, 24727db96d56Sopenharmony_ci }, 24737db96d56Sopenharmony_ci 'handlers' : { 24747db96d56Sopenharmony_ci 'hand1' : { 24757db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 24767db96d56Sopenharmony_ci 'formatter' : 'form1', 24777db96d56Sopenharmony_ci 'level' : 'NOTSET', 24787db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 24797db96d56Sopenharmony_ci }, 24807db96d56Sopenharmony_ci }, 24817db96d56Sopenharmony_ci 'root' : { 24827db96d56Sopenharmony_ci 'level' : 'NOTSET', 24837db96d56Sopenharmony_ci 'handlers' : ['hand1'], 24847db96d56Sopenharmony_ci }, 24857db96d56Sopenharmony_ci } 24867db96d56Sopenharmony_ci 24877db96d56Sopenharmony_ci # As config4 but using an actual callable rather than a string 24887db96d56Sopenharmony_ci config4a = { 24897db96d56Sopenharmony_ci 'version': 1, 24907db96d56Sopenharmony_ci 'formatters': { 24917db96d56Sopenharmony_ci 'form1' : { 24927db96d56Sopenharmony_ci '()' : ExceptionFormatter, 24937db96d56Sopenharmony_ci 'format' : '%(levelname)s:%(name)s:%(message)s', 24947db96d56Sopenharmony_ci }, 24957db96d56Sopenharmony_ci 'form2' : { 24967db96d56Sopenharmony_ci '()' : __name__ + '.formatFunc', 24977db96d56Sopenharmony_ci 'format' : '%(levelname)s:%(name)s:%(message)s', 24987db96d56Sopenharmony_ci }, 24997db96d56Sopenharmony_ci 'form3' : { 25007db96d56Sopenharmony_ci '()' : formatFunc, 25017db96d56Sopenharmony_ci 'format' : '%(levelname)s:%(name)s:%(message)s', 25027db96d56Sopenharmony_ci }, 25037db96d56Sopenharmony_ci }, 25047db96d56Sopenharmony_ci 'handlers' : { 25057db96d56Sopenharmony_ci 'hand1' : { 25067db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 25077db96d56Sopenharmony_ci 'formatter' : 'form1', 25087db96d56Sopenharmony_ci 'level' : 'NOTSET', 25097db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 25107db96d56Sopenharmony_ci }, 25117db96d56Sopenharmony_ci 'hand2' : { 25127db96d56Sopenharmony_ci '()' : handlerFunc, 25137db96d56Sopenharmony_ci }, 25147db96d56Sopenharmony_ci }, 25157db96d56Sopenharmony_ci 'root' : { 25167db96d56Sopenharmony_ci 'level' : 'NOTSET', 25177db96d56Sopenharmony_ci 'handlers' : ['hand1'], 25187db96d56Sopenharmony_ci }, 25197db96d56Sopenharmony_ci } 25207db96d56Sopenharmony_ci 25217db96d56Sopenharmony_ci # config5 specifies a custom handler class to be loaded 25227db96d56Sopenharmony_ci config5 = { 25237db96d56Sopenharmony_ci 'version': 1, 25247db96d56Sopenharmony_ci 'formatters': { 25257db96d56Sopenharmony_ci 'form1' : { 25267db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 25277db96d56Sopenharmony_ci }, 25287db96d56Sopenharmony_ci }, 25297db96d56Sopenharmony_ci 'handlers' : { 25307db96d56Sopenharmony_ci 'hand1' : { 25317db96d56Sopenharmony_ci 'class' : __name__ + '.CustomHandler', 25327db96d56Sopenharmony_ci 'formatter' : 'form1', 25337db96d56Sopenharmony_ci 'level' : 'NOTSET', 25347db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 25357db96d56Sopenharmony_ci }, 25367db96d56Sopenharmony_ci }, 25377db96d56Sopenharmony_ci 'loggers' : { 25387db96d56Sopenharmony_ci 'compiler.parser' : { 25397db96d56Sopenharmony_ci 'level' : 'DEBUG', 25407db96d56Sopenharmony_ci 'handlers' : ['hand1'], 25417db96d56Sopenharmony_ci }, 25427db96d56Sopenharmony_ci }, 25437db96d56Sopenharmony_ci 'root' : { 25447db96d56Sopenharmony_ci 'level' : 'WARNING', 25457db96d56Sopenharmony_ci }, 25467db96d56Sopenharmony_ci } 25477db96d56Sopenharmony_ci 25487db96d56Sopenharmony_ci # config6 specifies a custom handler class to be loaded 25497db96d56Sopenharmony_ci # but has bad arguments 25507db96d56Sopenharmony_ci config6 = { 25517db96d56Sopenharmony_ci 'version': 1, 25527db96d56Sopenharmony_ci 'formatters': { 25537db96d56Sopenharmony_ci 'form1' : { 25547db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 25557db96d56Sopenharmony_ci }, 25567db96d56Sopenharmony_ci }, 25577db96d56Sopenharmony_ci 'handlers' : { 25587db96d56Sopenharmony_ci 'hand1' : { 25597db96d56Sopenharmony_ci 'class' : __name__ + '.CustomHandler', 25607db96d56Sopenharmony_ci 'formatter' : 'form1', 25617db96d56Sopenharmony_ci 'level' : 'NOTSET', 25627db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 25637db96d56Sopenharmony_ci '9' : 'invalid parameter name', 25647db96d56Sopenharmony_ci }, 25657db96d56Sopenharmony_ci }, 25667db96d56Sopenharmony_ci 'loggers' : { 25677db96d56Sopenharmony_ci 'compiler.parser' : { 25687db96d56Sopenharmony_ci 'level' : 'DEBUG', 25697db96d56Sopenharmony_ci 'handlers' : ['hand1'], 25707db96d56Sopenharmony_ci }, 25717db96d56Sopenharmony_ci }, 25727db96d56Sopenharmony_ci 'root' : { 25737db96d56Sopenharmony_ci 'level' : 'WARNING', 25747db96d56Sopenharmony_ci }, 25757db96d56Sopenharmony_ci } 25767db96d56Sopenharmony_ci 25777db96d56Sopenharmony_ci # config 7 does not define compiler.parser but defines compiler.lexer 25787db96d56Sopenharmony_ci # so compiler.parser should be disabled after applying it 25797db96d56Sopenharmony_ci config7 = { 25807db96d56Sopenharmony_ci 'version': 1, 25817db96d56Sopenharmony_ci 'formatters': { 25827db96d56Sopenharmony_ci 'form1' : { 25837db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 25847db96d56Sopenharmony_ci }, 25857db96d56Sopenharmony_ci }, 25867db96d56Sopenharmony_ci 'handlers' : { 25877db96d56Sopenharmony_ci 'hand1' : { 25887db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 25897db96d56Sopenharmony_ci 'formatter' : 'form1', 25907db96d56Sopenharmony_ci 'level' : 'NOTSET', 25917db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 25927db96d56Sopenharmony_ci }, 25937db96d56Sopenharmony_ci }, 25947db96d56Sopenharmony_ci 'loggers' : { 25957db96d56Sopenharmony_ci 'compiler.lexer' : { 25967db96d56Sopenharmony_ci 'level' : 'DEBUG', 25977db96d56Sopenharmony_ci 'handlers' : ['hand1'], 25987db96d56Sopenharmony_ci }, 25997db96d56Sopenharmony_ci }, 26007db96d56Sopenharmony_ci 'root' : { 26017db96d56Sopenharmony_ci 'level' : 'WARNING', 26027db96d56Sopenharmony_ci }, 26037db96d56Sopenharmony_ci } 26047db96d56Sopenharmony_ci 26057db96d56Sopenharmony_ci # config8 defines both compiler and compiler.lexer 26067db96d56Sopenharmony_ci # so compiler.parser should not be disabled (since 26077db96d56Sopenharmony_ci # compiler is defined) 26087db96d56Sopenharmony_ci config8 = { 26097db96d56Sopenharmony_ci 'version': 1, 26107db96d56Sopenharmony_ci 'disable_existing_loggers' : False, 26117db96d56Sopenharmony_ci 'formatters': { 26127db96d56Sopenharmony_ci 'form1' : { 26137db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 26147db96d56Sopenharmony_ci }, 26157db96d56Sopenharmony_ci }, 26167db96d56Sopenharmony_ci 'handlers' : { 26177db96d56Sopenharmony_ci 'hand1' : { 26187db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 26197db96d56Sopenharmony_ci 'formatter' : 'form1', 26207db96d56Sopenharmony_ci 'level' : 'NOTSET', 26217db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 26227db96d56Sopenharmony_ci }, 26237db96d56Sopenharmony_ci }, 26247db96d56Sopenharmony_ci 'loggers' : { 26257db96d56Sopenharmony_ci 'compiler' : { 26267db96d56Sopenharmony_ci 'level' : 'DEBUG', 26277db96d56Sopenharmony_ci 'handlers' : ['hand1'], 26287db96d56Sopenharmony_ci }, 26297db96d56Sopenharmony_ci 'compiler.lexer' : { 26307db96d56Sopenharmony_ci }, 26317db96d56Sopenharmony_ci }, 26327db96d56Sopenharmony_ci 'root' : { 26337db96d56Sopenharmony_ci 'level' : 'WARNING', 26347db96d56Sopenharmony_ci }, 26357db96d56Sopenharmony_ci } 26367db96d56Sopenharmony_ci 26377db96d56Sopenharmony_ci # config8a disables existing loggers 26387db96d56Sopenharmony_ci config8a = { 26397db96d56Sopenharmony_ci 'version': 1, 26407db96d56Sopenharmony_ci 'disable_existing_loggers' : True, 26417db96d56Sopenharmony_ci 'formatters': { 26427db96d56Sopenharmony_ci 'form1' : { 26437db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 26447db96d56Sopenharmony_ci }, 26457db96d56Sopenharmony_ci }, 26467db96d56Sopenharmony_ci 'handlers' : { 26477db96d56Sopenharmony_ci 'hand1' : { 26487db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 26497db96d56Sopenharmony_ci 'formatter' : 'form1', 26507db96d56Sopenharmony_ci 'level' : 'NOTSET', 26517db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 26527db96d56Sopenharmony_ci }, 26537db96d56Sopenharmony_ci }, 26547db96d56Sopenharmony_ci 'loggers' : { 26557db96d56Sopenharmony_ci 'compiler' : { 26567db96d56Sopenharmony_ci 'level' : 'DEBUG', 26577db96d56Sopenharmony_ci 'handlers' : ['hand1'], 26587db96d56Sopenharmony_ci }, 26597db96d56Sopenharmony_ci 'compiler.lexer' : { 26607db96d56Sopenharmony_ci }, 26617db96d56Sopenharmony_ci }, 26627db96d56Sopenharmony_ci 'root' : { 26637db96d56Sopenharmony_ci 'level' : 'WARNING', 26647db96d56Sopenharmony_ci }, 26657db96d56Sopenharmony_ci } 26667db96d56Sopenharmony_ci 26677db96d56Sopenharmony_ci config9 = { 26687db96d56Sopenharmony_ci 'version': 1, 26697db96d56Sopenharmony_ci 'formatters': { 26707db96d56Sopenharmony_ci 'form1' : { 26717db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 26727db96d56Sopenharmony_ci }, 26737db96d56Sopenharmony_ci }, 26747db96d56Sopenharmony_ci 'handlers' : { 26757db96d56Sopenharmony_ci 'hand1' : { 26767db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 26777db96d56Sopenharmony_ci 'formatter' : 'form1', 26787db96d56Sopenharmony_ci 'level' : 'WARNING', 26797db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 26807db96d56Sopenharmony_ci }, 26817db96d56Sopenharmony_ci }, 26827db96d56Sopenharmony_ci 'loggers' : { 26837db96d56Sopenharmony_ci 'compiler.parser' : { 26847db96d56Sopenharmony_ci 'level' : 'WARNING', 26857db96d56Sopenharmony_ci 'handlers' : ['hand1'], 26867db96d56Sopenharmony_ci }, 26877db96d56Sopenharmony_ci }, 26887db96d56Sopenharmony_ci 'root' : { 26897db96d56Sopenharmony_ci 'level' : 'NOTSET', 26907db96d56Sopenharmony_ci }, 26917db96d56Sopenharmony_ci } 26927db96d56Sopenharmony_ci 26937db96d56Sopenharmony_ci config9a = { 26947db96d56Sopenharmony_ci 'version': 1, 26957db96d56Sopenharmony_ci 'incremental' : True, 26967db96d56Sopenharmony_ci 'handlers' : { 26977db96d56Sopenharmony_ci 'hand1' : { 26987db96d56Sopenharmony_ci 'level' : 'WARNING', 26997db96d56Sopenharmony_ci }, 27007db96d56Sopenharmony_ci }, 27017db96d56Sopenharmony_ci 'loggers' : { 27027db96d56Sopenharmony_ci 'compiler.parser' : { 27037db96d56Sopenharmony_ci 'level' : 'INFO', 27047db96d56Sopenharmony_ci }, 27057db96d56Sopenharmony_ci }, 27067db96d56Sopenharmony_ci } 27077db96d56Sopenharmony_ci 27087db96d56Sopenharmony_ci config9b = { 27097db96d56Sopenharmony_ci 'version': 1, 27107db96d56Sopenharmony_ci 'incremental' : True, 27117db96d56Sopenharmony_ci 'handlers' : { 27127db96d56Sopenharmony_ci 'hand1' : { 27137db96d56Sopenharmony_ci 'level' : 'INFO', 27147db96d56Sopenharmony_ci }, 27157db96d56Sopenharmony_ci }, 27167db96d56Sopenharmony_ci 'loggers' : { 27177db96d56Sopenharmony_ci 'compiler.parser' : { 27187db96d56Sopenharmony_ci 'level' : 'INFO', 27197db96d56Sopenharmony_ci }, 27207db96d56Sopenharmony_ci }, 27217db96d56Sopenharmony_ci } 27227db96d56Sopenharmony_ci 27237db96d56Sopenharmony_ci # As config1 but with a filter added 27247db96d56Sopenharmony_ci config10 = { 27257db96d56Sopenharmony_ci 'version': 1, 27267db96d56Sopenharmony_ci 'formatters': { 27277db96d56Sopenharmony_ci 'form1' : { 27287db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 27297db96d56Sopenharmony_ci }, 27307db96d56Sopenharmony_ci }, 27317db96d56Sopenharmony_ci 'filters' : { 27327db96d56Sopenharmony_ci 'filt1' : { 27337db96d56Sopenharmony_ci 'name' : 'compiler.parser', 27347db96d56Sopenharmony_ci }, 27357db96d56Sopenharmony_ci }, 27367db96d56Sopenharmony_ci 'handlers' : { 27377db96d56Sopenharmony_ci 'hand1' : { 27387db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 27397db96d56Sopenharmony_ci 'formatter' : 'form1', 27407db96d56Sopenharmony_ci 'level' : 'NOTSET', 27417db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 27427db96d56Sopenharmony_ci 'filters' : ['filt1'], 27437db96d56Sopenharmony_ci }, 27447db96d56Sopenharmony_ci }, 27457db96d56Sopenharmony_ci 'loggers' : { 27467db96d56Sopenharmony_ci 'compiler.parser' : { 27477db96d56Sopenharmony_ci 'level' : 'DEBUG', 27487db96d56Sopenharmony_ci 'filters' : ['filt1'], 27497db96d56Sopenharmony_ci }, 27507db96d56Sopenharmony_ci }, 27517db96d56Sopenharmony_ci 'root' : { 27527db96d56Sopenharmony_ci 'level' : 'WARNING', 27537db96d56Sopenharmony_ci 'handlers' : ['hand1'], 27547db96d56Sopenharmony_ci }, 27557db96d56Sopenharmony_ci } 27567db96d56Sopenharmony_ci 27577db96d56Sopenharmony_ci # As config1 but using cfg:// references 27587db96d56Sopenharmony_ci config11 = { 27597db96d56Sopenharmony_ci 'version': 1, 27607db96d56Sopenharmony_ci 'true_formatters': { 27617db96d56Sopenharmony_ci 'form1' : { 27627db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 27637db96d56Sopenharmony_ci }, 27647db96d56Sopenharmony_ci }, 27657db96d56Sopenharmony_ci 'handler_configs': { 27667db96d56Sopenharmony_ci 'hand1' : { 27677db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 27687db96d56Sopenharmony_ci 'formatter' : 'form1', 27697db96d56Sopenharmony_ci 'level' : 'NOTSET', 27707db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 27717db96d56Sopenharmony_ci }, 27727db96d56Sopenharmony_ci }, 27737db96d56Sopenharmony_ci 'formatters' : 'cfg://true_formatters', 27747db96d56Sopenharmony_ci 'handlers' : { 27757db96d56Sopenharmony_ci 'hand1' : 'cfg://handler_configs[hand1]', 27767db96d56Sopenharmony_ci }, 27777db96d56Sopenharmony_ci 'loggers' : { 27787db96d56Sopenharmony_ci 'compiler.parser' : { 27797db96d56Sopenharmony_ci 'level' : 'DEBUG', 27807db96d56Sopenharmony_ci 'handlers' : ['hand1'], 27817db96d56Sopenharmony_ci }, 27827db96d56Sopenharmony_ci }, 27837db96d56Sopenharmony_ci 'root' : { 27847db96d56Sopenharmony_ci 'level' : 'WARNING', 27857db96d56Sopenharmony_ci }, 27867db96d56Sopenharmony_ci } 27877db96d56Sopenharmony_ci 27887db96d56Sopenharmony_ci # As config11 but missing the version key 27897db96d56Sopenharmony_ci config12 = { 27907db96d56Sopenharmony_ci 'true_formatters': { 27917db96d56Sopenharmony_ci 'form1' : { 27927db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 27937db96d56Sopenharmony_ci }, 27947db96d56Sopenharmony_ci }, 27957db96d56Sopenharmony_ci 'handler_configs': { 27967db96d56Sopenharmony_ci 'hand1' : { 27977db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 27987db96d56Sopenharmony_ci 'formatter' : 'form1', 27997db96d56Sopenharmony_ci 'level' : 'NOTSET', 28007db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 28017db96d56Sopenharmony_ci }, 28027db96d56Sopenharmony_ci }, 28037db96d56Sopenharmony_ci 'formatters' : 'cfg://true_formatters', 28047db96d56Sopenharmony_ci 'handlers' : { 28057db96d56Sopenharmony_ci 'hand1' : 'cfg://handler_configs[hand1]', 28067db96d56Sopenharmony_ci }, 28077db96d56Sopenharmony_ci 'loggers' : { 28087db96d56Sopenharmony_ci 'compiler.parser' : { 28097db96d56Sopenharmony_ci 'level' : 'DEBUG', 28107db96d56Sopenharmony_ci 'handlers' : ['hand1'], 28117db96d56Sopenharmony_ci }, 28127db96d56Sopenharmony_ci }, 28137db96d56Sopenharmony_ci 'root' : { 28147db96d56Sopenharmony_ci 'level' : 'WARNING', 28157db96d56Sopenharmony_ci }, 28167db96d56Sopenharmony_ci } 28177db96d56Sopenharmony_ci 28187db96d56Sopenharmony_ci # As config11 but using an unsupported version 28197db96d56Sopenharmony_ci config13 = { 28207db96d56Sopenharmony_ci 'version': 2, 28217db96d56Sopenharmony_ci 'true_formatters': { 28227db96d56Sopenharmony_ci 'form1' : { 28237db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 28247db96d56Sopenharmony_ci }, 28257db96d56Sopenharmony_ci }, 28267db96d56Sopenharmony_ci 'handler_configs': { 28277db96d56Sopenharmony_ci 'hand1' : { 28287db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 28297db96d56Sopenharmony_ci 'formatter' : 'form1', 28307db96d56Sopenharmony_ci 'level' : 'NOTSET', 28317db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 28327db96d56Sopenharmony_ci }, 28337db96d56Sopenharmony_ci }, 28347db96d56Sopenharmony_ci 'formatters' : 'cfg://true_formatters', 28357db96d56Sopenharmony_ci 'handlers' : { 28367db96d56Sopenharmony_ci 'hand1' : 'cfg://handler_configs[hand1]', 28377db96d56Sopenharmony_ci }, 28387db96d56Sopenharmony_ci 'loggers' : { 28397db96d56Sopenharmony_ci 'compiler.parser' : { 28407db96d56Sopenharmony_ci 'level' : 'DEBUG', 28417db96d56Sopenharmony_ci 'handlers' : ['hand1'], 28427db96d56Sopenharmony_ci }, 28437db96d56Sopenharmony_ci }, 28447db96d56Sopenharmony_ci 'root' : { 28457db96d56Sopenharmony_ci 'level' : 'WARNING', 28467db96d56Sopenharmony_ci }, 28477db96d56Sopenharmony_ci } 28487db96d56Sopenharmony_ci 28497db96d56Sopenharmony_ci # As config0, but with properties 28507db96d56Sopenharmony_ci config14 = { 28517db96d56Sopenharmony_ci 'version': 1, 28527db96d56Sopenharmony_ci 'formatters': { 28537db96d56Sopenharmony_ci 'form1' : { 28547db96d56Sopenharmony_ci 'format' : '%(levelname)s ++ %(message)s', 28557db96d56Sopenharmony_ci }, 28567db96d56Sopenharmony_ci }, 28577db96d56Sopenharmony_ci 'handlers' : { 28587db96d56Sopenharmony_ci 'hand1' : { 28597db96d56Sopenharmony_ci 'class' : 'logging.StreamHandler', 28607db96d56Sopenharmony_ci 'formatter' : 'form1', 28617db96d56Sopenharmony_ci 'level' : 'NOTSET', 28627db96d56Sopenharmony_ci 'stream' : 'ext://sys.stdout', 28637db96d56Sopenharmony_ci '.': { 28647db96d56Sopenharmony_ci 'foo': 'bar', 28657db96d56Sopenharmony_ci 'terminator': '!\n', 28667db96d56Sopenharmony_ci } 28677db96d56Sopenharmony_ci }, 28687db96d56Sopenharmony_ci }, 28697db96d56Sopenharmony_ci 'root' : { 28707db96d56Sopenharmony_ci 'level' : 'WARNING', 28717db96d56Sopenharmony_ci 'handlers' : ['hand1'], 28727db96d56Sopenharmony_ci }, 28737db96d56Sopenharmony_ci } 28747db96d56Sopenharmony_ci 28757db96d56Sopenharmony_ci out_of_order = { 28767db96d56Sopenharmony_ci "version": 1, 28777db96d56Sopenharmony_ci "formatters": { 28787db96d56Sopenharmony_ci "mySimpleFormatter": { 28797db96d56Sopenharmony_ci "format": "%(asctime)s (%(name)s) %(levelname)s: %(message)s", 28807db96d56Sopenharmony_ci "style": "$" 28817db96d56Sopenharmony_ci } 28827db96d56Sopenharmony_ci }, 28837db96d56Sopenharmony_ci "handlers": { 28847db96d56Sopenharmony_ci "fileGlobal": { 28857db96d56Sopenharmony_ci "class": "logging.StreamHandler", 28867db96d56Sopenharmony_ci "level": "DEBUG", 28877db96d56Sopenharmony_ci "formatter": "mySimpleFormatter" 28887db96d56Sopenharmony_ci }, 28897db96d56Sopenharmony_ci "bufferGlobal": { 28907db96d56Sopenharmony_ci "class": "logging.handlers.MemoryHandler", 28917db96d56Sopenharmony_ci "capacity": 5, 28927db96d56Sopenharmony_ci "formatter": "mySimpleFormatter", 28937db96d56Sopenharmony_ci "target": "fileGlobal", 28947db96d56Sopenharmony_ci "level": "DEBUG" 28957db96d56Sopenharmony_ci } 28967db96d56Sopenharmony_ci }, 28977db96d56Sopenharmony_ci "loggers": { 28987db96d56Sopenharmony_ci "mymodule": { 28997db96d56Sopenharmony_ci "level": "DEBUG", 29007db96d56Sopenharmony_ci "handlers": ["bufferGlobal"], 29017db96d56Sopenharmony_ci "propagate": "true" 29027db96d56Sopenharmony_ci } 29037db96d56Sopenharmony_ci } 29047db96d56Sopenharmony_ci } 29057db96d56Sopenharmony_ci 29067db96d56Sopenharmony_ci # Configuration with custom logging.Formatter subclass as '()' key and 'validate' set to False 29077db96d56Sopenharmony_ci custom_formatter_class_validate = { 29087db96d56Sopenharmony_ci 'version': 1, 29097db96d56Sopenharmony_ci 'formatters': { 29107db96d56Sopenharmony_ci 'form1': { 29117db96d56Sopenharmony_ci '()': __name__ + '.ExceptionFormatter', 29127db96d56Sopenharmony_ci 'format': '%(levelname)s:%(name)s:%(message)s', 29137db96d56Sopenharmony_ci 'validate': False, 29147db96d56Sopenharmony_ci }, 29157db96d56Sopenharmony_ci }, 29167db96d56Sopenharmony_ci 'handlers' : { 29177db96d56Sopenharmony_ci 'hand1' : { 29187db96d56Sopenharmony_ci 'class': 'logging.StreamHandler', 29197db96d56Sopenharmony_ci 'formatter': 'form1', 29207db96d56Sopenharmony_ci 'level': 'NOTSET', 29217db96d56Sopenharmony_ci 'stream': 'ext://sys.stdout', 29227db96d56Sopenharmony_ci }, 29237db96d56Sopenharmony_ci }, 29247db96d56Sopenharmony_ci "loggers": { 29257db96d56Sopenharmony_ci "my_test_logger_custom_formatter": { 29267db96d56Sopenharmony_ci "level": "DEBUG", 29277db96d56Sopenharmony_ci "handlers": ["hand1"], 29287db96d56Sopenharmony_ci "propagate": "true" 29297db96d56Sopenharmony_ci } 29307db96d56Sopenharmony_ci } 29317db96d56Sopenharmony_ci } 29327db96d56Sopenharmony_ci 29337db96d56Sopenharmony_ci # Configuration with custom logging.Formatter subclass as 'class' key and 'validate' set to False 29347db96d56Sopenharmony_ci custom_formatter_class_validate2 = { 29357db96d56Sopenharmony_ci 'version': 1, 29367db96d56Sopenharmony_ci 'formatters': { 29377db96d56Sopenharmony_ci 'form1': { 29387db96d56Sopenharmony_ci 'class': __name__ + '.ExceptionFormatter', 29397db96d56Sopenharmony_ci 'format': '%(levelname)s:%(name)s:%(message)s', 29407db96d56Sopenharmony_ci 'validate': False, 29417db96d56Sopenharmony_ci }, 29427db96d56Sopenharmony_ci }, 29437db96d56Sopenharmony_ci 'handlers' : { 29447db96d56Sopenharmony_ci 'hand1' : { 29457db96d56Sopenharmony_ci 'class': 'logging.StreamHandler', 29467db96d56Sopenharmony_ci 'formatter': 'form1', 29477db96d56Sopenharmony_ci 'level': 'NOTSET', 29487db96d56Sopenharmony_ci 'stream': 'ext://sys.stdout', 29497db96d56Sopenharmony_ci }, 29507db96d56Sopenharmony_ci }, 29517db96d56Sopenharmony_ci "loggers": { 29527db96d56Sopenharmony_ci "my_test_logger_custom_formatter": { 29537db96d56Sopenharmony_ci "level": "DEBUG", 29547db96d56Sopenharmony_ci "handlers": ["hand1"], 29557db96d56Sopenharmony_ci "propagate": "true" 29567db96d56Sopenharmony_ci } 29577db96d56Sopenharmony_ci } 29587db96d56Sopenharmony_ci } 29597db96d56Sopenharmony_ci 29607db96d56Sopenharmony_ci # Configuration with custom class that is not inherited from logging.Formatter 29617db96d56Sopenharmony_ci custom_formatter_class_validate3 = { 29627db96d56Sopenharmony_ci 'version': 1, 29637db96d56Sopenharmony_ci 'formatters': { 29647db96d56Sopenharmony_ci 'form1': { 29657db96d56Sopenharmony_ci 'class': __name__ + '.myCustomFormatter', 29667db96d56Sopenharmony_ci 'format': '%(levelname)s:%(name)s:%(message)s', 29677db96d56Sopenharmony_ci 'validate': False, 29687db96d56Sopenharmony_ci }, 29697db96d56Sopenharmony_ci }, 29707db96d56Sopenharmony_ci 'handlers' : { 29717db96d56Sopenharmony_ci 'hand1' : { 29727db96d56Sopenharmony_ci 'class': 'logging.StreamHandler', 29737db96d56Sopenharmony_ci 'formatter': 'form1', 29747db96d56Sopenharmony_ci 'level': 'NOTSET', 29757db96d56Sopenharmony_ci 'stream': 'ext://sys.stdout', 29767db96d56Sopenharmony_ci }, 29777db96d56Sopenharmony_ci }, 29787db96d56Sopenharmony_ci "loggers": { 29797db96d56Sopenharmony_ci "my_test_logger_custom_formatter": { 29807db96d56Sopenharmony_ci "level": "DEBUG", 29817db96d56Sopenharmony_ci "handlers": ["hand1"], 29827db96d56Sopenharmony_ci "propagate": "true" 29837db96d56Sopenharmony_ci } 29847db96d56Sopenharmony_ci } 29857db96d56Sopenharmony_ci } 29867db96d56Sopenharmony_ci 29877db96d56Sopenharmony_ci # Configuration with custom function and 'validate' set to False 29887db96d56Sopenharmony_ci custom_formatter_with_function = { 29897db96d56Sopenharmony_ci 'version': 1, 29907db96d56Sopenharmony_ci 'formatters': { 29917db96d56Sopenharmony_ci 'form1': { 29927db96d56Sopenharmony_ci '()': formatFunc, 29937db96d56Sopenharmony_ci 'format': '%(levelname)s:%(name)s:%(message)s', 29947db96d56Sopenharmony_ci 'validate': False, 29957db96d56Sopenharmony_ci }, 29967db96d56Sopenharmony_ci }, 29977db96d56Sopenharmony_ci 'handlers' : { 29987db96d56Sopenharmony_ci 'hand1' : { 29997db96d56Sopenharmony_ci 'class': 'logging.StreamHandler', 30007db96d56Sopenharmony_ci 'formatter': 'form1', 30017db96d56Sopenharmony_ci 'level': 'NOTSET', 30027db96d56Sopenharmony_ci 'stream': 'ext://sys.stdout', 30037db96d56Sopenharmony_ci }, 30047db96d56Sopenharmony_ci }, 30057db96d56Sopenharmony_ci "loggers": { 30067db96d56Sopenharmony_ci "my_test_logger_custom_formatter": { 30077db96d56Sopenharmony_ci "level": "DEBUG", 30087db96d56Sopenharmony_ci "handlers": ["hand1"], 30097db96d56Sopenharmony_ci "propagate": "true" 30107db96d56Sopenharmony_ci } 30117db96d56Sopenharmony_ci } 30127db96d56Sopenharmony_ci } 30137db96d56Sopenharmony_ci 30147db96d56Sopenharmony_ci def apply_config(self, conf): 30157db96d56Sopenharmony_ci logging.config.dictConfig(conf) 30167db96d56Sopenharmony_ci 30177db96d56Sopenharmony_ci def test_config0_ok(self): 30187db96d56Sopenharmony_ci # A simple config which overrides the default settings. 30197db96d56Sopenharmony_ci with support.captured_stdout() as output: 30207db96d56Sopenharmony_ci self.apply_config(self.config0) 30217db96d56Sopenharmony_ci logger = logging.getLogger() 30227db96d56Sopenharmony_ci # Won't output anything 30237db96d56Sopenharmony_ci logger.info(self.next_message()) 30247db96d56Sopenharmony_ci # Outputs a message 30257db96d56Sopenharmony_ci logger.error(self.next_message()) 30267db96d56Sopenharmony_ci self.assert_log_lines([ 30277db96d56Sopenharmony_ci ('ERROR', '2'), 30287db96d56Sopenharmony_ci ], stream=output) 30297db96d56Sopenharmony_ci # Original logger output is empty. 30307db96d56Sopenharmony_ci self.assert_log_lines([]) 30317db96d56Sopenharmony_ci 30327db96d56Sopenharmony_ci def test_config1_ok(self, config=config1): 30337db96d56Sopenharmony_ci # A config defining a sub-parser as well. 30347db96d56Sopenharmony_ci with support.captured_stdout() as output: 30357db96d56Sopenharmony_ci self.apply_config(config) 30367db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 30377db96d56Sopenharmony_ci # Both will output a message 30387db96d56Sopenharmony_ci logger.info(self.next_message()) 30397db96d56Sopenharmony_ci logger.error(self.next_message()) 30407db96d56Sopenharmony_ci self.assert_log_lines([ 30417db96d56Sopenharmony_ci ('INFO', '1'), 30427db96d56Sopenharmony_ci ('ERROR', '2'), 30437db96d56Sopenharmony_ci ], stream=output) 30447db96d56Sopenharmony_ci # Original logger output is empty. 30457db96d56Sopenharmony_ci self.assert_log_lines([]) 30467db96d56Sopenharmony_ci 30477db96d56Sopenharmony_ci def test_config2_failure(self): 30487db96d56Sopenharmony_ci # A simple config which overrides the default settings. 30497db96d56Sopenharmony_ci self.assertRaises(Exception, self.apply_config, self.config2) 30507db96d56Sopenharmony_ci 30517db96d56Sopenharmony_ci def test_config2a_failure(self): 30527db96d56Sopenharmony_ci # A simple config which overrides the default settings. 30537db96d56Sopenharmony_ci self.assertRaises(Exception, self.apply_config, self.config2a) 30547db96d56Sopenharmony_ci 30557db96d56Sopenharmony_ci def test_config2b_failure(self): 30567db96d56Sopenharmony_ci # A simple config which overrides the default settings. 30577db96d56Sopenharmony_ci self.assertRaises(Exception, self.apply_config, self.config2b) 30587db96d56Sopenharmony_ci 30597db96d56Sopenharmony_ci def test_config3_failure(self): 30607db96d56Sopenharmony_ci # A simple config which overrides the default settings. 30617db96d56Sopenharmony_ci self.assertRaises(Exception, self.apply_config, self.config3) 30627db96d56Sopenharmony_ci 30637db96d56Sopenharmony_ci def test_config4_ok(self): 30647db96d56Sopenharmony_ci # A config specifying a custom formatter class. 30657db96d56Sopenharmony_ci with support.captured_stdout() as output: 30667db96d56Sopenharmony_ci self.apply_config(self.config4) 30677db96d56Sopenharmony_ci #logger = logging.getLogger() 30687db96d56Sopenharmony_ci try: 30697db96d56Sopenharmony_ci raise RuntimeError() 30707db96d56Sopenharmony_ci except RuntimeError: 30717db96d56Sopenharmony_ci logging.exception("just testing") 30727db96d56Sopenharmony_ci sys.stdout.seek(0) 30737db96d56Sopenharmony_ci self.assertEqual(output.getvalue(), 30747db96d56Sopenharmony_ci "ERROR:root:just testing\nGot a [RuntimeError]\n") 30757db96d56Sopenharmony_ci # Original logger output is empty 30767db96d56Sopenharmony_ci self.assert_log_lines([]) 30777db96d56Sopenharmony_ci 30787db96d56Sopenharmony_ci def test_config4a_ok(self): 30797db96d56Sopenharmony_ci # A config specifying a custom formatter class. 30807db96d56Sopenharmony_ci with support.captured_stdout() as output: 30817db96d56Sopenharmony_ci self.apply_config(self.config4a) 30827db96d56Sopenharmony_ci #logger = logging.getLogger() 30837db96d56Sopenharmony_ci try: 30847db96d56Sopenharmony_ci raise RuntimeError() 30857db96d56Sopenharmony_ci except RuntimeError: 30867db96d56Sopenharmony_ci logging.exception("just testing") 30877db96d56Sopenharmony_ci sys.stdout.seek(0) 30887db96d56Sopenharmony_ci self.assertEqual(output.getvalue(), 30897db96d56Sopenharmony_ci "ERROR:root:just testing\nGot a [RuntimeError]\n") 30907db96d56Sopenharmony_ci # Original logger output is empty 30917db96d56Sopenharmony_ci self.assert_log_lines([]) 30927db96d56Sopenharmony_ci 30937db96d56Sopenharmony_ci def test_config5_ok(self): 30947db96d56Sopenharmony_ci self.test_config1_ok(config=self.config5) 30957db96d56Sopenharmony_ci 30967db96d56Sopenharmony_ci def test_config6_failure(self): 30977db96d56Sopenharmony_ci self.assertRaises(Exception, self.apply_config, self.config6) 30987db96d56Sopenharmony_ci 30997db96d56Sopenharmony_ci def test_config7_ok(self): 31007db96d56Sopenharmony_ci with support.captured_stdout() as output: 31017db96d56Sopenharmony_ci self.apply_config(self.config1) 31027db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 31037db96d56Sopenharmony_ci # Both will output a message 31047db96d56Sopenharmony_ci logger.info(self.next_message()) 31057db96d56Sopenharmony_ci logger.error(self.next_message()) 31067db96d56Sopenharmony_ci self.assert_log_lines([ 31077db96d56Sopenharmony_ci ('INFO', '1'), 31087db96d56Sopenharmony_ci ('ERROR', '2'), 31097db96d56Sopenharmony_ci ], stream=output) 31107db96d56Sopenharmony_ci # Original logger output is empty. 31117db96d56Sopenharmony_ci self.assert_log_lines([]) 31127db96d56Sopenharmony_ci with support.captured_stdout() as output: 31137db96d56Sopenharmony_ci self.apply_config(self.config7) 31147db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 31157db96d56Sopenharmony_ci self.assertTrue(logger.disabled) 31167db96d56Sopenharmony_ci logger = logging.getLogger("compiler.lexer") 31177db96d56Sopenharmony_ci # Both will output a message 31187db96d56Sopenharmony_ci logger.info(self.next_message()) 31197db96d56Sopenharmony_ci logger.error(self.next_message()) 31207db96d56Sopenharmony_ci self.assert_log_lines([ 31217db96d56Sopenharmony_ci ('INFO', '3'), 31227db96d56Sopenharmony_ci ('ERROR', '4'), 31237db96d56Sopenharmony_ci ], stream=output) 31247db96d56Sopenharmony_ci # Original logger output is empty. 31257db96d56Sopenharmony_ci self.assert_log_lines([]) 31267db96d56Sopenharmony_ci 31277db96d56Sopenharmony_ci # Same as test_config_7_ok but don't disable old loggers. 31287db96d56Sopenharmony_ci def test_config_8_ok(self): 31297db96d56Sopenharmony_ci with support.captured_stdout() as output: 31307db96d56Sopenharmony_ci self.apply_config(self.config1) 31317db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 31327db96d56Sopenharmony_ci # All will output a message 31337db96d56Sopenharmony_ci logger.info(self.next_message()) 31347db96d56Sopenharmony_ci logger.error(self.next_message()) 31357db96d56Sopenharmony_ci self.assert_log_lines([ 31367db96d56Sopenharmony_ci ('INFO', '1'), 31377db96d56Sopenharmony_ci ('ERROR', '2'), 31387db96d56Sopenharmony_ci ], stream=output) 31397db96d56Sopenharmony_ci # Original logger output is empty. 31407db96d56Sopenharmony_ci self.assert_log_lines([]) 31417db96d56Sopenharmony_ci with support.captured_stdout() as output: 31427db96d56Sopenharmony_ci self.apply_config(self.config8) 31437db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 31447db96d56Sopenharmony_ci self.assertFalse(logger.disabled) 31457db96d56Sopenharmony_ci # Both will output a message 31467db96d56Sopenharmony_ci logger.info(self.next_message()) 31477db96d56Sopenharmony_ci logger.error(self.next_message()) 31487db96d56Sopenharmony_ci logger = logging.getLogger("compiler.lexer") 31497db96d56Sopenharmony_ci # Both will output a message 31507db96d56Sopenharmony_ci logger.info(self.next_message()) 31517db96d56Sopenharmony_ci logger.error(self.next_message()) 31527db96d56Sopenharmony_ci self.assert_log_lines([ 31537db96d56Sopenharmony_ci ('INFO', '3'), 31547db96d56Sopenharmony_ci ('ERROR', '4'), 31557db96d56Sopenharmony_ci ('INFO', '5'), 31567db96d56Sopenharmony_ci ('ERROR', '6'), 31577db96d56Sopenharmony_ci ], stream=output) 31587db96d56Sopenharmony_ci # Original logger output is empty. 31597db96d56Sopenharmony_ci self.assert_log_lines([]) 31607db96d56Sopenharmony_ci 31617db96d56Sopenharmony_ci def test_config_8a_ok(self): 31627db96d56Sopenharmony_ci with support.captured_stdout() as output: 31637db96d56Sopenharmony_ci self.apply_config(self.config1a) 31647db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 31657db96d56Sopenharmony_ci # See issue #11424. compiler-hyphenated sorts 31667db96d56Sopenharmony_ci # between compiler and compiler.xyz and this 31677db96d56Sopenharmony_ci # was preventing compiler.xyz from being included 31687db96d56Sopenharmony_ci # in the child loggers of compiler because of an 31697db96d56Sopenharmony_ci # overzealous loop termination condition. 31707db96d56Sopenharmony_ci hyphenated = logging.getLogger('compiler-hyphenated') 31717db96d56Sopenharmony_ci # All will output a message 31727db96d56Sopenharmony_ci logger.info(self.next_message()) 31737db96d56Sopenharmony_ci logger.error(self.next_message()) 31747db96d56Sopenharmony_ci hyphenated.critical(self.next_message()) 31757db96d56Sopenharmony_ci self.assert_log_lines([ 31767db96d56Sopenharmony_ci ('INFO', '1'), 31777db96d56Sopenharmony_ci ('ERROR', '2'), 31787db96d56Sopenharmony_ci ('CRITICAL', '3'), 31797db96d56Sopenharmony_ci ], stream=output) 31807db96d56Sopenharmony_ci # Original logger output is empty. 31817db96d56Sopenharmony_ci self.assert_log_lines([]) 31827db96d56Sopenharmony_ci with support.captured_stdout() as output: 31837db96d56Sopenharmony_ci self.apply_config(self.config8a) 31847db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 31857db96d56Sopenharmony_ci self.assertFalse(logger.disabled) 31867db96d56Sopenharmony_ci # Both will output a message 31877db96d56Sopenharmony_ci logger.info(self.next_message()) 31887db96d56Sopenharmony_ci logger.error(self.next_message()) 31897db96d56Sopenharmony_ci logger = logging.getLogger("compiler.lexer") 31907db96d56Sopenharmony_ci # Both will output a message 31917db96d56Sopenharmony_ci logger.info(self.next_message()) 31927db96d56Sopenharmony_ci logger.error(self.next_message()) 31937db96d56Sopenharmony_ci # Will not appear 31947db96d56Sopenharmony_ci hyphenated.critical(self.next_message()) 31957db96d56Sopenharmony_ci self.assert_log_lines([ 31967db96d56Sopenharmony_ci ('INFO', '4'), 31977db96d56Sopenharmony_ci ('ERROR', '5'), 31987db96d56Sopenharmony_ci ('INFO', '6'), 31997db96d56Sopenharmony_ci ('ERROR', '7'), 32007db96d56Sopenharmony_ci ], stream=output) 32017db96d56Sopenharmony_ci # Original logger output is empty. 32027db96d56Sopenharmony_ci self.assert_log_lines([]) 32037db96d56Sopenharmony_ci 32047db96d56Sopenharmony_ci def test_config_9_ok(self): 32057db96d56Sopenharmony_ci with support.captured_stdout() as output: 32067db96d56Sopenharmony_ci self.apply_config(self.config9) 32077db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 32087db96d56Sopenharmony_ci # Nothing will be output since both handler and logger are set to WARNING 32097db96d56Sopenharmony_ci logger.info(self.next_message()) 32107db96d56Sopenharmony_ci self.assert_log_lines([], stream=output) 32117db96d56Sopenharmony_ci self.apply_config(self.config9a) 32127db96d56Sopenharmony_ci # Nothing will be output since handler is still set to WARNING 32137db96d56Sopenharmony_ci logger.info(self.next_message()) 32147db96d56Sopenharmony_ci self.assert_log_lines([], stream=output) 32157db96d56Sopenharmony_ci self.apply_config(self.config9b) 32167db96d56Sopenharmony_ci # Message should now be output 32177db96d56Sopenharmony_ci logger.info(self.next_message()) 32187db96d56Sopenharmony_ci self.assert_log_lines([ 32197db96d56Sopenharmony_ci ('INFO', '3'), 32207db96d56Sopenharmony_ci ], stream=output) 32217db96d56Sopenharmony_ci 32227db96d56Sopenharmony_ci def test_config_10_ok(self): 32237db96d56Sopenharmony_ci with support.captured_stdout() as output: 32247db96d56Sopenharmony_ci self.apply_config(self.config10) 32257db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 32267db96d56Sopenharmony_ci logger.warning(self.next_message()) 32277db96d56Sopenharmony_ci logger = logging.getLogger('compiler') 32287db96d56Sopenharmony_ci # Not output, because filtered 32297db96d56Sopenharmony_ci logger.warning(self.next_message()) 32307db96d56Sopenharmony_ci logger = logging.getLogger('compiler.lexer') 32317db96d56Sopenharmony_ci # Not output, because filtered 32327db96d56Sopenharmony_ci logger.warning(self.next_message()) 32337db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser.codegen") 32347db96d56Sopenharmony_ci # Output, as not filtered 32357db96d56Sopenharmony_ci logger.error(self.next_message()) 32367db96d56Sopenharmony_ci self.assert_log_lines([ 32377db96d56Sopenharmony_ci ('WARNING', '1'), 32387db96d56Sopenharmony_ci ('ERROR', '4'), 32397db96d56Sopenharmony_ci ], stream=output) 32407db96d56Sopenharmony_ci 32417db96d56Sopenharmony_ci def test_config11_ok(self): 32427db96d56Sopenharmony_ci self.test_config1_ok(self.config11) 32437db96d56Sopenharmony_ci 32447db96d56Sopenharmony_ci def test_config12_failure(self): 32457db96d56Sopenharmony_ci self.assertRaises(Exception, self.apply_config, self.config12) 32467db96d56Sopenharmony_ci 32477db96d56Sopenharmony_ci def test_config13_failure(self): 32487db96d56Sopenharmony_ci self.assertRaises(Exception, self.apply_config, self.config13) 32497db96d56Sopenharmony_ci 32507db96d56Sopenharmony_ci def test_config14_ok(self): 32517db96d56Sopenharmony_ci with support.captured_stdout() as output: 32527db96d56Sopenharmony_ci self.apply_config(self.config14) 32537db96d56Sopenharmony_ci h = logging._handlers['hand1'] 32547db96d56Sopenharmony_ci self.assertEqual(h.foo, 'bar') 32557db96d56Sopenharmony_ci self.assertEqual(h.terminator, '!\n') 32567db96d56Sopenharmony_ci logging.warning('Exclamation') 32577db96d56Sopenharmony_ci self.assertTrue(output.getvalue().endswith('Exclamation!\n')) 32587db96d56Sopenharmony_ci 32597db96d56Sopenharmony_ci def test_config15_ok(self): 32607db96d56Sopenharmony_ci 32617db96d56Sopenharmony_ci def cleanup(h1, fn): 32627db96d56Sopenharmony_ci h1.close() 32637db96d56Sopenharmony_ci os.remove(fn) 32647db96d56Sopenharmony_ci 32657db96d56Sopenharmony_ci with self.check_no_resource_warning(): 32667db96d56Sopenharmony_ci fd, fn = tempfile.mkstemp(".log", "test_logging-X-") 32677db96d56Sopenharmony_ci os.close(fd) 32687db96d56Sopenharmony_ci 32697db96d56Sopenharmony_ci config = { 32707db96d56Sopenharmony_ci "version": 1, 32717db96d56Sopenharmony_ci "handlers": { 32727db96d56Sopenharmony_ci "file": { 32737db96d56Sopenharmony_ci "class": "logging.FileHandler", 32747db96d56Sopenharmony_ci "filename": fn, 32757db96d56Sopenharmony_ci "encoding": "utf-8", 32767db96d56Sopenharmony_ci } 32777db96d56Sopenharmony_ci }, 32787db96d56Sopenharmony_ci "root": { 32797db96d56Sopenharmony_ci "handlers": ["file"] 32807db96d56Sopenharmony_ci } 32817db96d56Sopenharmony_ci } 32827db96d56Sopenharmony_ci 32837db96d56Sopenharmony_ci self.apply_config(config) 32847db96d56Sopenharmony_ci self.apply_config(config) 32857db96d56Sopenharmony_ci 32867db96d56Sopenharmony_ci handler = logging.root.handlers[0] 32877db96d56Sopenharmony_ci self.addCleanup(cleanup, handler, fn) 32887db96d56Sopenharmony_ci 32897db96d56Sopenharmony_ci def setup_via_listener(self, text, verify=None): 32907db96d56Sopenharmony_ci text = text.encode("utf-8") 32917db96d56Sopenharmony_ci # Ask for a randomly assigned port (by using port 0) 32927db96d56Sopenharmony_ci t = logging.config.listen(0, verify) 32937db96d56Sopenharmony_ci t.start() 32947db96d56Sopenharmony_ci t.ready.wait() 32957db96d56Sopenharmony_ci # Now get the port allocated 32967db96d56Sopenharmony_ci port = t.port 32977db96d56Sopenharmony_ci t.ready.clear() 32987db96d56Sopenharmony_ci try: 32997db96d56Sopenharmony_ci sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 33007db96d56Sopenharmony_ci sock.settimeout(2.0) 33017db96d56Sopenharmony_ci sock.connect(('localhost', port)) 33027db96d56Sopenharmony_ci 33037db96d56Sopenharmony_ci slen = struct.pack('>L', len(text)) 33047db96d56Sopenharmony_ci s = slen + text 33057db96d56Sopenharmony_ci sentsofar = 0 33067db96d56Sopenharmony_ci left = len(s) 33077db96d56Sopenharmony_ci while left > 0: 33087db96d56Sopenharmony_ci sent = sock.send(s[sentsofar:]) 33097db96d56Sopenharmony_ci sentsofar += sent 33107db96d56Sopenharmony_ci left -= sent 33117db96d56Sopenharmony_ci sock.close() 33127db96d56Sopenharmony_ci finally: 33137db96d56Sopenharmony_ci t.ready.wait(2.0) 33147db96d56Sopenharmony_ci logging.config.stopListening() 33157db96d56Sopenharmony_ci threading_helper.join_thread(t) 33167db96d56Sopenharmony_ci 33177db96d56Sopenharmony_ci @support.requires_working_socket() 33187db96d56Sopenharmony_ci def test_listen_config_10_ok(self): 33197db96d56Sopenharmony_ci with support.captured_stdout() as output: 33207db96d56Sopenharmony_ci self.setup_via_listener(json.dumps(self.config10)) 33217db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 33227db96d56Sopenharmony_ci logger.warning(self.next_message()) 33237db96d56Sopenharmony_ci logger = logging.getLogger('compiler') 33247db96d56Sopenharmony_ci # Not output, because filtered 33257db96d56Sopenharmony_ci logger.warning(self.next_message()) 33267db96d56Sopenharmony_ci logger = logging.getLogger('compiler.lexer') 33277db96d56Sopenharmony_ci # Not output, because filtered 33287db96d56Sopenharmony_ci logger.warning(self.next_message()) 33297db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser.codegen") 33307db96d56Sopenharmony_ci # Output, as not filtered 33317db96d56Sopenharmony_ci logger.error(self.next_message()) 33327db96d56Sopenharmony_ci self.assert_log_lines([ 33337db96d56Sopenharmony_ci ('WARNING', '1'), 33347db96d56Sopenharmony_ci ('ERROR', '4'), 33357db96d56Sopenharmony_ci ], stream=output) 33367db96d56Sopenharmony_ci 33377db96d56Sopenharmony_ci @support.requires_working_socket() 33387db96d56Sopenharmony_ci def test_listen_config_1_ok(self): 33397db96d56Sopenharmony_ci with support.captured_stdout() as output: 33407db96d56Sopenharmony_ci self.setup_via_listener(textwrap.dedent(ConfigFileTest.config1)) 33417db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 33427db96d56Sopenharmony_ci # Both will output a message 33437db96d56Sopenharmony_ci logger.info(self.next_message()) 33447db96d56Sopenharmony_ci logger.error(self.next_message()) 33457db96d56Sopenharmony_ci self.assert_log_lines([ 33467db96d56Sopenharmony_ci ('INFO', '1'), 33477db96d56Sopenharmony_ci ('ERROR', '2'), 33487db96d56Sopenharmony_ci ], stream=output) 33497db96d56Sopenharmony_ci # Original logger output is empty. 33507db96d56Sopenharmony_ci self.assert_log_lines([]) 33517db96d56Sopenharmony_ci 33527db96d56Sopenharmony_ci @support.requires_working_socket() 33537db96d56Sopenharmony_ci def test_listen_verify(self): 33547db96d56Sopenharmony_ci 33557db96d56Sopenharmony_ci def verify_fail(stuff): 33567db96d56Sopenharmony_ci return None 33577db96d56Sopenharmony_ci 33587db96d56Sopenharmony_ci def verify_reverse(stuff): 33597db96d56Sopenharmony_ci return stuff[::-1] 33607db96d56Sopenharmony_ci 33617db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 33627db96d56Sopenharmony_ci to_send = textwrap.dedent(ConfigFileTest.config1) 33637db96d56Sopenharmony_ci # First, specify a verification function that will fail. 33647db96d56Sopenharmony_ci # We expect to see no output, since our configuration 33657db96d56Sopenharmony_ci # never took effect. 33667db96d56Sopenharmony_ci with support.captured_stdout() as output: 33677db96d56Sopenharmony_ci self.setup_via_listener(to_send, verify_fail) 33687db96d56Sopenharmony_ci # Both will output a message 33697db96d56Sopenharmony_ci logger.info(self.next_message()) 33707db96d56Sopenharmony_ci logger.error(self.next_message()) 33717db96d56Sopenharmony_ci self.assert_log_lines([], stream=output) 33727db96d56Sopenharmony_ci # Original logger output has the stuff we logged. 33737db96d56Sopenharmony_ci self.assert_log_lines([ 33747db96d56Sopenharmony_ci ('INFO', '1'), 33757db96d56Sopenharmony_ci ('ERROR', '2'), 33767db96d56Sopenharmony_ci ], pat=r"^[\w.]+ -> (\w+): (\d+)$") 33777db96d56Sopenharmony_ci 33787db96d56Sopenharmony_ci # Now, perform no verification. Our configuration 33797db96d56Sopenharmony_ci # should take effect. 33807db96d56Sopenharmony_ci 33817db96d56Sopenharmony_ci with support.captured_stdout() as output: 33827db96d56Sopenharmony_ci self.setup_via_listener(to_send) # no verify callable specified 33837db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 33847db96d56Sopenharmony_ci # Both will output a message 33857db96d56Sopenharmony_ci logger.info(self.next_message()) 33867db96d56Sopenharmony_ci logger.error(self.next_message()) 33877db96d56Sopenharmony_ci self.assert_log_lines([ 33887db96d56Sopenharmony_ci ('INFO', '3'), 33897db96d56Sopenharmony_ci ('ERROR', '4'), 33907db96d56Sopenharmony_ci ], stream=output) 33917db96d56Sopenharmony_ci # Original logger output still has the stuff we logged before. 33927db96d56Sopenharmony_ci self.assert_log_lines([ 33937db96d56Sopenharmony_ci ('INFO', '1'), 33947db96d56Sopenharmony_ci ('ERROR', '2'), 33957db96d56Sopenharmony_ci ], pat=r"^[\w.]+ -> (\w+): (\d+)$") 33967db96d56Sopenharmony_ci 33977db96d56Sopenharmony_ci # Now, perform verification which transforms the bytes. 33987db96d56Sopenharmony_ci 33997db96d56Sopenharmony_ci with support.captured_stdout() as output: 34007db96d56Sopenharmony_ci self.setup_via_listener(to_send[::-1], verify_reverse) 34017db96d56Sopenharmony_ci logger = logging.getLogger("compiler.parser") 34027db96d56Sopenharmony_ci # Both will output a message 34037db96d56Sopenharmony_ci logger.info(self.next_message()) 34047db96d56Sopenharmony_ci logger.error(self.next_message()) 34057db96d56Sopenharmony_ci self.assert_log_lines([ 34067db96d56Sopenharmony_ci ('INFO', '5'), 34077db96d56Sopenharmony_ci ('ERROR', '6'), 34087db96d56Sopenharmony_ci ], stream=output) 34097db96d56Sopenharmony_ci # Original logger output still has the stuff we logged before. 34107db96d56Sopenharmony_ci self.assert_log_lines([ 34117db96d56Sopenharmony_ci ('INFO', '1'), 34127db96d56Sopenharmony_ci ('ERROR', '2'), 34137db96d56Sopenharmony_ci ], pat=r"^[\w.]+ -> (\w+): (\d+)$") 34147db96d56Sopenharmony_ci 34157db96d56Sopenharmony_ci def test_out_of_order(self): 34167db96d56Sopenharmony_ci self.assertRaises(ValueError, self.apply_config, self.out_of_order) 34177db96d56Sopenharmony_ci 34187db96d56Sopenharmony_ci def test_out_of_order_with_dollar_style(self): 34197db96d56Sopenharmony_ci config = copy.deepcopy(self.out_of_order) 34207db96d56Sopenharmony_ci config['formatters']['mySimpleFormatter']['format'] = "${asctime} (${name}) ${levelname}: ${message}" 34217db96d56Sopenharmony_ci 34227db96d56Sopenharmony_ci self.apply_config(config) 34237db96d56Sopenharmony_ci handler = logging.getLogger('mymodule').handlers[0] 34247db96d56Sopenharmony_ci self.assertIsInstance(handler.target, logging.Handler) 34257db96d56Sopenharmony_ci self.assertIsInstance(handler.formatter._style, 34267db96d56Sopenharmony_ci logging.StringTemplateStyle) 34277db96d56Sopenharmony_ci 34287db96d56Sopenharmony_ci def test_custom_formatter_class_with_validate(self): 34297db96d56Sopenharmony_ci self.apply_config(self.custom_formatter_class_validate) 34307db96d56Sopenharmony_ci handler = logging.getLogger("my_test_logger_custom_formatter").handlers[0] 34317db96d56Sopenharmony_ci self.assertIsInstance(handler.formatter, ExceptionFormatter) 34327db96d56Sopenharmony_ci 34337db96d56Sopenharmony_ci def test_custom_formatter_class_with_validate2(self): 34347db96d56Sopenharmony_ci self.apply_config(self.custom_formatter_class_validate2) 34357db96d56Sopenharmony_ci handler = logging.getLogger("my_test_logger_custom_formatter").handlers[0] 34367db96d56Sopenharmony_ci self.assertIsInstance(handler.formatter, ExceptionFormatter) 34377db96d56Sopenharmony_ci 34387db96d56Sopenharmony_ci def test_custom_formatter_class_with_validate2_with_wrong_fmt(self): 34397db96d56Sopenharmony_ci config = self.custom_formatter_class_validate.copy() 34407db96d56Sopenharmony_ci config['formatters']['form1']['style'] = "$" 34417db96d56Sopenharmony_ci 34427db96d56Sopenharmony_ci # Exception should not be raise as we have configured 'validate' to False 34437db96d56Sopenharmony_ci self.apply_config(config) 34447db96d56Sopenharmony_ci handler = logging.getLogger("my_test_logger_custom_formatter").handlers[0] 34457db96d56Sopenharmony_ci self.assertIsInstance(handler.formatter, ExceptionFormatter) 34467db96d56Sopenharmony_ci 34477db96d56Sopenharmony_ci def test_custom_formatter_class_with_validate3(self): 34487db96d56Sopenharmony_ci self.assertRaises(ValueError, self.apply_config, self.custom_formatter_class_validate3) 34497db96d56Sopenharmony_ci 34507db96d56Sopenharmony_ci def test_custom_formatter_function_with_validate(self): 34517db96d56Sopenharmony_ci self.assertRaises(ValueError, self.apply_config, self.custom_formatter_with_function) 34527db96d56Sopenharmony_ci 34537db96d56Sopenharmony_ci def test_baseconfig(self): 34547db96d56Sopenharmony_ci d = { 34557db96d56Sopenharmony_ci 'atuple': (1, 2, 3), 34567db96d56Sopenharmony_ci 'alist': ['a', 'b', 'c'], 34577db96d56Sopenharmony_ci 'adict': {'d': 'e', 'f': 3 }, 34587db96d56Sopenharmony_ci 'nest1': ('g', ('h', 'i'), 'j'), 34597db96d56Sopenharmony_ci 'nest2': ['k', ['l', 'm'], 'n'], 34607db96d56Sopenharmony_ci 'nest3': ['o', 'cfg://alist', 'p'], 34617db96d56Sopenharmony_ci } 34627db96d56Sopenharmony_ci bc = logging.config.BaseConfigurator(d) 34637db96d56Sopenharmony_ci self.assertEqual(bc.convert('cfg://atuple[1]'), 2) 34647db96d56Sopenharmony_ci self.assertEqual(bc.convert('cfg://alist[1]'), 'b') 34657db96d56Sopenharmony_ci self.assertEqual(bc.convert('cfg://nest1[1][0]'), 'h') 34667db96d56Sopenharmony_ci self.assertEqual(bc.convert('cfg://nest2[1][1]'), 'm') 34677db96d56Sopenharmony_ci self.assertEqual(bc.convert('cfg://adict.d'), 'e') 34687db96d56Sopenharmony_ci self.assertEqual(bc.convert('cfg://adict[f]'), 3) 34697db96d56Sopenharmony_ci v = bc.convert('cfg://nest3') 34707db96d56Sopenharmony_ci self.assertEqual(v.pop(1), ['a', 'b', 'c']) 34717db96d56Sopenharmony_ci self.assertRaises(KeyError, bc.convert, 'cfg://nosuch') 34727db96d56Sopenharmony_ci self.assertRaises(ValueError, bc.convert, 'cfg://!') 34737db96d56Sopenharmony_ci self.assertRaises(KeyError, bc.convert, 'cfg://adict[2]') 34747db96d56Sopenharmony_ci 34757db96d56Sopenharmony_ci def test_namedtuple(self): 34767db96d56Sopenharmony_ci # see bpo-39142 34777db96d56Sopenharmony_ci from collections import namedtuple 34787db96d56Sopenharmony_ci 34797db96d56Sopenharmony_ci class MyHandler(logging.StreamHandler): 34807db96d56Sopenharmony_ci def __init__(self, resource, *args, **kwargs): 34817db96d56Sopenharmony_ci super().__init__(*args, **kwargs) 34827db96d56Sopenharmony_ci self.resource: namedtuple = resource 34837db96d56Sopenharmony_ci 34847db96d56Sopenharmony_ci def emit(self, record): 34857db96d56Sopenharmony_ci record.msg += f' {self.resource.type}' 34867db96d56Sopenharmony_ci return super().emit(record) 34877db96d56Sopenharmony_ci 34887db96d56Sopenharmony_ci Resource = namedtuple('Resource', ['type', 'labels']) 34897db96d56Sopenharmony_ci resource = Resource(type='my_type', labels=['a']) 34907db96d56Sopenharmony_ci 34917db96d56Sopenharmony_ci config = { 34927db96d56Sopenharmony_ci 'version': 1, 34937db96d56Sopenharmony_ci 'handlers': { 34947db96d56Sopenharmony_ci 'myhandler': { 34957db96d56Sopenharmony_ci '()': MyHandler, 34967db96d56Sopenharmony_ci 'resource': resource 34977db96d56Sopenharmony_ci } 34987db96d56Sopenharmony_ci }, 34997db96d56Sopenharmony_ci 'root': {'level': 'INFO', 'handlers': ['myhandler']}, 35007db96d56Sopenharmony_ci } 35017db96d56Sopenharmony_ci with support.captured_stderr() as stderr: 35027db96d56Sopenharmony_ci self.apply_config(config) 35037db96d56Sopenharmony_ci logging.info('some log') 35047db96d56Sopenharmony_ci self.assertEqual(stderr.getvalue(), 'some log my_type\n') 35057db96d56Sopenharmony_ci 35067db96d56Sopenharmony_ci def test_config_callable_filter_works(self): 35077db96d56Sopenharmony_ci def filter_(_): 35087db96d56Sopenharmony_ci return 1 35097db96d56Sopenharmony_ci self.apply_config({ 35107db96d56Sopenharmony_ci "version": 1, "root": {"level": "DEBUG", "filters": [filter_]} 35117db96d56Sopenharmony_ci }) 35127db96d56Sopenharmony_ci assert logging.getLogger().filters[0] is filter_ 35137db96d56Sopenharmony_ci logging.getLogger().filters = [] 35147db96d56Sopenharmony_ci 35157db96d56Sopenharmony_ci def test_config_filter_works(self): 35167db96d56Sopenharmony_ci filter_ = logging.Filter("spam.eggs") 35177db96d56Sopenharmony_ci self.apply_config({ 35187db96d56Sopenharmony_ci "version": 1, "root": {"level": "DEBUG", "filters": [filter_]} 35197db96d56Sopenharmony_ci }) 35207db96d56Sopenharmony_ci assert logging.getLogger().filters[0] is filter_ 35217db96d56Sopenharmony_ci logging.getLogger().filters = [] 35227db96d56Sopenharmony_ci 35237db96d56Sopenharmony_ci def test_config_filter_method_works(self): 35247db96d56Sopenharmony_ci class FakeFilter: 35257db96d56Sopenharmony_ci def filter(self, _): 35267db96d56Sopenharmony_ci return 1 35277db96d56Sopenharmony_ci filter_ = FakeFilter() 35287db96d56Sopenharmony_ci self.apply_config({ 35297db96d56Sopenharmony_ci "version": 1, "root": {"level": "DEBUG", "filters": [filter_]} 35307db96d56Sopenharmony_ci }) 35317db96d56Sopenharmony_ci assert logging.getLogger().filters[0] is filter_ 35327db96d56Sopenharmony_ci logging.getLogger().filters = [] 35337db96d56Sopenharmony_ci 35347db96d56Sopenharmony_ci def test_invalid_type_raises(self): 35357db96d56Sopenharmony_ci class NotAFilter: pass 35367db96d56Sopenharmony_ci for filter_ in [None, 1, NotAFilter()]: 35377db96d56Sopenharmony_ci self.assertRaises( 35387db96d56Sopenharmony_ci ValueError, 35397db96d56Sopenharmony_ci self.apply_config, 35407db96d56Sopenharmony_ci {"version": 1, "root": {"level": "DEBUG", "filters": [filter_]}} 35417db96d56Sopenharmony_ci ) 35427db96d56Sopenharmony_ci 35437db96d56Sopenharmony_ci def test_90195(self): 35447db96d56Sopenharmony_ci # See gh-90195 35457db96d56Sopenharmony_ci config = { 35467db96d56Sopenharmony_ci 'version': 1, 35477db96d56Sopenharmony_ci 'disable_existing_loggers': False, 35487db96d56Sopenharmony_ci 'handlers': { 35497db96d56Sopenharmony_ci 'console': { 35507db96d56Sopenharmony_ci 'level': 'DEBUG', 35517db96d56Sopenharmony_ci 'class': 'logging.StreamHandler', 35527db96d56Sopenharmony_ci }, 35537db96d56Sopenharmony_ci }, 35547db96d56Sopenharmony_ci 'loggers': { 35557db96d56Sopenharmony_ci 'a': { 35567db96d56Sopenharmony_ci 'level': 'DEBUG', 35577db96d56Sopenharmony_ci 'handlers': ['console'] 35587db96d56Sopenharmony_ci } 35597db96d56Sopenharmony_ci } 35607db96d56Sopenharmony_ci } 35617db96d56Sopenharmony_ci logger = logging.getLogger('a') 35627db96d56Sopenharmony_ci self.assertFalse(logger.disabled) 35637db96d56Sopenharmony_ci self.apply_config(config) 35647db96d56Sopenharmony_ci self.assertFalse(logger.disabled) 35657db96d56Sopenharmony_ci # Should disable all loggers ... 35667db96d56Sopenharmony_ci self.apply_config({'version': 1}) 35677db96d56Sopenharmony_ci self.assertTrue(logger.disabled) 35687db96d56Sopenharmony_ci del config['disable_existing_loggers'] 35697db96d56Sopenharmony_ci self.apply_config(config) 35707db96d56Sopenharmony_ci # Logger should be enabled, since explicitly mentioned 35717db96d56Sopenharmony_ci self.assertFalse(logger.disabled) 35727db96d56Sopenharmony_ci 35737db96d56Sopenharmony_ciclass ManagerTest(BaseTest): 35747db96d56Sopenharmony_ci def test_manager_loggerclass(self): 35757db96d56Sopenharmony_ci logged = [] 35767db96d56Sopenharmony_ci 35777db96d56Sopenharmony_ci class MyLogger(logging.Logger): 35787db96d56Sopenharmony_ci def _log(self, level, msg, args, exc_info=None, extra=None): 35797db96d56Sopenharmony_ci logged.append(msg) 35807db96d56Sopenharmony_ci 35817db96d56Sopenharmony_ci man = logging.Manager(None) 35827db96d56Sopenharmony_ci self.assertRaises(TypeError, man.setLoggerClass, int) 35837db96d56Sopenharmony_ci man.setLoggerClass(MyLogger) 35847db96d56Sopenharmony_ci logger = man.getLogger('test') 35857db96d56Sopenharmony_ci logger.warning('should appear in logged') 35867db96d56Sopenharmony_ci logging.warning('should not appear in logged') 35877db96d56Sopenharmony_ci 35887db96d56Sopenharmony_ci self.assertEqual(logged, ['should appear in logged']) 35897db96d56Sopenharmony_ci 35907db96d56Sopenharmony_ci def test_set_log_record_factory(self): 35917db96d56Sopenharmony_ci man = logging.Manager(None) 35927db96d56Sopenharmony_ci expected = object() 35937db96d56Sopenharmony_ci man.setLogRecordFactory(expected) 35947db96d56Sopenharmony_ci self.assertEqual(man.logRecordFactory, expected) 35957db96d56Sopenharmony_ci 35967db96d56Sopenharmony_ciclass ChildLoggerTest(BaseTest): 35977db96d56Sopenharmony_ci def test_child_loggers(self): 35987db96d56Sopenharmony_ci r = logging.getLogger() 35997db96d56Sopenharmony_ci l1 = logging.getLogger('abc') 36007db96d56Sopenharmony_ci l2 = logging.getLogger('def.ghi') 36017db96d56Sopenharmony_ci c1 = r.getChild('xyz') 36027db96d56Sopenharmony_ci c2 = r.getChild('uvw.xyz') 36037db96d56Sopenharmony_ci self.assertIs(c1, logging.getLogger('xyz')) 36047db96d56Sopenharmony_ci self.assertIs(c2, logging.getLogger('uvw.xyz')) 36057db96d56Sopenharmony_ci c1 = l1.getChild('def') 36067db96d56Sopenharmony_ci c2 = c1.getChild('ghi') 36077db96d56Sopenharmony_ci c3 = l1.getChild('def.ghi') 36087db96d56Sopenharmony_ci self.assertIs(c1, logging.getLogger('abc.def')) 36097db96d56Sopenharmony_ci self.assertIs(c2, logging.getLogger('abc.def.ghi')) 36107db96d56Sopenharmony_ci self.assertIs(c2, c3) 36117db96d56Sopenharmony_ci 36127db96d56Sopenharmony_ci 36137db96d56Sopenharmony_ciclass DerivedLogRecord(logging.LogRecord): 36147db96d56Sopenharmony_ci pass 36157db96d56Sopenharmony_ci 36167db96d56Sopenharmony_ciclass LogRecordFactoryTest(BaseTest): 36177db96d56Sopenharmony_ci 36187db96d56Sopenharmony_ci def setUp(self): 36197db96d56Sopenharmony_ci class CheckingFilter(logging.Filter): 36207db96d56Sopenharmony_ci def __init__(self, cls): 36217db96d56Sopenharmony_ci self.cls = cls 36227db96d56Sopenharmony_ci 36237db96d56Sopenharmony_ci def filter(self, record): 36247db96d56Sopenharmony_ci t = type(record) 36257db96d56Sopenharmony_ci if t is not self.cls: 36267db96d56Sopenharmony_ci msg = 'Unexpected LogRecord type %s, expected %s' % (t, 36277db96d56Sopenharmony_ci self.cls) 36287db96d56Sopenharmony_ci raise TypeError(msg) 36297db96d56Sopenharmony_ci return True 36307db96d56Sopenharmony_ci 36317db96d56Sopenharmony_ci BaseTest.setUp(self) 36327db96d56Sopenharmony_ci self.filter = CheckingFilter(DerivedLogRecord) 36337db96d56Sopenharmony_ci self.root_logger.addFilter(self.filter) 36347db96d56Sopenharmony_ci self.orig_factory = logging.getLogRecordFactory() 36357db96d56Sopenharmony_ci 36367db96d56Sopenharmony_ci def tearDown(self): 36377db96d56Sopenharmony_ci self.root_logger.removeFilter(self.filter) 36387db96d56Sopenharmony_ci BaseTest.tearDown(self) 36397db96d56Sopenharmony_ci logging.setLogRecordFactory(self.orig_factory) 36407db96d56Sopenharmony_ci 36417db96d56Sopenharmony_ci def test_logrecord_class(self): 36427db96d56Sopenharmony_ci self.assertRaises(TypeError, self.root_logger.warning, 36437db96d56Sopenharmony_ci self.next_message()) 36447db96d56Sopenharmony_ci logging.setLogRecordFactory(DerivedLogRecord) 36457db96d56Sopenharmony_ci self.root_logger.error(self.next_message()) 36467db96d56Sopenharmony_ci self.assert_log_lines([ 36477db96d56Sopenharmony_ci ('root', 'ERROR', '2'), 36487db96d56Sopenharmony_ci ]) 36497db96d56Sopenharmony_ci 36507db96d56Sopenharmony_ci 36517db96d56Sopenharmony_ci@threading_helper.requires_working_threading() 36527db96d56Sopenharmony_ciclass QueueHandlerTest(BaseTest): 36537db96d56Sopenharmony_ci # Do not bother with a logger name group. 36547db96d56Sopenharmony_ci expected_log_pat = r"^[\w.]+ -> (\w+): (\d+)$" 36557db96d56Sopenharmony_ci 36567db96d56Sopenharmony_ci def setUp(self): 36577db96d56Sopenharmony_ci BaseTest.setUp(self) 36587db96d56Sopenharmony_ci self.queue = queue.Queue(-1) 36597db96d56Sopenharmony_ci self.que_hdlr = logging.handlers.QueueHandler(self.queue) 36607db96d56Sopenharmony_ci self.name = 'que' 36617db96d56Sopenharmony_ci self.que_logger = logging.getLogger('que') 36627db96d56Sopenharmony_ci self.que_logger.propagate = False 36637db96d56Sopenharmony_ci self.que_logger.setLevel(logging.WARNING) 36647db96d56Sopenharmony_ci self.que_logger.addHandler(self.que_hdlr) 36657db96d56Sopenharmony_ci 36667db96d56Sopenharmony_ci def tearDown(self): 36677db96d56Sopenharmony_ci self.que_hdlr.close() 36687db96d56Sopenharmony_ci BaseTest.tearDown(self) 36697db96d56Sopenharmony_ci 36707db96d56Sopenharmony_ci def test_queue_handler(self): 36717db96d56Sopenharmony_ci self.que_logger.debug(self.next_message()) 36727db96d56Sopenharmony_ci self.assertRaises(queue.Empty, self.queue.get_nowait) 36737db96d56Sopenharmony_ci self.que_logger.info(self.next_message()) 36747db96d56Sopenharmony_ci self.assertRaises(queue.Empty, self.queue.get_nowait) 36757db96d56Sopenharmony_ci msg = self.next_message() 36767db96d56Sopenharmony_ci self.que_logger.warning(msg) 36777db96d56Sopenharmony_ci data = self.queue.get_nowait() 36787db96d56Sopenharmony_ci self.assertTrue(isinstance(data, logging.LogRecord)) 36797db96d56Sopenharmony_ci self.assertEqual(data.name, self.que_logger.name) 36807db96d56Sopenharmony_ci self.assertEqual((data.msg, data.args), (msg, None)) 36817db96d56Sopenharmony_ci 36827db96d56Sopenharmony_ci def test_formatting(self): 36837db96d56Sopenharmony_ci msg = self.next_message() 36847db96d56Sopenharmony_ci levelname = logging.getLevelName(logging.WARNING) 36857db96d56Sopenharmony_ci log_format_str = '{name} -> {levelname}: {message}' 36867db96d56Sopenharmony_ci formatted_msg = log_format_str.format(name=self.name, 36877db96d56Sopenharmony_ci levelname=levelname, message=msg) 36887db96d56Sopenharmony_ci formatter = logging.Formatter(self.log_format) 36897db96d56Sopenharmony_ci self.que_hdlr.setFormatter(formatter) 36907db96d56Sopenharmony_ci self.que_logger.warning(msg) 36917db96d56Sopenharmony_ci log_record = self.queue.get_nowait() 36927db96d56Sopenharmony_ci self.assertEqual(formatted_msg, log_record.msg) 36937db96d56Sopenharmony_ci self.assertEqual(formatted_msg, log_record.message) 36947db96d56Sopenharmony_ci 36957db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'), 36967db96d56Sopenharmony_ci 'logging.handlers.QueueListener required for this test') 36977db96d56Sopenharmony_ci def test_queue_listener(self): 36987db96d56Sopenharmony_ci handler = TestHandler(support.Matcher()) 36997db96d56Sopenharmony_ci listener = logging.handlers.QueueListener(self.queue, handler) 37007db96d56Sopenharmony_ci listener.start() 37017db96d56Sopenharmony_ci try: 37027db96d56Sopenharmony_ci self.que_logger.warning(self.next_message()) 37037db96d56Sopenharmony_ci self.que_logger.error(self.next_message()) 37047db96d56Sopenharmony_ci self.que_logger.critical(self.next_message()) 37057db96d56Sopenharmony_ci finally: 37067db96d56Sopenharmony_ci listener.stop() 37077db96d56Sopenharmony_ci self.assertTrue(handler.matches(levelno=logging.WARNING, message='1')) 37087db96d56Sopenharmony_ci self.assertTrue(handler.matches(levelno=logging.ERROR, message='2')) 37097db96d56Sopenharmony_ci self.assertTrue(handler.matches(levelno=logging.CRITICAL, message='3')) 37107db96d56Sopenharmony_ci handler.close() 37117db96d56Sopenharmony_ci 37127db96d56Sopenharmony_ci # Now test with respect_handler_level set 37137db96d56Sopenharmony_ci 37147db96d56Sopenharmony_ci handler = TestHandler(support.Matcher()) 37157db96d56Sopenharmony_ci handler.setLevel(logging.CRITICAL) 37167db96d56Sopenharmony_ci listener = logging.handlers.QueueListener(self.queue, handler, 37177db96d56Sopenharmony_ci respect_handler_level=True) 37187db96d56Sopenharmony_ci listener.start() 37197db96d56Sopenharmony_ci try: 37207db96d56Sopenharmony_ci self.que_logger.warning(self.next_message()) 37217db96d56Sopenharmony_ci self.que_logger.error(self.next_message()) 37227db96d56Sopenharmony_ci self.que_logger.critical(self.next_message()) 37237db96d56Sopenharmony_ci finally: 37247db96d56Sopenharmony_ci listener.stop() 37257db96d56Sopenharmony_ci self.assertFalse(handler.matches(levelno=logging.WARNING, message='4')) 37267db96d56Sopenharmony_ci self.assertFalse(handler.matches(levelno=logging.ERROR, message='5')) 37277db96d56Sopenharmony_ci self.assertTrue(handler.matches(levelno=logging.CRITICAL, message='6')) 37287db96d56Sopenharmony_ci handler.close() 37297db96d56Sopenharmony_ci 37307db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'), 37317db96d56Sopenharmony_ci 'logging.handlers.QueueListener required for this test') 37327db96d56Sopenharmony_ci def test_queue_listener_with_StreamHandler(self): 37337db96d56Sopenharmony_ci # Test that traceback and stack-info only appends once (bpo-34334, bpo-46755). 37347db96d56Sopenharmony_ci listener = logging.handlers.QueueListener(self.queue, self.root_hdlr) 37357db96d56Sopenharmony_ci listener.start() 37367db96d56Sopenharmony_ci try: 37377db96d56Sopenharmony_ci 1 / 0 37387db96d56Sopenharmony_ci except ZeroDivisionError as e: 37397db96d56Sopenharmony_ci exc = e 37407db96d56Sopenharmony_ci self.que_logger.exception(self.next_message(), exc_info=exc) 37417db96d56Sopenharmony_ci self.que_logger.error(self.next_message(), stack_info=True) 37427db96d56Sopenharmony_ci listener.stop() 37437db96d56Sopenharmony_ci self.assertEqual(self.stream.getvalue().strip().count('Traceback'), 1) 37447db96d56Sopenharmony_ci self.assertEqual(self.stream.getvalue().strip().count('Stack'), 1) 37457db96d56Sopenharmony_ci 37467db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'), 37477db96d56Sopenharmony_ci 'logging.handlers.QueueListener required for this test') 37487db96d56Sopenharmony_ci def test_queue_listener_with_multiple_handlers(self): 37497db96d56Sopenharmony_ci # Test that queue handler format doesn't affect other handler formats (bpo-35726). 37507db96d56Sopenharmony_ci self.que_hdlr.setFormatter(self.root_formatter) 37517db96d56Sopenharmony_ci self.que_logger.addHandler(self.root_hdlr) 37527db96d56Sopenharmony_ci 37537db96d56Sopenharmony_ci listener = logging.handlers.QueueListener(self.queue, self.que_hdlr) 37547db96d56Sopenharmony_ci listener.start() 37557db96d56Sopenharmony_ci self.que_logger.error("error") 37567db96d56Sopenharmony_ci listener.stop() 37577db96d56Sopenharmony_ci self.assertEqual(self.stream.getvalue().strip(), "que -> ERROR: error") 37587db96d56Sopenharmony_ci 37597db96d56Sopenharmony_ciif hasattr(logging.handlers, 'QueueListener'): 37607db96d56Sopenharmony_ci import multiprocessing 37617db96d56Sopenharmony_ci from unittest.mock import patch 37627db96d56Sopenharmony_ci 37637db96d56Sopenharmony_ci @threading_helper.requires_working_threading() 37647db96d56Sopenharmony_ci class QueueListenerTest(BaseTest): 37657db96d56Sopenharmony_ci """ 37667db96d56Sopenharmony_ci Tests based on patch submitted for issue #27930. Ensure that 37677db96d56Sopenharmony_ci QueueListener handles all log messages. 37687db96d56Sopenharmony_ci """ 37697db96d56Sopenharmony_ci 37707db96d56Sopenharmony_ci repeat = 20 37717db96d56Sopenharmony_ci 37727db96d56Sopenharmony_ci @staticmethod 37737db96d56Sopenharmony_ci def setup_and_log(log_queue, ident): 37747db96d56Sopenharmony_ci """ 37757db96d56Sopenharmony_ci Creates a logger with a QueueHandler that logs to a queue read by a 37767db96d56Sopenharmony_ci QueueListener. Starts the listener, logs five messages, and stops 37777db96d56Sopenharmony_ci the listener. 37787db96d56Sopenharmony_ci """ 37797db96d56Sopenharmony_ci logger = logging.getLogger('test_logger_with_id_%s' % ident) 37807db96d56Sopenharmony_ci logger.setLevel(logging.DEBUG) 37817db96d56Sopenharmony_ci handler = logging.handlers.QueueHandler(log_queue) 37827db96d56Sopenharmony_ci logger.addHandler(handler) 37837db96d56Sopenharmony_ci listener = logging.handlers.QueueListener(log_queue) 37847db96d56Sopenharmony_ci listener.start() 37857db96d56Sopenharmony_ci 37867db96d56Sopenharmony_ci logger.info('one') 37877db96d56Sopenharmony_ci logger.info('two') 37887db96d56Sopenharmony_ci logger.info('three') 37897db96d56Sopenharmony_ci logger.info('four') 37907db96d56Sopenharmony_ci logger.info('five') 37917db96d56Sopenharmony_ci 37927db96d56Sopenharmony_ci listener.stop() 37937db96d56Sopenharmony_ci logger.removeHandler(handler) 37947db96d56Sopenharmony_ci handler.close() 37957db96d56Sopenharmony_ci 37967db96d56Sopenharmony_ci @patch.object(logging.handlers.QueueListener, 'handle') 37977db96d56Sopenharmony_ci def test_handle_called_with_queue_queue(self, mock_handle): 37987db96d56Sopenharmony_ci for i in range(self.repeat): 37997db96d56Sopenharmony_ci log_queue = queue.Queue() 38007db96d56Sopenharmony_ci self.setup_and_log(log_queue, '%s_%s' % (self.id(), i)) 38017db96d56Sopenharmony_ci self.assertEqual(mock_handle.call_count, 5 * self.repeat, 38027db96d56Sopenharmony_ci 'correct number of handled log messages') 38037db96d56Sopenharmony_ci 38047db96d56Sopenharmony_ci @patch.object(logging.handlers.QueueListener, 'handle') 38057db96d56Sopenharmony_ci def test_handle_called_with_mp_queue(self, mock_handle): 38067db96d56Sopenharmony_ci # bpo-28668: The multiprocessing (mp) module is not functional 38077db96d56Sopenharmony_ci # when the mp.synchronize module cannot be imported. 38087db96d56Sopenharmony_ci support.skip_if_broken_multiprocessing_synchronize() 38097db96d56Sopenharmony_ci for i in range(self.repeat): 38107db96d56Sopenharmony_ci log_queue = multiprocessing.Queue() 38117db96d56Sopenharmony_ci self.setup_and_log(log_queue, '%s_%s' % (self.id(), i)) 38127db96d56Sopenharmony_ci log_queue.close() 38137db96d56Sopenharmony_ci log_queue.join_thread() 38147db96d56Sopenharmony_ci self.assertEqual(mock_handle.call_count, 5 * self.repeat, 38157db96d56Sopenharmony_ci 'correct number of handled log messages') 38167db96d56Sopenharmony_ci 38177db96d56Sopenharmony_ci @staticmethod 38187db96d56Sopenharmony_ci def get_all_from_queue(log_queue): 38197db96d56Sopenharmony_ci try: 38207db96d56Sopenharmony_ci while True: 38217db96d56Sopenharmony_ci yield log_queue.get_nowait() 38227db96d56Sopenharmony_ci except queue.Empty: 38237db96d56Sopenharmony_ci return [] 38247db96d56Sopenharmony_ci 38257db96d56Sopenharmony_ci def test_no_messages_in_queue_after_stop(self): 38267db96d56Sopenharmony_ci """ 38277db96d56Sopenharmony_ci Five messages are logged then the QueueListener is stopped. This 38287db96d56Sopenharmony_ci test then gets everything off the queue. Failure of this test 38297db96d56Sopenharmony_ci indicates that messages were not registered on the queue until 38307db96d56Sopenharmony_ci _after_ the QueueListener stopped. 38317db96d56Sopenharmony_ci """ 38327db96d56Sopenharmony_ci # bpo-28668: The multiprocessing (mp) module is not functional 38337db96d56Sopenharmony_ci # when the mp.synchronize module cannot be imported. 38347db96d56Sopenharmony_ci support.skip_if_broken_multiprocessing_synchronize() 38357db96d56Sopenharmony_ci for i in range(self.repeat): 38367db96d56Sopenharmony_ci queue = multiprocessing.Queue() 38377db96d56Sopenharmony_ci self.setup_and_log(queue, '%s_%s' %(self.id(), i)) 38387db96d56Sopenharmony_ci # time.sleep(1) 38397db96d56Sopenharmony_ci items = list(self.get_all_from_queue(queue)) 38407db96d56Sopenharmony_ci queue.close() 38417db96d56Sopenharmony_ci queue.join_thread() 38427db96d56Sopenharmony_ci 38437db96d56Sopenharmony_ci expected = [[], [logging.handlers.QueueListener._sentinel]] 38447db96d56Sopenharmony_ci self.assertIn(items, expected, 38457db96d56Sopenharmony_ci 'Found unexpected messages in queue: %s' % ( 38467db96d56Sopenharmony_ci [m.msg if isinstance(m, logging.LogRecord) 38477db96d56Sopenharmony_ci else m for m in items])) 38487db96d56Sopenharmony_ci 38497db96d56Sopenharmony_ci def test_calls_task_done_after_stop(self): 38507db96d56Sopenharmony_ci # Issue 36813: Make sure queue.join does not deadlock. 38517db96d56Sopenharmony_ci log_queue = queue.Queue() 38527db96d56Sopenharmony_ci listener = logging.handlers.QueueListener(log_queue) 38537db96d56Sopenharmony_ci listener.start() 38547db96d56Sopenharmony_ci listener.stop() 38557db96d56Sopenharmony_ci with self.assertRaises(ValueError): 38567db96d56Sopenharmony_ci # Make sure all tasks are done and .join won't block. 38577db96d56Sopenharmony_ci log_queue.task_done() 38587db96d56Sopenharmony_ci 38597db96d56Sopenharmony_ci 38607db96d56Sopenharmony_ciZERO = datetime.timedelta(0) 38617db96d56Sopenharmony_ci 38627db96d56Sopenharmony_ciclass UTC(datetime.tzinfo): 38637db96d56Sopenharmony_ci def utcoffset(self, dt): 38647db96d56Sopenharmony_ci return ZERO 38657db96d56Sopenharmony_ci 38667db96d56Sopenharmony_ci dst = utcoffset 38677db96d56Sopenharmony_ci 38687db96d56Sopenharmony_ci def tzname(self, dt): 38697db96d56Sopenharmony_ci return 'UTC' 38707db96d56Sopenharmony_ci 38717db96d56Sopenharmony_ciutc = UTC() 38727db96d56Sopenharmony_ci 38737db96d56Sopenharmony_ciclass AssertErrorMessage: 38747db96d56Sopenharmony_ci 38757db96d56Sopenharmony_ci def assert_error_message(self, exception, message, *args, **kwargs): 38767db96d56Sopenharmony_ci try: 38777db96d56Sopenharmony_ci self.assertRaises((), *args, **kwargs) 38787db96d56Sopenharmony_ci except exception as e: 38797db96d56Sopenharmony_ci self.assertEqual(message, str(e)) 38807db96d56Sopenharmony_ci 38817db96d56Sopenharmony_ciclass FormatterTest(unittest.TestCase, AssertErrorMessage): 38827db96d56Sopenharmony_ci def setUp(self): 38837db96d56Sopenharmony_ci self.common = { 38847db96d56Sopenharmony_ci 'name': 'formatter.test', 38857db96d56Sopenharmony_ci 'level': logging.DEBUG, 38867db96d56Sopenharmony_ci 'pathname': os.path.join('path', 'to', 'dummy.ext'), 38877db96d56Sopenharmony_ci 'lineno': 42, 38887db96d56Sopenharmony_ci 'exc_info': None, 38897db96d56Sopenharmony_ci 'func': None, 38907db96d56Sopenharmony_ci 'msg': 'Message with %d %s', 38917db96d56Sopenharmony_ci 'args': (2, 'placeholders'), 38927db96d56Sopenharmony_ci } 38937db96d56Sopenharmony_ci self.variants = { 38947db96d56Sopenharmony_ci 'custom': { 38957db96d56Sopenharmony_ci 'custom': 1234 38967db96d56Sopenharmony_ci } 38977db96d56Sopenharmony_ci } 38987db96d56Sopenharmony_ci 38997db96d56Sopenharmony_ci def get_record(self, name=None): 39007db96d56Sopenharmony_ci result = dict(self.common) 39017db96d56Sopenharmony_ci if name is not None: 39027db96d56Sopenharmony_ci result.update(self.variants[name]) 39037db96d56Sopenharmony_ci return logging.makeLogRecord(result) 39047db96d56Sopenharmony_ci 39057db96d56Sopenharmony_ci def test_percent(self): 39067db96d56Sopenharmony_ci # Test %-formatting 39077db96d56Sopenharmony_ci r = self.get_record() 39087db96d56Sopenharmony_ci f = logging.Formatter('${%(message)s}') 39097db96d56Sopenharmony_ci self.assertEqual(f.format(r), '${Message with 2 placeholders}') 39107db96d56Sopenharmony_ci f = logging.Formatter('%(random)s') 39117db96d56Sopenharmony_ci self.assertRaises(ValueError, f.format, r) 39127db96d56Sopenharmony_ci self.assertFalse(f.usesTime()) 39137db96d56Sopenharmony_ci f = logging.Formatter('%(asctime)s') 39147db96d56Sopenharmony_ci self.assertTrue(f.usesTime()) 39157db96d56Sopenharmony_ci f = logging.Formatter('%(asctime)-15s') 39167db96d56Sopenharmony_ci self.assertTrue(f.usesTime()) 39177db96d56Sopenharmony_ci f = logging.Formatter('%(asctime)#15s') 39187db96d56Sopenharmony_ci self.assertTrue(f.usesTime()) 39197db96d56Sopenharmony_ci 39207db96d56Sopenharmony_ci def test_braces(self): 39217db96d56Sopenharmony_ci # Test {}-formatting 39227db96d56Sopenharmony_ci r = self.get_record() 39237db96d56Sopenharmony_ci f = logging.Formatter('$%{message}%$', style='{') 39247db96d56Sopenharmony_ci self.assertEqual(f.format(r), '$%Message with 2 placeholders%$') 39257db96d56Sopenharmony_ci f = logging.Formatter('{random}', style='{') 39267db96d56Sopenharmony_ci self.assertRaises(ValueError, f.format, r) 39277db96d56Sopenharmony_ci f = logging.Formatter("{message}", style='{') 39287db96d56Sopenharmony_ci self.assertFalse(f.usesTime()) 39297db96d56Sopenharmony_ci f = logging.Formatter('{asctime}', style='{') 39307db96d56Sopenharmony_ci self.assertTrue(f.usesTime()) 39317db96d56Sopenharmony_ci f = logging.Formatter('{asctime!s:15}', style='{') 39327db96d56Sopenharmony_ci self.assertTrue(f.usesTime()) 39337db96d56Sopenharmony_ci f = logging.Formatter('{asctime:15}', style='{') 39347db96d56Sopenharmony_ci self.assertTrue(f.usesTime()) 39357db96d56Sopenharmony_ci 39367db96d56Sopenharmony_ci def test_dollars(self): 39377db96d56Sopenharmony_ci # Test $-formatting 39387db96d56Sopenharmony_ci r = self.get_record() 39397db96d56Sopenharmony_ci f = logging.Formatter('${message}', style='$') 39407db96d56Sopenharmony_ci self.assertEqual(f.format(r), 'Message with 2 placeholders') 39417db96d56Sopenharmony_ci f = logging.Formatter('$message', style='$') 39427db96d56Sopenharmony_ci self.assertEqual(f.format(r), 'Message with 2 placeholders') 39437db96d56Sopenharmony_ci f = logging.Formatter('$$%${message}%$$', style='$') 39447db96d56Sopenharmony_ci self.assertEqual(f.format(r), '$%Message with 2 placeholders%$') 39457db96d56Sopenharmony_ci f = logging.Formatter('${random}', style='$') 39467db96d56Sopenharmony_ci self.assertRaises(ValueError, f.format, r) 39477db96d56Sopenharmony_ci self.assertFalse(f.usesTime()) 39487db96d56Sopenharmony_ci f = logging.Formatter('${asctime}', style='$') 39497db96d56Sopenharmony_ci self.assertTrue(f.usesTime()) 39507db96d56Sopenharmony_ci f = logging.Formatter('$asctime', style='$') 39517db96d56Sopenharmony_ci self.assertTrue(f.usesTime()) 39527db96d56Sopenharmony_ci f = logging.Formatter('${message}', style='$') 39537db96d56Sopenharmony_ci self.assertFalse(f.usesTime()) 39547db96d56Sopenharmony_ci f = logging.Formatter('${asctime}--', style='$') 39557db96d56Sopenharmony_ci self.assertTrue(f.usesTime()) 39567db96d56Sopenharmony_ci 39577db96d56Sopenharmony_ci def test_format_validate(self): 39587db96d56Sopenharmony_ci # Check correct formatting 39597db96d56Sopenharmony_ci # Percentage style 39607db96d56Sopenharmony_ci f = logging.Formatter("%(levelname)-15s - %(message) 5s - %(process)03d - %(module) - %(asctime)*.3s") 39617db96d56Sopenharmony_ci self.assertEqual(f._fmt, "%(levelname)-15s - %(message) 5s - %(process)03d - %(module) - %(asctime)*.3s") 39627db96d56Sopenharmony_ci f = logging.Formatter("%(asctime)*s - %(asctime)*.3s - %(process)-34.33o") 39637db96d56Sopenharmony_ci self.assertEqual(f._fmt, "%(asctime)*s - %(asctime)*.3s - %(process)-34.33o") 39647db96d56Sopenharmony_ci f = logging.Formatter("%(process)#+027.23X") 39657db96d56Sopenharmony_ci self.assertEqual(f._fmt, "%(process)#+027.23X") 39667db96d56Sopenharmony_ci f = logging.Formatter("%(foo)#.*g") 39677db96d56Sopenharmony_ci self.assertEqual(f._fmt, "%(foo)#.*g") 39687db96d56Sopenharmony_ci 39697db96d56Sopenharmony_ci # StrFormat Style 39707db96d56Sopenharmony_ci f = logging.Formatter("$%{message}%$ - {asctime!a:15} - {customfield['key']}", style="{") 39717db96d56Sopenharmony_ci self.assertEqual(f._fmt, "$%{message}%$ - {asctime!a:15} - {customfield['key']}") 39727db96d56Sopenharmony_ci f = logging.Formatter("{process:.2f} - {custom.f:.4f}", style="{") 39737db96d56Sopenharmony_ci self.assertEqual(f._fmt, "{process:.2f} - {custom.f:.4f}") 39747db96d56Sopenharmony_ci f = logging.Formatter("{customfield!s:#<30}", style="{") 39757db96d56Sopenharmony_ci self.assertEqual(f._fmt, "{customfield!s:#<30}") 39767db96d56Sopenharmony_ci f = logging.Formatter("{message!r}", style="{") 39777db96d56Sopenharmony_ci self.assertEqual(f._fmt, "{message!r}") 39787db96d56Sopenharmony_ci f = logging.Formatter("{message!s}", style="{") 39797db96d56Sopenharmony_ci self.assertEqual(f._fmt, "{message!s}") 39807db96d56Sopenharmony_ci f = logging.Formatter("{message!a}", style="{") 39817db96d56Sopenharmony_ci self.assertEqual(f._fmt, "{message!a}") 39827db96d56Sopenharmony_ci f = logging.Formatter("{process!r:4.2}", style="{") 39837db96d56Sopenharmony_ci self.assertEqual(f._fmt, "{process!r:4.2}") 39847db96d56Sopenharmony_ci f = logging.Formatter("{process!s:<#30,.12f}- {custom:=+#30,.1d} - {module:^30}", style="{") 39857db96d56Sopenharmony_ci self.assertEqual(f._fmt, "{process!s:<#30,.12f}- {custom:=+#30,.1d} - {module:^30}") 39867db96d56Sopenharmony_ci f = logging.Formatter("{process!s:{w},.{p}}", style="{") 39877db96d56Sopenharmony_ci self.assertEqual(f._fmt, "{process!s:{w},.{p}}") 39887db96d56Sopenharmony_ci f = logging.Formatter("{foo:12.{p}}", style="{") 39897db96d56Sopenharmony_ci self.assertEqual(f._fmt, "{foo:12.{p}}") 39907db96d56Sopenharmony_ci f = logging.Formatter("{foo:{w}.6}", style="{") 39917db96d56Sopenharmony_ci self.assertEqual(f._fmt, "{foo:{w}.6}") 39927db96d56Sopenharmony_ci f = logging.Formatter("{foo[0].bar[1].baz}", style="{") 39937db96d56Sopenharmony_ci self.assertEqual(f._fmt, "{foo[0].bar[1].baz}") 39947db96d56Sopenharmony_ci f = logging.Formatter("{foo[k1].bar[k2].baz}", style="{") 39957db96d56Sopenharmony_ci self.assertEqual(f._fmt, "{foo[k1].bar[k2].baz}") 39967db96d56Sopenharmony_ci f = logging.Formatter("{12[k1].bar[k2].baz}", style="{") 39977db96d56Sopenharmony_ci self.assertEqual(f._fmt, "{12[k1].bar[k2].baz}") 39987db96d56Sopenharmony_ci 39997db96d56Sopenharmony_ci # Dollar style 40007db96d56Sopenharmony_ci f = logging.Formatter("${asctime} - $message", style="$") 40017db96d56Sopenharmony_ci self.assertEqual(f._fmt, "${asctime} - $message") 40027db96d56Sopenharmony_ci f = logging.Formatter("$bar $$", style="$") 40037db96d56Sopenharmony_ci self.assertEqual(f._fmt, "$bar $$") 40047db96d56Sopenharmony_ci f = logging.Formatter("$bar $$$$", style="$") 40057db96d56Sopenharmony_ci self.assertEqual(f._fmt, "$bar $$$$") # this would print two $($$) 40067db96d56Sopenharmony_ci 40077db96d56Sopenharmony_ci # Testing when ValueError being raised from incorrect format 40087db96d56Sopenharmony_ci # Percentage Style 40097db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, "%(asctime)Z") 40107db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, "%(asctime)b") 40117db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, "%(asctime)*") 40127db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, "%(asctime)*3s") 40137db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, "%(asctime)_") 40147db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{asctime}') 40157db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '${message}') 40167db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '%(foo)#12.3*f') # with both * and decimal number as precision 40177db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '%(foo)0*.8*f') 40187db96d56Sopenharmony_ci 40197db96d56Sopenharmony_ci # StrFormat Style 40207db96d56Sopenharmony_ci # Testing failure for '-' in field name 40217db96d56Sopenharmony_ci self.assert_error_message( 40227db96d56Sopenharmony_ci ValueError, 40237db96d56Sopenharmony_ci "invalid format: invalid field name/expression: 'name-thing'", 40247db96d56Sopenharmony_ci logging.Formatter, "{name-thing}", style="{" 40257db96d56Sopenharmony_ci ) 40267db96d56Sopenharmony_ci # Testing failure for style mismatch 40277db96d56Sopenharmony_ci self.assert_error_message( 40287db96d56Sopenharmony_ci ValueError, 40297db96d56Sopenharmony_ci "invalid format: no fields", 40307db96d56Sopenharmony_ci logging.Formatter, '%(asctime)s', style='{' 40317db96d56Sopenharmony_ci ) 40327db96d56Sopenharmony_ci # Testing failure for invalid conversion 40337db96d56Sopenharmony_ci self.assert_error_message( 40347db96d56Sopenharmony_ci ValueError, 40357db96d56Sopenharmony_ci "invalid conversion: 'Z'" 40367db96d56Sopenharmony_ci ) 40377db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{asctime!s:#30,15f}', style='{') 40387db96d56Sopenharmony_ci self.assert_error_message( 40397db96d56Sopenharmony_ci ValueError, 40407db96d56Sopenharmony_ci "invalid format: expected ':' after conversion specifier", 40417db96d56Sopenharmony_ci logging.Formatter, '{asctime!aa:15}', style='{' 40427db96d56Sopenharmony_ci ) 40437db96d56Sopenharmony_ci # Testing failure for invalid spec 40447db96d56Sopenharmony_ci self.assert_error_message( 40457db96d56Sopenharmony_ci ValueError, 40467db96d56Sopenharmony_ci "invalid format: bad specifier: '.2ff'", 40477db96d56Sopenharmony_ci logging.Formatter, '{process:.2ff}', style='{' 40487db96d56Sopenharmony_ci ) 40497db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{process:.2Z}', style='{') 40507db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{process!s:<##30,12g}', style='{') 40517db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{process!s:<#30#,12g}', style='{') 40527db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{process!s:{{w}},{{p}}}', style='{') 40537db96d56Sopenharmony_ci # Testing failure for mismatch braces 40547db96d56Sopenharmony_ci self.assert_error_message( 40557db96d56Sopenharmony_ci ValueError, 40567db96d56Sopenharmony_ci "invalid format: expected '}' before end of string", 40577db96d56Sopenharmony_ci logging.Formatter, '{process', style='{' 40587db96d56Sopenharmony_ci ) 40597db96d56Sopenharmony_ci self.assert_error_message( 40607db96d56Sopenharmony_ci ValueError, 40617db96d56Sopenharmony_ci "invalid format: Single '}' encountered in format string", 40627db96d56Sopenharmony_ci logging.Formatter, 'process}', style='{' 40637db96d56Sopenharmony_ci ) 40647db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{{foo!r:4.2}', style='{') 40657db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{{foo!r:4.2}}', style='{') 40667db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{foo/bar}', style='{') 40677db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{foo:{{w}}.{{p}}}}', style='{') 40687db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{foo!X:{{w}}.{{p}}}', style='{') 40697db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{foo!a:random}', style='{') 40707db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{foo!a:ran{dom}', style='{') 40717db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{foo!a:ran{d}om}', style='{') 40727db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '{foo.!a:d}', style='{') 40737db96d56Sopenharmony_ci 40747db96d56Sopenharmony_ci # Dollar style 40757db96d56Sopenharmony_ci # Testing failure for mismatch bare $ 40767db96d56Sopenharmony_ci self.assert_error_message( 40777db96d56Sopenharmony_ci ValueError, 40787db96d56Sopenharmony_ci "invalid format: bare \'$\' not allowed", 40797db96d56Sopenharmony_ci logging.Formatter, '$bar $$$', style='$' 40807db96d56Sopenharmony_ci ) 40817db96d56Sopenharmony_ci self.assert_error_message( 40827db96d56Sopenharmony_ci ValueError, 40837db96d56Sopenharmony_ci "invalid format: bare \'$\' not allowed", 40847db96d56Sopenharmony_ci logging.Formatter, 'bar $', style='$' 40857db96d56Sopenharmony_ci ) 40867db96d56Sopenharmony_ci self.assert_error_message( 40877db96d56Sopenharmony_ci ValueError, 40887db96d56Sopenharmony_ci "invalid format: bare \'$\' not allowed", 40897db96d56Sopenharmony_ci logging.Formatter, 'foo $.', style='$' 40907db96d56Sopenharmony_ci ) 40917db96d56Sopenharmony_ci # Testing failure for mismatch style 40927db96d56Sopenharmony_ci self.assert_error_message( 40937db96d56Sopenharmony_ci ValueError, 40947db96d56Sopenharmony_ci "invalid format: no fields", 40957db96d56Sopenharmony_ci logging.Formatter, '{asctime}', style='$' 40967db96d56Sopenharmony_ci ) 40977db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '%(asctime)s', style='$') 40987db96d56Sopenharmony_ci 40997db96d56Sopenharmony_ci # Testing failure for incorrect fields 41007db96d56Sopenharmony_ci self.assert_error_message( 41017db96d56Sopenharmony_ci ValueError, 41027db96d56Sopenharmony_ci "invalid format: no fields", 41037db96d56Sopenharmony_ci logging.Formatter, 'foo', style='$' 41047db96d56Sopenharmony_ci ) 41057db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, '${asctime', style='$') 41067db96d56Sopenharmony_ci 41077db96d56Sopenharmony_ci def test_defaults_parameter(self): 41087db96d56Sopenharmony_ci fmts = ['%(custom)s %(message)s', '{custom} {message}', '$custom $message'] 41097db96d56Sopenharmony_ci styles = ['%', '{', '$'] 41107db96d56Sopenharmony_ci for fmt, style in zip(fmts, styles): 41117db96d56Sopenharmony_ci f = logging.Formatter(fmt, style=style, defaults={'custom': 'Default'}) 41127db96d56Sopenharmony_ci r = self.get_record() 41137db96d56Sopenharmony_ci self.assertEqual(f.format(r), 'Default Message with 2 placeholders') 41147db96d56Sopenharmony_ci r = self.get_record("custom") 41157db96d56Sopenharmony_ci self.assertEqual(f.format(r), '1234 Message with 2 placeholders') 41167db96d56Sopenharmony_ci 41177db96d56Sopenharmony_ci # Without default 41187db96d56Sopenharmony_ci f = logging.Formatter(fmt, style=style) 41197db96d56Sopenharmony_ci r = self.get_record() 41207db96d56Sopenharmony_ci self.assertRaises(ValueError, f.format, r) 41217db96d56Sopenharmony_ci 41227db96d56Sopenharmony_ci # Non-existing default is ignored 41237db96d56Sopenharmony_ci f = logging.Formatter(fmt, style=style, defaults={'Non-existing': 'Default'}) 41247db96d56Sopenharmony_ci r = self.get_record("custom") 41257db96d56Sopenharmony_ci self.assertEqual(f.format(r), '1234 Message with 2 placeholders') 41267db96d56Sopenharmony_ci 41277db96d56Sopenharmony_ci def test_invalid_style(self): 41287db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.Formatter, None, None, 'x') 41297db96d56Sopenharmony_ci 41307db96d56Sopenharmony_ci def test_time(self): 41317db96d56Sopenharmony_ci r = self.get_record() 41327db96d56Sopenharmony_ci dt = datetime.datetime(1993, 4, 21, 8, 3, 0, 0, utc) 41337db96d56Sopenharmony_ci # We use None to indicate we want the local timezone 41347db96d56Sopenharmony_ci # We're essentially converting a UTC time to local time 41357db96d56Sopenharmony_ci r.created = time.mktime(dt.astimezone(None).timetuple()) 41367db96d56Sopenharmony_ci r.msecs = 123 41377db96d56Sopenharmony_ci f = logging.Formatter('%(asctime)s %(message)s') 41387db96d56Sopenharmony_ci f.converter = time.gmtime 41397db96d56Sopenharmony_ci self.assertEqual(f.formatTime(r), '1993-04-21 08:03:00,123') 41407db96d56Sopenharmony_ci self.assertEqual(f.formatTime(r, '%Y:%d'), '1993:21') 41417db96d56Sopenharmony_ci f.format(r) 41427db96d56Sopenharmony_ci self.assertEqual(r.asctime, '1993-04-21 08:03:00,123') 41437db96d56Sopenharmony_ci 41447db96d56Sopenharmony_ci def test_default_msec_format_none(self): 41457db96d56Sopenharmony_ci class NoMsecFormatter(logging.Formatter): 41467db96d56Sopenharmony_ci default_msec_format = None 41477db96d56Sopenharmony_ci default_time_format = '%d/%m/%Y %H:%M:%S' 41487db96d56Sopenharmony_ci 41497db96d56Sopenharmony_ci r = self.get_record() 41507db96d56Sopenharmony_ci dt = datetime.datetime(1993, 4, 21, 8, 3, 0, 123, utc) 41517db96d56Sopenharmony_ci r.created = time.mktime(dt.astimezone(None).timetuple()) 41527db96d56Sopenharmony_ci f = NoMsecFormatter() 41537db96d56Sopenharmony_ci f.converter = time.gmtime 41547db96d56Sopenharmony_ci self.assertEqual(f.formatTime(r), '21/04/1993 08:03:00') 41557db96d56Sopenharmony_ci 41567db96d56Sopenharmony_ci def test_issue_89047(self): 41577db96d56Sopenharmony_ci f = logging.Formatter(fmt='{asctime}.{msecs:03.0f} {message}', style='{', datefmt="%Y-%m-%d %H:%M:%S") 41587db96d56Sopenharmony_ci for i in range(2500): 41597db96d56Sopenharmony_ci time.sleep(0.0004) 41607db96d56Sopenharmony_ci r = logging.makeLogRecord({'msg': 'Message %d' % (i + 1)}) 41617db96d56Sopenharmony_ci s = f.format(r) 41627db96d56Sopenharmony_ci self.assertNotIn('.1000', s) 41637db96d56Sopenharmony_ci 41647db96d56Sopenharmony_ci 41657db96d56Sopenharmony_ciclass TestBufferingFormatter(logging.BufferingFormatter): 41667db96d56Sopenharmony_ci def formatHeader(self, records): 41677db96d56Sopenharmony_ci return '[(%d)' % len(records) 41687db96d56Sopenharmony_ci 41697db96d56Sopenharmony_ci def formatFooter(self, records): 41707db96d56Sopenharmony_ci return '(%d)]' % len(records) 41717db96d56Sopenharmony_ci 41727db96d56Sopenharmony_ciclass BufferingFormatterTest(unittest.TestCase): 41737db96d56Sopenharmony_ci def setUp(self): 41747db96d56Sopenharmony_ci self.records = [ 41757db96d56Sopenharmony_ci logging.makeLogRecord({'msg': 'one'}), 41767db96d56Sopenharmony_ci logging.makeLogRecord({'msg': 'two'}), 41777db96d56Sopenharmony_ci ] 41787db96d56Sopenharmony_ci 41797db96d56Sopenharmony_ci def test_default(self): 41807db96d56Sopenharmony_ci f = logging.BufferingFormatter() 41817db96d56Sopenharmony_ci self.assertEqual('', f.format([])) 41827db96d56Sopenharmony_ci self.assertEqual('onetwo', f.format(self.records)) 41837db96d56Sopenharmony_ci 41847db96d56Sopenharmony_ci def test_custom(self): 41857db96d56Sopenharmony_ci f = TestBufferingFormatter() 41867db96d56Sopenharmony_ci self.assertEqual('[(2)onetwo(2)]', f.format(self.records)) 41877db96d56Sopenharmony_ci lf = logging.Formatter('<%(message)s>') 41887db96d56Sopenharmony_ci f = TestBufferingFormatter(lf) 41897db96d56Sopenharmony_ci self.assertEqual('[(2)<one><two>(2)]', f.format(self.records)) 41907db96d56Sopenharmony_ci 41917db96d56Sopenharmony_ciclass ExceptionTest(BaseTest): 41927db96d56Sopenharmony_ci def test_formatting(self): 41937db96d56Sopenharmony_ci r = self.root_logger 41947db96d56Sopenharmony_ci h = RecordingHandler() 41957db96d56Sopenharmony_ci r.addHandler(h) 41967db96d56Sopenharmony_ci try: 41977db96d56Sopenharmony_ci raise RuntimeError('deliberate mistake') 41987db96d56Sopenharmony_ci except: 41997db96d56Sopenharmony_ci logging.exception('failed', stack_info=True) 42007db96d56Sopenharmony_ci r.removeHandler(h) 42017db96d56Sopenharmony_ci h.close() 42027db96d56Sopenharmony_ci r = h.records[0] 42037db96d56Sopenharmony_ci self.assertTrue(r.exc_text.startswith('Traceback (most recent ' 42047db96d56Sopenharmony_ci 'call last):\n')) 42057db96d56Sopenharmony_ci self.assertTrue(r.exc_text.endswith('\nRuntimeError: ' 42067db96d56Sopenharmony_ci 'deliberate mistake')) 42077db96d56Sopenharmony_ci self.assertTrue(r.stack_info.startswith('Stack (most recent ' 42087db96d56Sopenharmony_ci 'call last):\n')) 42097db96d56Sopenharmony_ci self.assertTrue(r.stack_info.endswith('logging.exception(\'failed\', ' 42107db96d56Sopenharmony_ci 'stack_info=True)')) 42117db96d56Sopenharmony_ci 42127db96d56Sopenharmony_ci 42137db96d56Sopenharmony_ciclass LastResortTest(BaseTest): 42147db96d56Sopenharmony_ci def test_last_resort(self): 42157db96d56Sopenharmony_ci # Test the last resort handler 42167db96d56Sopenharmony_ci root = self.root_logger 42177db96d56Sopenharmony_ci root.removeHandler(self.root_hdlr) 42187db96d56Sopenharmony_ci old_lastresort = logging.lastResort 42197db96d56Sopenharmony_ci old_raise_exceptions = logging.raiseExceptions 42207db96d56Sopenharmony_ci 42217db96d56Sopenharmony_ci try: 42227db96d56Sopenharmony_ci with support.captured_stderr() as stderr: 42237db96d56Sopenharmony_ci root.debug('This should not appear') 42247db96d56Sopenharmony_ci self.assertEqual(stderr.getvalue(), '') 42257db96d56Sopenharmony_ci root.warning('Final chance!') 42267db96d56Sopenharmony_ci self.assertEqual(stderr.getvalue(), 'Final chance!\n') 42277db96d56Sopenharmony_ci 42287db96d56Sopenharmony_ci # No handlers and no last resort, so 'No handlers' message 42297db96d56Sopenharmony_ci logging.lastResort = None 42307db96d56Sopenharmony_ci with support.captured_stderr() as stderr: 42317db96d56Sopenharmony_ci root.warning('Final chance!') 42327db96d56Sopenharmony_ci msg = 'No handlers could be found for logger "root"\n' 42337db96d56Sopenharmony_ci self.assertEqual(stderr.getvalue(), msg) 42347db96d56Sopenharmony_ci 42357db96d56Sopenharmony_ci # 'No handlers' message only printed once 42367db96d56Sopenharmony_ci with support.captured_stderr() as stderr: 42377db96d56Sopenharmony_ci root.warning('Final chance!') 42387db96d56Sopenharmony_ci self.assertEqual(stderr.getvalue(), '') 42397db96d56Sopenharmony_ci 42407db96d56Sopenharmony_ci # If raiseExceptions is False, no message is printed 42417db96d56Sopenharmony_ci root.manager.emittedNoHandlerWarning = False 42427db96d56Sopenharmony_ci logging.raiseExceptions = False 42437db96d56Sopenharmony_ci with support.captured_stderr() as stderr: 42447db96d56Sopenharmony_ci root.warning('Final chance!') 42457db96d56Sopenharmony_ci self.assertEqual(stderr.getvalue(), '') 42467db96d56Sopenharmony_ci finally: 42477db96d56Sopenharmony_ci root.addHandler(self.root_hdlr) 42487db96d56Sopenharmony_ci logging.lastResort = old_lastresort 42497db96d56Sopenharmony_ci logging.raiseExceptions = old_raise_exceptions 42507db96d56Sopenharmony_ci 42517db96d56Sopenharmony_ci 42527db96d56Sopenharmony_ciclass FakeHandler: 42537db96d56Sopenharmony_ci 42547db96d56Sopenharmony_ci def __init__(self, identifier, called): 42557db96d56Sopenharmony_ci for method in ('acquire', 'flush', 'close', 'release'): 42567db96d56Sopenharmony_ci setattr(self, method, self.record_call(identifier, method, called)) 42577db96d56Sopenharmony_ci 42587db96d56Sopenharmony_ci def record_call(self, identifier, method_name, called): 42597db96d56Sopenharmony_ci def inner(): 42607db96d56Sopenharmony_ci called.append('{} - {}'.format(identifier, method_name)) 42617db96d56Sopenharmony_ci return inner 42627db96d56Sopenharmony_ci 42637db96d56Sopenharmony_ci 42647db96d56Sopenharmony_ciclass RecordingHandler(logging.NullHandler): 42657db96d56Sopenharmony_ci 42667db96d56Sopenharmony_ci def __init__(self, *args, **kwargs): 42677db96d56Sopenharmony_ci super(RecordingHandler, self).__init__(*args, **kwargs) 42687db96d56Sopenharmony_ci self.records = [] 42697db96d56Sopenharmony_ci 42707db96d56Sopenharmony_ci def handle(self, record): 42717db96d56Sopenharmony_ci """Keep track of all the emitted records.""" 42727db96d56Sopenharmony_ci self.records.append(record) 42737db96d56Sopenharmony_ci 42747db96d56Sopenharmony_ci 42757db96d56Sopenharmony_ciclass ShutdownTest(BaseTest): 42767db96d56Sopenharmony_ci 42777db96d56Sopenharmony_ci """Test suite for the shutdown method.""" 42787db96d56Sopenharmony_ci 42797db96d56Sopenharmony_ci def setUp(self): 42807db96d56Sopenharmony_ci super(ShutdownTest, self).setUp() 42817db96d56Sopenharmony_ci self.called = [] 42827db96d56Sopenharmony_ci 42837db96d56Sopenharmony_ci raise_exceptions = logging.raiseExceptions 42847db96d56Sopenharmony_ci self.addCleanup(setattr, logging, 'raiseExceptions', raise_exceptions) 42857db96d56Sopenharmony_ci 42867db96d56Sopenharmony_ci def raise_error(self, error): 42877db96d56Sopenharmony_ci def inner(): 42887db96d56Sopenharmony_ci raise error() 42897db96d56Sopenharmony_ci return inner 42907db96d56Sopenharmony_ci 42917db96d56Sopenharmony_ci def test_no_failure(self): 42927db96d56Sopenharmony_ci # create some fake handlers 42937db96d56Sopenharmony_ci handler0 = FakeHandler(0, self.called) 42947db96d56Sopenharmony_ci handler1 = FakeHandler(1, self.called) 42957db96d56Sopenharmony_ci handler2 = FakeHandler(2, self.called) 42967db96d56Sopenharmony_ci 42977db96d56Sopenharmony_ci # create live weakref to those handlers 42987db96d56Sopenharmony_ci handlers = map(logging.weakref.ref, [handler0, handler1, handler2]) 42997db96d56Sopenharmony_ci 43007db96d56Sopenharmony_ci logging.shutdown(handlerList=list(handlers)) 43017db96d56Sopenharmony_ci 43027db96d56Sopenharmony_ci expected = ['2 - acquire', '2 - flush', '2 - close', '2 - release', 43037db96d56Sopenharmony_ci '1 - acquire', '1 - flush', '1 - close', '1 - release', 43047db96d56Sopenharmony_ci '0 - acquire', '0 - flush', '0 - close', '0 - release'] 43057db96d56Sopenharmony_ci self.assertEqual(expected, self.called) 43067db96d56Sopenharmony_ci 43077db96d56Sopenharmony_ci def _test_with_failure_in_method(self, method, error): 43087db96d56Sopenharmony_ci handler = FakeHandler(0, self.called) 43097db96d56Sopenharmony_ci setattr(handler, method, self.raise_error(error)) 43107db96d56Sopenharmony_ci handlers = [logging.weakref.ref(handler)] 43117db96d56Sopenharmony_ci 43127db96d56Sopenharmony_ci logging.shutdown(handlerList=list(handlers)) 43137db96d56Sopenharmony_ci 43147db96d56Sopenharmony_ci self.assertEqual('0 - release', self.called[-1]) 43157db96d56Sopenharmony_ci 43167db96d56Sopenharmony_ci def test_with_ioerror_in_acquire(self): 43177db96d56Sopenharmony_ci self._test_with_failure_in_method('acquire', OSError) 43187db96d56Sopenharmony_ci 43197db96d56Sopenharmony_ci def test_with_ioerror_in_flush(self): 43207db96d56Sopenharmony_ci self._test_with_failure_in_method('flush', OSError) 43217db96d56Sopenharmony_ci 43227db96d56Sopenharmony_ci def test_with_ioerror_in_close(self): 43237db96d56Sopenharmony_ci self._test_with_failure_in_method('close', OSError) 43247db96d56Sopenharmony_ci 43257db96d56Sopenharmony_ci def test_with_valueerror_in_acquire(self): 43267db96d56Sopenharmony_ci self._test_with_failure_in_method('acquire', ValueError) 43277db96d56Sopenharmony_ci 43287db96d56Sopenharmony_ci def test_with_valueerror_in_flush(self): 43297db96d56Sopenharmony_ci self._test_with_failure_in_method('flush', ValueError) 43307db96d56Sopenharmony_ci 43317db96d56Sopenharmony_ci def test_with_valueerror_in_close(self): 43327db96d56Sopenharmony_ci self._test_with_failure_in_method('close', ValueError) 43337db96d56Sopenharmony_ci 43347db96d56Sopenharmony_ci def test_with_other_error_in_acquire_without_raise(self): 43357db96d56Sopenharmony_ci logging.raiseExceptions = False 43367db96d56Sopenharmony_ci self._test_with_failure_in_method('acquire', IndexError) 43377db96d56Sopenharmony_ci 43387db96d56Sopenharmony_ci def test_with_other_error_in_flush_without_raise(self): 43397db96d56Sopenharmony_ci logging.raiseExceptions = False 43407db96d56Sopenharmony_ci self._test_with_failure_in_method('flush', IndexError) 43417db96d56Sopenharmony_ci 43427db96d56Sopenharmony_ci def test_with_other_error_in_close_without_raise(self): 43437db96d56Sopenharmony_ci logging.raiseExceptions = False 43447db96d56Sopenharmony_ci self._test_with_failure_in_method('close', IndexError) 43457db96d56Sopenharmony_ci 43467db96d56Sopenharmony_ci def test_with_other_error_in_acquire_with_raise(self): 43477db96d56Sopenharmony_ci logging.raiseExceptions = True 43487db96d56Sopenharmony_ci self.assertRaises(IndexError, self._test_with_failure_in_method, 43497db96d56Sopenharmony_ci 'acquire', IndexError) 43507db96d56Sopenharmony_ci 43517db96d56Sopenharmony_ci def test_with_other_error_in_flush_with_raise(self): 43527db96d56Sopenharmony_ci logging.raiseExceptions = True 43537db96d56Sopenharmony_ci self.assertRaises(IndexError, self._test_with_failure_in_method, 43547db96d56Sopenharmony_ci 'flush', IndexError) 43557db96d56Sopenharmony_ci 43567db96d56Sopenharmony_ci def test_with_other_error_in_close_with_raise(self): 43577db96d56Sopenharmony_ci logging.raiseExceptions = True 43587db96d56Sopenharmony_ci self.assertRaises(IndexError, self._test_with_failure_in_method, 43597db96d56Sopenharmony_ci 'close', IndexError) 43607db96d56Sopenharmony_ci 43617db96d56Sopenharmony_ci 43627db96d56Sopenharmony_ciclass ModuleLevelMiscTest(BaseTest): 43637db96d56Sopenharmony_ci 43647db96d56Sopenharmony_ci """Test suite for some module level methods.""" 43657db96d56Sopenharmony_ci 43667db96d56Sopenharmony_ci def test_disable(self): 43677db96d56Sopenharmony_ci old_disable = logging.root.manager.disable 43687db96d56Sopenharmony_ci # confirm our assumptions are correct 43697db96d56Sopenharmony_ci self.assertEqual(old_disable, 0) 43707db96d56Sopenharmony_ci self.addCleanup(logging.disable, old_disable) 43717db96d56Sopenharmony_ci 43727db96d56Sopenharmony_ci logging.disable(83) 43737db96d56Sopenharmony_ci self.assertEqual(logging.root.manager.disable, 83) 43747db96d56Sopenharmony_ci 43757db96d56Sopenharmony_ci self.assertRaises(ValueError, logging.disable, "doesnotexists") 43767db96d56Sopenharmony_ci 43777db96d56Sopenharmony_ci class _NotAnIntOrString: 43787db96d56Sopenharmony_ci pass 43797db96d56Sopenharmony_ci 43807db96d56Sopenharmony_ci self.assertRaises(TypeError, logging.disable, _NotAnIntOrString()) 43817db96d56Sopenharmony_ci 43827db96d56Sopenharmony_ci logging.disable("WARN") 43837db96d56Sopenharmony_ci 43847db96d56Sopenharmony_ci # test the default value introduced in 3.7 43857db96d56Sopenharmony_ci # (Issue #28524) 43867db96d56Sopenharmony_ci logging.disable() 43877db96d56Sopenharmony_ci self.assertEqual(logging.root.manager.disable, logging.CRITICAL) 43887db96d56Sopenharmony_ci 43897db96d56Sopenharmony_ci def _test_log(self, method, level=None): 43907db96d56Sopenharmony_ci called = [] 43917db96d56Sopenharmony_ci support.patch(self, logging, 'basicConfig', 43927db96d56Sopenharmony_ci lambda *a, **kw: called.append((a, kw))) 43937db96d56Sopenharmony_ci 43947db96d56Sopenharmony_ci recording = RecordingHandler() 43957db96d56Sopenharmony_ci logging.root.addHandler(recording) 43967db96d56Sopenharmony_ci 43977db96d56Sopenharmony_ci log_method = getattr(logging, method) 43987db96d56Sopenharmony_ci if level is not None: 43997db96d56Sopenharmony_ci log_method(level, "test me: %r", recording) 44007db96d56Sopenharmony_ci else: 44017db96d56Sopenharmony_ci log_method("test me: %r", recording) 44027db96d56Sopenharmony_ci 44037db96d56Sopenharmony_ci self.assertEqual(len(recording.records), 1) 44047db96d56Sopenharmony_ci record = recording.records[0] 44057db96d56Sopenharmony_ci self.assertEqual(record.getMessage(), "test me: %r" % recording) 44067db96d56Sopenharmony_ci 44077db96d56Sopenharmony_ci expected_level = level if level is not None else getattr(logging, method.upper()) 44087db96d56Sopenharmony_ci self.assertEqual(record.levelno, expected_level) 44097db96d56Sopenharmony_ci 44107db96d56Sopenharmony_ci # basicConfig was not called! 44117db96d56Sopenharmony_ci self.assertEqual(called, []) 44127db96d56Sopenharmony_ci 44137db96d56Sopenharmony_ci def test_log(self): 44147db96d56Sopenharmony_ci self._test_log('log', logging.ERROR) 44157db96d56Sopenharmony_ci 44167db96d56Sopenharmony_ci def test_debug(self): 44177db96d56Sopenharmony_ci self._test_log('debug') 44187db96d56Sopenharmony_ci 44197db96d56Sopenharmony_ci def test_info(self): 44207db96d56Sopenharmony_ci self._test_log('info') 44217db96d56Sopenharmony_ci 44227db96d56Sopenharmony_ci def test_warning(self): 44237db96d56Sopenharmony_ci self._test_log('warning') 44247db96d56Sopenharmony_ci 44257db96d56Sopenharmony_ci def test_error(self): 44267db96d56Sopenharmony_ci self._test_log('error') 44277db96d56Sopenharmony_ci 44287db96d56Sopenharmony_ci def test_critical(self): 44297db96d56Sopenharmony_ci self._test_log('critical') 44307db96d56Sopenharmony_ci 44317db96d56Sopenharmony_ci def test_set_logger_class(self): 44327db96d56Sopenharmony_ci self.assertRaises(TypeError, logging.setLoggerClass, object) 44337db96d56Sopenharmony_ci 44347db96d56Sopenharmony_ci class MyLogger(logging.Logger): 44357db96d56Sopenharmony_ci pass 44367db96d56Sopenharmony_ci 44377db96d56Sopenharmony_ci logging.setLoggerClass(MyLogger) 44387db96d56Sopenharmony_ci self.assertEqual(logging.getLoggerClass(), MyLogger) 44397db96d56Sopenharmony_ci 44407db96d56Sopenharmony_ci logging.setLoggerClass(logging.Logger) 44417db96d56Sopenharmony_ci self.assertEqual(logging.getLoggerClass(), logging.Logger) 44427db96d56Sopenharmony_ci 44437db96d56Sopenharmony_ci def test_subclass_logger_cache(self): 44447db96d56Sopenharmony_ci # bpo-37258 44457db96d56Sopenharmony_ci message = [] 44467db96d56Sopenharmony_ci 44477db96d56Sopenharmony_ci class MyLogger(logging.getLoggerClass()): 44487db96d56Sopenharmony_ci def __init__(self, name='MyLogger', level=logging.NOTSET): 44497db96d56Sopenharmony_ci super().__init__(name, level) 44507db96d56Sopenharmony_ci message.append('initialized') 44517db96d56Sopenharmony_ci 44527db96d56Sopenharmony_ci logging.setLoggerClass(MyLogger) 44537db96d56Sopenharmony_ci logger = logging.getLogger('just_some_logger') 44547db96d56Sopenharmony_ci self.assertEqual(message, ['initialized']) 44557db96d56Sopenharmony_ci stream = io.StringIO() 44567db96d56Sopenharmony_ci h = logging.StreamHandler(stream) 44577db96d56Sopenharmony_ci logger.addHandler(h) 44587db96d56Sopenharmony_ci try: 44597db96d56Sopenharmony_ci logger.setLevel(logging.DEBUG) 44607db96d56Sopenharmony_ci logger.debug("hello") 44617db96d56Sopenharmony_ci self.assertEqual(stream.getvalue().strip(), "hello") 44627db96d56Sopenharmony_ci 44637db96d56Sopenharmony_ci stream.truncate(0) 44647db96d56Sopenharmony_ci stream.seek(0) 44657db96d56Sopenharmony_ci 44667db96d56Sopenharmony_ci logger.setLevel(logging.INFO) 44677db96d56Sopenharmony_ci logger.debug("hello") 44687db96d56Sopenharmony_ci self.assertEqual(stream.getvalue(), "") 44697db96d56Sopenharmony_ci finally: 44707db96d56Sopenharmony_ci logger.removeHandler(h) 44717db96d56Sopenharmony_ci h.close() 44727db96d56Sopenharmony_ci logging.setLoggerClass(logging.Logger) 44737db96d56Sopenharmony_ci 44747db96d56Sopenharmony_ci def test_logging_at_shutdown(self): 44757db96d56Sopenharmony_ci # bpo-20037: Doing text I/O late at interpreter shutdown must not crash 44767db96d56Sopenharmony_ci code = textwrap.dedent(""" 44777db96d56Sopenharmony_ci import logging 44787db96d56Sopenharmony_ci 44797db96d56Sopenharmony_ci class A: 44807db96d56Sopenharmony_ci def __del__(self): 44817db96d56Sopenharmony_ci try: 44827db96d56Sopenharmony_ci raise ValueError("some error") 44837db96d56Sopenharmony_ci except Exception: 44847db96d56Sopenharmony_ci logging.exception("exception in __del__") 44857db96d56Sopenharmony_ci 44867db96d56Sopenharmony_ci a = A() 44877db96d56Sopenharmony_ci """) 44887db96d56Sopenharmony_ci rc, out, err = assert_python_ok("-c", code) 44897db96d56Sopenharmony_ci err = err.decode() 44907db96d56Sopenharmony_ci self.assertIn("exception in __del__", err) 44917db96d56Sopenharmony_ci self.assertIn("ValueError: some error", err) 44927db96d56Sopenharmony_ci 44937db96d56Sopenharmony_ci def test_logging_at_shutdown_open(self): 44947db96d56Sopenharmony_ci # bpo-26789: FileHandler keeps a reference to the builtin open() 44957db96d56Sopenharmony_ci # function to be able to open or reopen the file during Python 44967db96d56Sopenharmony_ci # finalization. 44977db96d56Sopenharmony_ci filename = os_helper.TESTFN 44987db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, filename) 44997db96d56Sopenharmony_ci 45007db96d56Sopenharmony_ci code = textwrap.dedent(f""" 45017db96d56Sopenharmony_ci import builtins 45027db96d56Sopenharmony_ci import logging 45037db96d56Sopenharmony_ci 45047db96d56Sopenharmony_ci class A: 45057db96d56Sopenharmony_ci def __del__(self): 45067db96d56Sopenharmony_ci logging.error("log in __del__") 45077db96d56Sopenharmony_ci 45087db96d56Sopenharmony_ci # basicConfig() opens the file, but logging.shutdown() closes 45097db96d56Sopenharmony_ci # it at Python exit. When A.__del__() is called, 45107db96d56Sopenharmony_ci # FileHandler._open() must be called again to re-open the file. 45117db96d56Sopenharmony_ci logging.basicConfig(filename={filename!r}, encoding="utf-8") 45127db96d56Sopenharmony_ci 45137db96d56Sopenharmony_ci a = A() 45147db96d56Sopenharmony_ci 45157db96d56Sopenharmony_ci # Simulate the Python finalization which removes the builtin 45167db96d56Sopenharmony_ci # open() function. 45177db96d56Sopenharmony_ci del builtins.open 45187db96d56Sopenharmony_ci """) 45197db96d56Sopenharmony_ci assert_python_ok("-c", code) 45207db96d56Sopenharmony_ci 45217db96d56Sopenharmony_ci with open(filename, encoding="utf-8") as fp: 45227db96d56Sopenharmony_ci self.assertEqual(fp.read().rstrip(), "ERROR:root:log in __del__") 45237db96d56Sopenharmony_ci 45247db96d56Sopenharmony_ci def test_recursion_error(self): 45257db96d56Sopenharmony_ci # Issue 36272 45267db96d56Sopenharmony_ci code = textwrap.dedent(""" 45277db96d56Sopenharmony_ci import logging 45287db96d56Sopenharmony_ci 45297db96d56Sopenharmony_ci def rec(): 45307db96d56Sopenharmony_ci logging.error("foo") 45317db96d56Sopenharmony_ci rec() 45327db96d56Sopenharmony_ci 45337db96d56Sopenharmony_ci rec() 45347db96d56Sopenharmony_ci """) 45357db96d56Sopenharmony_ci rc, out, err = assert_python_failure("-c", code) 45367db96d56Sopenharmony_ci err = err.decode() 45377db96d56Sopenharmony_ci self.assertNotIn("Cannot recover from stack overflow.", err) 45387db96d56Sopenharmony_ci self.assertEqual(rc, 1) 45397db96d56Sopenharmony_ci 45407db96d56Sopenharmony_ci def test_get_level_names_mapping(self): 45417db96d56Sopenharmony_ci mapping = logging.getLevelNamesMapping() 45427db96d56Sopenharmony_ci self.assertEqual(logging._nameToLevel, mapping) # value is equivalent 45437db96d56Sopenharmony_ci self.assertIsNot(logging._nameToLevel, mapping) # but not the internal data 45447db96d56Sopenharmony_ci new_mapping = logging.getLevelNamesMapping() # another call -> another copy 45457db96d56Sopenharmony_ci self.assertIsNot(mapping, new_mapping) # verify not the same object as before 45467db96d56Sopenharmony_ci self.assertEqual(mapping, new_mapping) # but equivalent in value 45477db96d56Sopenharmony_ci 45487db96d56Sopenharmony_ci 45497db96d56Sopenharmony_ciclass LogRecordTest(BaseTest): 45507db96d56Sopenharmony_ci def test_str_rep(self): 45517db96d56Sopenharmony_ci r = logging.makeLogRecord({}) 45527db96d56Sopenharmony_ci s = str(r) 45537db96d56Sopenharmony_ci self.assertTrue(s.startswith('<LogRecord: ')) 45547db96d56Sopenharmony_ci self.assertTrue(s.endswith('>')) 45557db96d56Sopenharmony_ci 45567db96d56Sopenharmony_ci def test_dict_arg(self): 45577db96d56Sopenharmony_ci h = RecordingHandler() 45587db96d56Sopenharmony_ci r = logging.getLogger() 45597db96d56Sopenharmony_ci r.addHandler(h) 45607db96d56Sopenharmony_ci d = {'less' : 'more' } 45617db96d56Sopenharmony_ci logging.warning('less is %(less)s', d) 45627db96d56Sopenharmony_ci self.assertIs(h.records[0].args, d) 45637db96d56Sopenharmony_ci self.assertEqual(h.records[0].message, 'less is more') 45647db96d56Sopenharmony_ci r.removeHandler(h) 45657db96d56Sopenharmony_ci h.close() 45667db96d56Sopenharmony_ci 45677db96d56Sopenharmony_ci @staticmethod # pickled as target of child process in the following test 45687db96d56Sopenharmony_ci def _extract_logrecord_process_name(key, logMultiprocessing, conn=None): 45697db96d56Sopenharmony_ci prev_logMultiprocessing = logging.logMultiprocessing 45707db96d56Sopenharmony_ci logging.logMultiprocessing = logMultiprocessing 45717db96d56Sopenharmony_ci try: 45727db96d56Sopenharmony_ci import multiprocessing as mp 45737db96d56Sopenharmony_ci name = mp.current_process().name 45747db96d56Sopenharmony_ci 45757db96d56Sopenharmony_ci r1 = logging.makeLogRecord({'msg': f'msg1_{key}'}) 45767db96d56Sopenharmony_ci 45777db96d56Sopenharmony_ci # https://bugs.python.org/issue45128 45787db96d56Sopenharmony_ci with support.swap_item(sys.modules, 'multiprocessing', None): 45797db96d56Sopenharmony_ci r2 = logging.makeLogRecord({'msg': f'msg2_{key}'}) 45807db96d56Sopenharmony_ci 45817db96d56Sopenharmony_ci results = {'processName' : name, 45827db96d56Sopenharmony_ci 'r1.processName': r1.processName, 45837db96d56Sopenharmony_ci 'r2.processName': r2.processName, 45847db96d56Sopenharmony_ci } 45857db96d56Sopenharmony_ci finally: 45867db96d56Sopenharmony_ci logging.logMultiprocessing = prev_logMultiprocessing 45877db96d56Sopenharmony_ci if conn: 45887db96d56Sopenharmony_ci conn.send(results) 45897db96d56Sopenharmony_ci else: 45907db96d56Sopenharmony_ci return results 45917db96d56Sopenharmony_ci 45927db96d56Sopenharmony_ci def test_multiprocessing(self): 45937db96d56Sopenharmony_ci support.skip_if_broken_multiprocessing_synchronize() 45947db96d56Sopenharmony_ci multiprocessing_imported = 'multiprocessing' in sys.modules 45957db96d56Sopenharmony_ci try: 45967db96d56Sopenharmony_ci # logMultiprocessing is True by default 45977db96d56Sopenharmony_ci self.assertEqual(logging.logMultiprocessing, True) 45987db96d56Sopenharmony_ci 45997db96d56Sopenharmony_ci LOG_MULTI_PROCESSING = True 46007db96d56Sopenharmony_ci # When logMultiprocessing == True: 46017db96d56Sopenharmony_ci # In the main process processName = 'MainProcess' 46027db96d56Sopenharmony_ci r = logging.makeLogRecord({}) 46037db96d56Sopenharmony_ci self.assertEqual(r.processName, 'MainProcess') 46047db96d56Sopenharmony_ci 46057db96d56Sopenharmony_ci results = self._extract_logrecord_process_name(1, LOG_MULTI_PROCESSING) 46067db96d56Sopenharmony_ci self.assertEqual('MainProcess', results['processName']) 46077db96d56Sopenharmony_ci self.assertEqual('MainProcess', results['r1.processName']) 46087db96d56Sopenharmony_ci self.assertEqual('MainProcess', results['r2.processName']) 46097db96d56Sopenharmony_ci 46107db96d56Sopenharmony_ci # In other processes, processName is correct when multiprocessing in imported, 46117db96d56Sopenharmony_ci # but it is (incorrectly) defaulted to 'MainProcess' otherwise (bpo-38762). 46127db96d56Sopenharmony_ci import multiprocessing 46137db96d56Sopenharmony_ci parent_conn, child_conn = multiprocessing.Pipe() 46147db96d56Sopenharmony_ci p = multiprocessing.Process( 46157db96d56Sopenharmony_ci target=self._extract_logrecord_process_name, 46167db96d56Sopenharmony_ci args=(2, LOG_MULTI_PROCESSING, child_conn,) 46177db96d56Sopenharmony_ci ) 46187db96d56Sopenharmony_ci p.start() 46197db96d56Sopenharmony_ci results = parent_conn.recv() 46207db96d56Sopenharmony_ci self.assertNotEqual('MainProcess', results['processName']) 46217db96d56Sopenharmony_ci self.assertEqual(results['processName'], results['r1.processName']) 46227db96d56Sopenharmony_ci self.assertEqual('MainProcess', results['r2.processName']) 46237db96d56Sopenharmony_ci p.join() 46247db96d56Sopenharmony_ci 46257db96d56Sopenharmony_ci finally: 46267db96d56Sopenharmony_ci if multiprocessing_imported: 46277db96d56Sopenharmony_ci import multiprocessing 46287db96d56Sopenharmony_ci 46297db96d56Sopenharmony_ci def test_optional(self): 46307db96d56Sopenharmony_ci r = logging.makeLogRecord({}) 46317db96d56Sopenharmony_ci NOT_NONE = self.assertIsNotNone 46327db96d56Sopenharmony_ci NOT_NONE(r.thread) 46337db96d56Sopenharmony_ci NOT_NONE(r.threadName) 46347db96d56Sopenharmony_ci NOT_NONE(r.process) 46357db96d56Sopenharmony_ci NOT_NONE(r.processName) 46367db96d56Sopenharmony_ci log_threads = logging.logThreads 46377db96d56Sopenharmony_ci log_processes = logging.logProcesses 46387db96d56Sopenharmony_ci log_multiprocessing = logging.logMultiprocessing 46397db96d56Sopenharmony_ci try: 46407db96d56Sopenharmony_ci logging.logThreads = False 46417db96d56Sopenharmony_ci logging.logProcesses = False 46427db96d56Sopenharmony_ci logging.logMultiprocessing = False 46437db96d56Sopenharmony_ci r = logging.makeLogRecord({}) 46447db96d56Sopenharmony_ci NONE = self.assertIsNone 46457db96d56Sopenharmony_ci NONE(r.thread) 46467db96d56Sopenharmony_ci NONE(r.threadName) 46477db96d56Sopenharmony_ci NONE(r.process) 46487db96d56Sopenharmony_ci NONE(r.processName) 46497db96d56Sopenharmony_ci finally: 46507db96d56Sopenharmony_ci logging.logThreads = log_threads 46517db96d56Sopenharmony_ci logging.logProcesses = log_processes 46527db96d56Sopenharmony_ci logging.logMultiprocessing = log_multiprocessing 46537db96d56Sopenharmony_ci 46547db96d56Sopenharmony_ciclass BasicConfigTest(unittest.TestCase): 46557db96d56Sopenharmony_ci 46567db96d56Sopenharmony_ci """Test suite for logging.basicConfig.""" 46577db96d56Sopenharmony_ci 46587db96d56Sopenharmony_ci def setUp(self): 46597db96d56Sopenharmony_ci super(BasicConfigTest, self).setUp() 46607db96d56Sopenharmony_ci self.handlers = logging.root.handlers 46617db96d56Sopenharmony_ci self.saved_handlers = logging._handlers.copy() 46627db96d56Sopenharmony_ci self.saved_handler_list = logging._handlerList[:] 46637db96d56Sopenharmony_ci self.original_logging_level = logging.root.level 46647db96d56Sopenharmony_ci self.addCleanup(self.cleanup) 46657db96d56Sopenharmony_ci logging.root.handlers = [] 46667db96d56Sopenharmony_ci 46677db96d56Sopenharmony_ci def tearDown(self): 46687db96d56Sopenharmony_ci for h in logging.root.handlers[:]: 46697db96d56Sopenharmony_ci logging.root.removeHandler(h) 46707db96d56Sopenharmony_ci h.close() 46717db96d56Sopenharmony_ci super(BasicConfigTest, self).tearDown() 46727db96d56Sopenharmony_ci 46737db96d56Sopenharmony_ci def cleanup(self): 46747db96d56Sopenharmony_ci setattr(logging.root, 'handlers', self.handlers) 46757db96d56Sopenharmony_ci logging._handlers.clear() 46767db96d56Sopenharmony_ci logging._handlers.update(self.saved_handlers) 46777db96d56Sopenharmony_ci logging._handlerList[:] = self.saved_handler_list 46787db96d56Sopenharmony_ci logging.root.setLevel(self.original_logging_level) 46797db96d56Sopenharmony_ci 46807db96d56Sopenharmony_ci def test_no_kwargs(self): 46817db96d56Sopenharmony_ci logging.basicConfig() 46827db96d56Sopenharmony_ci 46837db96d56Sopenharmony_ci # handler defaults to a StreamHandler to sys.stderr 46847db96d56Sopenharmony_ci self.assertEqual(len(logging.root.handlers), 1) 46857db96d56Sopenharmony_ci handler = logging.root.handlers[0] 46867db96d56Sopenharmony_ci self.assertIsInstance(handler, logging.StreamHandler) 46877db96d56Sopenharmony_ci self.assertEqual(handler.stream, sys.stderr) 46887db96d56Sopenharmony_ci 46897db96d56Sopenharmony_ci formatter = handler.formatter 46907db96d56Sopenharmony_ci # format defaults to logging.BASIC_FORMAT 46917db96d56Sopenharmony_ci self.assertEqual(formatter._style._fmt, logging.BASIC_FORMAT) 46927db96d56Sopenharmony_ci # datefmt defaults to None 46937db96d56Sopenharmony_ci self.assertIsNone(formatter.datefmt) 46947db96d56Sopenharmony_ci # style defaults to % 46957db96d56Sopenharmony_ci self.assertIsInstance(formatter._style, logging.PercentStyle) 46967db96d56Sopenharmony_ci 46977db96d56Sopenharmony_ci # level is not explicitly set 46987db96d56Sopenharmony_ci self.assertEqual(logging.root.level, self.original_logging_level) 46997db96d56Sopenharmony_ci 47007db96d56Sopenharmony_ci def test_strformatstyle(self): 47017db96d56Sopenharmony_ci with support.captured_stdout() as output: 47027db96d56Sopenharmony_ci logging.basicConfig(stream=sys.stdout, style="{") 47037db96d56Sopenharmony_ci logging.error("Log an error") 47047db96d56Sopenharmony_ci sys.stdout.seek(0) 47057db96d56Sopenharmony_ci self.assertEqual(output.getvalue().strip(), 47067db96d56Sopenharmony_ci "ERROR:root:Log an error") 47077db96d56Sopenharmony_ci 47087db96d56Sopenharmony_ci def test_stringtemplatestyle(self): 47097db96d56Sopenharmony_ci with support.captured_stdout() as output: 47107db96d56Sopenharmony_ci logging.basicConfig(stream=sys.stdout, style="$") 47117db96d56Sopenharmony_ci logging.error("Log an error") 47127db96d56Sopenharmony_ci sys.stdout.seek(0) 47137db96d56Sopenharmony_ci self.assertEqual(output.getvalue().strip(), 47147db96d56Sopenharmony_ci "ERROR:root:Log an error") 47157db96d56Sopenharmony_ci 47167db96d56Sopenharmony_ci def test_filename(self): 47177db96d56Sopenharmony_ci 47187db96d56Sopenharmony_ci def cleanup(h1, h2, fn): 47197db96d56Sopenharmony_ci h1.close() 47207db96d56Sopenharmony_ci h2.close() 47217db96d56Sopenharmony_ci os.remove(fn) 47227db96d56Sopenharmony_ci 47237db96d56Sopenharmony_ci logging.basicConfig(filename='test.log', encoding='utf-8') 47247db96d56Sopenharmony_ci 47257db96d56Sopenharmony_ci self.assertEqual(len(logging.root.handlers), 1) 47267db96d56Sopenharmony_ci handler = logging.root.handlers[0] 47277db96d56Sopenharmony_ci self.assertIsInstance(handler, logging.FileHandler) 47287db96d56Sopenharmony_ci 47297db96d56Sopenharmony_ci expected = logging.FileHandler('test.log', 'a', encoding='utf-8') 47307db96d56Sopenharmony_ci self.assertEqual(handler.stream.mode, expected.stream.mode) 47317db96d56Sopenharmony_ci self.assertEqual(handler.stream.name, expected.stream.name) 47327db96d56Sopenharmony_ci self.addCleanup(cleanup, handler, expected, 'test.log') 47337db96d56Sopenharmony_ci 47347db96d56Sopenharmony_ci def test_filemode(self): 47357db96d56Sopenharmony_ci 47367db96d56Sopenharmony_ci def cleanup(h1, h2, fn): 47377db96d56Sopenharmony_ci h1.close() 47387db96d56Sopenharmony_ci h2.close() 47397db96d56Sopenharmony_ci os.remove(fn) 47407db96d56Sopenharmony_ci 47417db96d56Sopenharmony_ci logging.basicConfig(filename='test.log', filemode='wb') 47427db96d56Sopenharmony_ci 47437db96d56Sopenharmony_ci handler = logging.root.handlers[0] 47447db96d56Sopenharmony_ci expected = logging.FileHandler('test.log', 'wb') 47457db96d56Sopenharmony_ci self.assertEqual(handler.stream.mode, expected.stream.mode) 47467db96d56Sopenharmony_ci self.addCleanup(cleanup, handler, expected, 'test.log') 47477db96d56Sopenharmony_ci 47487db96d56Sopenharmony_ci def test_stream(self): 47497db96d56Sopenharmony_ci stream = io.StringIO() 47507db96d56Sopenharmony_ci self.addCleanup(stream.close) 47517db96d56Sopenharmony_ci logging.basicConfig(stream=stream) 47527db96d56Sopenharmony_ci 47537db96d56Sopenharmony_ci self.assertEqual(len(logging.root.handlers), 1) 47547db96d56Sopenharmony_ci handler = logging.root.handlers[0] 47557db96d56Sopenharmony_ci self.assertIsInstance(handler, logging.StreamHandler) 47567db96d56Sopenharmony_ci self.assertEqual(handler.stream, stream) 47577db96d56Sopenharmony_ci 47587db96d56Sopenharmony_ci def test_format(self): 47597db96d56Sopenharmony_ci logging.basicConfig(format='%(asctime)s - %(message)s') 47607db96d56Sopenharmony_ci 47617db96d56Sopenharmony_ci formatter = logging.root.handlers[0].formatter 47627db96d56Sopenharmony_ci self.assertEqual(formatter._style._fmt, '%(asctime)s - %(message)s') 47637db96d56Sopenharmony_ci 47647db96d56Sopenharmony_ci def test_datefmt(self): 47657db96d56Sopenharmony_ci logging.basicConfig(datefmt='bar') 47667db96d56Sopenharmony_ci 47677db96d56Sopenharmony_ci formatter = logging.root.handlers[0].formatter 47687db96d56Sopenharmony_ci self.assertEqual(formatter.datefmt, 'bar') 47697db96d56Sopenharmony_ci 47707db96d56Sopenharmony_ci def test_style(self): 47717db96d56Sopenharmony_ci logging.basicConfig(style='$') 47727db96d56Sopenharmony_ci 47737db96d56Sopenharmony_ci formatter = logging.root.handlers[0].formatter 47747db96d56Sopenharmony_ci self.assertIsInstance(formatter._style, logging.StringTemplateStyle) 47757db96d56Sopenharmony_ci 47767db96d56Sopenharmony_ci def test_level(self): 47777db96d56Sopenharmony_ci old_level = logging.root.level 47787db96d56Sopenharmony_ci self.addCleanup(logging.root.setLevel, old_level) 47797db96d56Sopenharmony_ci 47807db96d56Sopenharmony_ci logging.basicConfig(level=57) 47817db96d56Sopenharmony_ci self.assertEqual(logging.root.level, 57) 47827db96d56Sopenharmony_ci # Test that second call has no effect 47837db96d56Sopenharmony_ci logging.basicConfig(level=58) 47847db96d56Sopenharmony_ci self.assertEqual(logging.root.level, 57) 47857db96d56Sopenharmony_ci 47867db96d56Sopenharmony_ci def test_incompatible(self): 47877db96d56Sopenharmony_ci assertRaises = self.assertRaises 47887db96d56Sopenharmony_ci handlers = [logging.StreamHandler()] 47897db96d56Sopenharmony_ci stream = sys.stderr 47907db96d56Sopenharmony_ci assertRaises(ValueError, logging.basicConfig, filename='test.log', 47917db96d56Sopenharmony_ci stream=stream) 47927db96d56Sopenharmony_ci assertRaises(ValueError, logging.basicConfig, filename='test.log', 47937db96d56Sopenharmony_ci handlers=handlers) 47947db96d56Sopenharmony_ci assertRaises(ValueError, logging.basicConfig, stream=stream, 47957db96d56Sopenharmony_ci handlers=handlers) 47967db96d56Sopenharmony_ci # Issue 23207: test for invalid kwargs 47977db96d56Sopenharmony_ci assertRaises(ValueError, logging.basicConfig, loglevel=logging.INFO) 47987db96d56Sopenharmony_ci # Should pop both filename and filemode even if filename is None 47997db96d56Sopenharmony_ci logging.basicConfig(filename=None, filemode='a') 48007db96d56Sopenharmony_ci 48017db96d56Sopenharmony_ci def test_handlers(self): 48027db96d56Sopenharmony_ci handlers = [ 48037db96d56Sopenharmony_ci logging.StreamHandler(), 48047db96d56Sopenharmony_ci logging.StreamHandler(sys.stdout), 48057db96d56Sopenharmony_ci logging.StreamHandler(), 48067db96d56Sopenharmony_ci ] 48077db96d56Sopenharmony_ci f = logging.Formatter() 48087db96d56Sopenharmony_ci handlers[2].setFormatter(f) 48097db96d56Sopenharmony_ci logging.basicConfig(handlers=handlers) 48107db96d56Sopenharmony_ci self.assertIs(handlers[0], logging.root.handlers[0]) 48117db96d56Sopenharmony_ci self.assertIs(handlers[1], logging.root.handlers[1]) 48127db96d56Sopenharmony_ci self.assertIs(handlers[2], logging.root.handlers[2]) 48137db96d56Sopenharmony_ci self.assertIsNotNone(handlers[0].formatter) 48147db96d56Sopenharmony_ci self.assertIsNotNone(handlers[1].formatter) 48157db96d56Sopenharmony_ci self.assertIs(handlers[2].formatter, f) 48167db96d56Sopenharmony_ci self.assertIs(handlers[0].formatter, handlers[1].formatter) 48177db96d56Sopenharmony_ci 48187db96d56Sopenharmony_ci def test_force(self): 48197db96d56Sopenharmony_ci old_string_io = io.StringIO() 48207db96d56Sopenharmony_ci new_string_io = io.StringIO() 48217db96d56Sopenharmony_ci old_handlers = [logging.StreamHandler(old_string_io)] 48227db96d56Sopenharmony_ci new_handlers = [logging.StreamHandler(new_string_io)] 48237db96d56Sopenharmony_ci logging.basicConfig(level=logging.WARNING, handlers=old_handlers) 48247db96d56Sopenharmony_ci logging.warning('warn') 48257db96d56Sopenharmony_ci logging.info('info') 48267db96d56Sopenharmony_ci logging.debug('debug') 48277db96d56Sopenharmony_ci self.assertEqual(len(logging.root.handlers), 1) 48287db96d56Sopenharmony_ci logging.basicConfig(level=logging.INFO, handlers=new_handlers, 48297db96d56Sopenharmony_ci force=True) 48307db96d56Sopenharmony_ci logging.warning('warn') 48317db96d56Sopenharmony_ci logging.info('info') 48327db96d56Sopenharmony_ci logging.debug('debug') 48337db96d56Sopenharmony_ci self.assertEqual(len(logging.root.handlers), 1) 48347db96d56Sopenharmony_ci self.assertEqual(old_string_io.getvalue().strip(), 48357db96d56Sopenharmony_ci 'WARNING:root:warn') 48367db96d56Sopenharmony_ci self.assertEqual(new_string_io.getvalue().strip(), 48377db96d56Sopenharmony_ci 'WARNING:root:warn\nINFO:root:info') 48387db96d56Sopenharmony_ci 48397db96d56Sopenharmony_ci def test_encoding(self): 48407db96d56Sopenharmony_ci try: 48417db96d56Sopenharmony_ci encoding = 'utf-8' 48427db96d56Sopenharmony_ci logging.basicConfig(filename='test.log', encoding=encoding, 48437db96d56Sopenharmony_ci errors='strict', 48447db96d56Sopenharmony_ci format='%(message)s', level=logging.DEBUG) 48457db96d56Sopenharmony_ci 48467db96d56Sopenharmony_ci self.assertEqual(len(logging.root.handlers), 1) 48477db96d56Sopenharmony_ci handler = logging.root.handlers[0] 48487db96d56Sopenharmony_ci self.assertIsInstance(handler, logging.FileHandler) 48497db96d56Sopenharmony_ci self.assertEqual(handler.encoding, encoding) 48507db96d56Sopenharmony_ci logging.debug('The Øresund Bridge joins Copenhagen to Malmö') 48517db96d56Sopenharmony_ci finally: 48527db96d56Sopenharmony_ci handler.close() 48537db96d56Sopenharmony_ci with open('test.log', encoding='utf-8') as f: 48547db96d56Sopenharmony_ci data = f.read().strip() 48557db96d56Sopenharmony_ci os.remove('test.log') 48567db96d56Sopenharmony_ci self.assertEqual(data, 48577db96d56Sopenharmony_ci 'The Øresund Bridge joins Copenhagen to Malmö') 48587db96d56Sopenharmony_ci 48597db96d56Sopenharmony_ci def test_encoding_errors(self): 48607db96d56Sopenharmony_ci try: 48617db96d56Sopenharmony_ci encoding = 'ascii' 48627db96d56Sopenharmony_ci logging.basicConfig(filename='test.log', encoding=encoding, 48637db96d56Sopenharmony_ci errors='ignore', 48647db96d56Sopenharmony_ci format='%(message)s', level=logging.DEBUG) 48657db96d56Sopenharmony_ci 48667db96d56Sopenharmony_ci self.assertEqual(len(logging.root.handlers), 1) 48677db96d56Sopenharmony_ci handler = logging.root.handlers[0] 48687db96d56Sopenharmony_ci self.assertIsInstance(handler, logging.FileHandler) 48697db96d56Sopenharmony_ci self.assertEqual(handler.encoding, encoding) 48707db96d56Sopenharmony_ci logging.debug('The Øresund Bridge joins Copenhagen to Malmö') 48717db96d56Sopenharmony_ci finally: 48727db96d56Sopenharmony_ci handler.close() 48737db96d56Sopenharmony_ci with open('test.log', encoding='utf-8') as f: 48747db96d56Sopenharmony_ci data = f.read().strip() 48757db96d56Sopenharmony_ci os.remove('test.log') 48767db96d56Sopenharmony_ci self.assertEqual(data, 'The resund Bridge joins Copenhagen to Malm') 48777db96d56Sopenharmony_ci 48787db96d56Sopenharmony_ci def test_encoding_errors_default(self): 48797db96d56Sopenharmony_ci try: 48807db96d56Sopenharmony_ci encoding = 'ascii' 48817db96d56Sopenharmony_ci logging.basicConfig(filename='test.log', encoding=encoding, 48827db96d56Sopenharmony_ci format='%(message)s', level=logging.DEBUG) 48837db96d56Sopenharmony_ci 48847db96d56Sopenharmony_ci self.assertEqual(len(logging.root.handlers), 1) 48857db96d56Sopenharmony_ci handler = logging.root.handlers[0] 48867db96d56Sopenharmony_ci self.assertIsInstance(handler, logging.FileHandler) 48877db96d56Sopenharmony_ci self.assertEqual(handler.encoding, encoding) 48887db96d56Sopenharmony_ci self.assertEqual(handler.errors, 'backslashreplace') 48897db96d56Sopenharmony_ci logging.debug(': ☃️: The Øresund Bridge joins Copenhagen to Malmö') 48907db96d56Sopenharmony_ci finally: 48917db96d56Sopenharmony_ci handler.close() 48927db96d56Sopenharmony_ci with open('test.log', encoding='utf-8') as f: 48937db96d56Sopenharmony_ci data = f.read().strip() 48947db96d56Sopenharmony_ci os.remove('test.log') 48957db96d56Sopenharmony_ci self.assertEqual(data, r'\U0001f602: \u2603\ufe0f: The \xd8resund ' 48967db96d56Sopenharmony_ci r'Bridge joins Copenhagen to Malm\xf6') 48977db96d56Sopenharmony_ci 48987db96d56Sopenharmony_ci def test_encoding_errors_none(self): 48997db96d56Sopenharmony_ci # Specifying None should behave as 'strict' 49007db96d56Sopenharmony_ci try: 49017db96d56Sopenharmony_ci encoding = 'ascii' 49027db96d56Sopenharmony_ci logging.basicConfig(filename='test.log', encoding=encoding, 49037db96d56Sopenharmony_ci errors=None, 49047db96d56Sopenharmony_ci format='%(message)s', level=logging.DEBUG) 49057db96d56Sopenharmony_ci 49067db96d56Sopenharmony_ci self.assertEqual(len(logging.root.handlers), 1) 49077db96d56Sopenharmony_ci handler = logging.root.handlers[0] 49087db96d56Sopenharmony_ci self.assertIsInstance(handler, logging.FileHandler) 49097db96d56Sopenharmony_ci self.assertEqual(handler.encoding, encoding) 49107db96d56Sopenharmony_ci self.assertIsNone(handler.errors) 49117db96d56Sopenharmony_ci 49127db96d56Sopenharmony_ci message = [] 49137db96d56Sopenharmony_ci 49147db96d56Sopenharmony_ci def dummy_handle_error(record): 49157db96d56Sopenharmony_ci _, v, _ = sys.exc_info() 49167db96d56Sopenharmony_ci message.append(str(v)) 49177db96d56Sopenharmony_ci 49187db96d56Sopenharmony_ci handler.handleError = dummy_handle_error 49197db96d56Sopenharmony_ci logging.debug('The Øresund Bridge joins Copenhagen to Malmö') 49207db96d56Sopenharmony_ci self.assertTrue(message) 49217db96d56Sopenharmony_ci self.assertIn("'ascii' codec can't encode " 49227db96d56Sopenharmony_ci "character '\\xd8' in position 4:", message[0]) 49237db96d56Sopenharmony_ci finally: 49247db96d56Sopenharmony_ci handler.close() 49257db96d56Sopenharmony_ci with open('test.log', encoding='utf-8') as f: 49267db96d56Sopenharmony_ci data = f.read().strip() 49277db96d56Sopenharmony_ci os.remove('test.log') 49287db96d56Sopenharmony_ci # didn't write anything due to the encoding error 49297db96d56Sopenharmony_ci self.assertEqual(data, r'') 49307db96d56Sopenharmony_ci 49317db96d56Sopenharmony_ci 49327db96d56Sopenharmony_ci def _test_log(self, method, level=None): 49337db96d56Sopenharmony_ci # logging.root has no handlers so basicConfig should be called 49347db96d56Sopenharmony_ci called = [] 49357db96d56Sopenharmony_ci 49367db96d56Sopenharmony_ci old_basic_config = logging.basicConfig 49377db96d56Sopenharmony_ci def my_basic_config(*a, **kw): 49387db96d56Sopenharmony_ci old_basic_config() 49397db96d56Sopenharmony_ci old_level = logging.root.level 49407db96d56Sopenharmony_ci logging.root.setLevel(100) # avoid having messages in stderr 49417db96d56Sopenharmony_ci self.addCleanup(logging.root.setLevel, old_level) 49427db96d56Sopenharmony_ci called.append((a, kw)) 49437db96d56Sopenharmony_ci 49447db96d56Sopenharmony_ci support.patch(self, logging, 'basicConfig', my_basic_config) 49457db96d56Sopenharmony_ci 49467db96d56Sopenharmony_ci log_method = getattr(logging, method) 49477db96d56Sopenharmony_ci if level is not None: 49487db96d56Sopenharmony_ci log_method(level, "test me") 49497db96d56Sopenharmony_ci else: 49507db96d56Sopenharmony_ci log_method("test me") 49517db96d56Sopenharmony_ci 49527db96d56Sopenharmony_ci # basicConfig was called with no arguments 49537db96d56Sopenharmony_ci self.assertEqual(called, [((), {})]) 49547db96d56Sopenharmony_ci 49557db96d56Sopenharmony_ci def test_log(self): 49567db96d56Sopenharmony_ci self._test_log('log', logging.WARNING) 49577db96d56Sopenharmony_ci 49587db96d56Sopenharmony_ci def test_debug(self): 49597db96d56Sopenharmony_ci self._test_log('debug') 49607db96d56Sopenharmony_ci 49617db96d56Sopenharmony_ci def test_info(self): 49627db96d56Sopenharmony_ci self._test_log('info') 49637db96d56Sopenharmony_ci 49647db96d56Sopenharmony_ci def test_warning(self): 49657db96d56Sopenharmony_ci self._test_log('warning') 49667db96d56Sopenharmony_ci 49677db96d56Sopenharmony_ci def test_error(self): 49687db96d56Sopenharmony_ci self._test_log('error') 49697db96d56Sopenharmony_ci 49707db96d56Sopenharmony_ci def test_critical(self): 49717db96d56Sopenharmony_ci self._test_log('critical') 49727db96d56Sopenharmony_ci 49737db96d56Sopenharmony_ci 49747db96d56Sopenharmony_ciclass LoggerAdapterTest(unittest.TestCase): 49757db96d56Sopenharmony_ci def setUp(self): 49767db96d56Sopenharmony_ci super(LoggerAdapterTest, self).setUp() 49777db96d56Sopenharmony_ci old_handler_list = logging._handlerList[:] 49787db96d56Sopenharmony_ci 49797db96d56Sopenharmony_ci self.recording = RecordingHandler() 49807db96d56Sopenharmony_ci self.logger = logging.root 49817db96d56Sopenharmony_ci self.logger.addHandler(self.recording) 49827db96d56Sopenharmony_ci self.addCleanup(self.logger.removeHandler, self.recording) 49837db96d56Sopenharmony_ci self.addCleanup(self.recording.close) 49847db96d56Sopenharmony_ci 49857db96d56Sopenharmony_ci def cleanup(): 49867db96d56Sopenharmony_ci logging._handlerList[:] = old_handler_list 49877db96d56Sopenharmony_ci 49887db96d56Sopenharmony_ci self.addCleanup(cleanup) 49897db96d56Sopenharmony_ci self.addCleanup(logging.shutdown) 49907db96d56Sopenharmony_ci self.adapter = logging.LoggerAdapter(logger=self.logger, extra=None) 49917db96d56Sopenharmony_ci 49927db96d56Sopenharmony_ci def test_exception(self): 49937db96d56Sopenharmony_ci msg = 'testing exception: %r' 49947db96d56Sopenharmony_ci exc = None 49957db96d56Sopenharmony_ci try: 49967db96d56Sopenharmony_ci 1 / 0 49977db96d56Sopenharmony_ci except ZeroDivisionError as e: 49987db96d56Sopenharmony_ci exc = e 49997db96d56Sopenharmony_ci self.adapter.exception(msg, self.recording) 50007db96d56Sopenharmony_ci 50017db96d56Sopenharmony_ci self.assertEqual(len(self.recording.records), 1) 50027db96d56Sopenharmony_ci record = self.recording.records[0] 50037db96d56Sopenharmony_ci self.assertEqual(record.levelno, logging.ERROR) 50047db96d56Sopenharmony_ci self.assertEqual(record.msg, msg) 50057db96d56Sopenharmony_ci self.assertEqual(record.args, (self.recording,)) 50067db96d56Sopenharmony_ci self.assertEqual(record.exc_info, 50077db96d56Sopenharmony_ci (exc.__class__, exc, exc.__traceback__)) 50087db96d56Sopenharmony_ci 50097db96d56Sopenharmony_ci def test_exception_excinfo(self): 50107db96d56Sopenharmony_ci try: 50117db96d56Sopenharmony_ci 1 / 0 50127db96d56Sopenharmony_ci except ZeroDivisionError as e: 50137db96d56Sopenharmony_ci exc = e 50147db96d56Sopenharmony_ci 50157db96d56Sopenharmony_ci self.adapter.exception('exc_info test', exc_info=exc) 50167db96d56Sopenharmony_ci 50177db96d56Sopenharmony_ci self.assertEqual(len(self.recording.records), 1) 50187db96d56Sopenharmony_ci record = self.recording.records[0] 50197db96d56Sopenharmony_ci self.assertEqual(record.exc_info, 50207db96d56Sopenharmony_ci (exc.__class__, exc, exc.__traceback__)) 50217db96d56Sopenharmony_ci 50227db96d56Sopenharmony_ci def test_critical(self): 50237db96d56Sopenharmony_ci msg = 'critical test! %r' 50247db96d56Sopenharmony_ci self.adapter.critical(msg, self.recording) 50257db96d56Sopenharmony_ci 50267db96d56Sopenharmony_ci self.assertEqual(len(self.recording.records), 1) 50277db96d56Sopenharmony_ci record = self.recording.records[0] 50287db96d56Sopenharmony_ci self.assertEqual(record.levelno, logging.CRITICAL) 50297db96d56Sopenharmony_ci self.assertEqual(record.msg, msg) 50307db96d56Sopenharmony_ci self.assertEqual(record.args, (self.recording,)) 50317db96d56Sopenharmony_ci 50327db96d56Sopenharmony_ci def test_is_enabled_for(self): 50337db96d56Sopenharmony_ci old_disable = self.adapter.logger.manager.disable 50347db96d56Sopenharmony_ci self.adapter.logger.manager.disable = 33 50357db96d56Sopenharmony_ci self.addCleanup(setattr, self.adapter.logger.manager, 'disable', 50367db96d56Sopenharmony_ci old_disable) 50377db96d56Sopenharmony_ci self.assertFalse(self.adapter.isEnabledFor(32)) 50387db96d56Sopenharmony_ci 50397db96d56Sopenharmony_ci def test_has_handlers(self): 50407db96d56Sopenharmony_ci self.assertTrue(self.adapter.hasHandlers()) 50417db96d56Sopenharmony_ci 50427db96d56Sopenharmony_ci for handler in self.logger.handlers: 50437db96d56Sopenharmony_ci self.logger.removeHandler(handler) 50447db96d56Sopenharmony_ci 50457db96d56Sopenharmony_ci self.assertFalse(self.logger.hasHandlers()) 50467db96d56Sopenharmony_ci self.assertFalse(self.adapter.hasHandlers()) 50477db96d56Sopenharmony_ci 50487db96d56Sopenharmony_ci def test_nested(self): 50497db96d56Sopenharmony_ci class Adapter(logging.LoggerAdapter): 50507db96d56Sopenharmony_ci prefix = 'Adapter' 50517db96d56Sopenharmony_ci 50527db96d56Sopenharmony_ci def process(self, msg, kwargs): 50537db96d56Sopenharmony_ci return f"{self.prefix} {msg}", kwargs 50547db96d56Sopenharmony_ci 50557db96d56Sopenharmony_ci msg = 'Adapters can be nested, yo.' 50567db96d56Sopenharmony_ci adapter = Adapter(logger=self.logger, extra=None) 50577db96d56Sopenharmony_ci adapter_adapter = Adapter(logger=adapter, extra=None) 50587db96d56Sopenharmony_ci adapter_adapter.prefix = 'AdapterAdapter' 50597db96d56Sopenharmony_ci self.assertEqual(repr(adapter), repr(adapter_adapter)) 50607db96d56Sopenharmony_ci adapter_adapter.log(logging.CRITICAL, msg, self.recording) 50617db96d56Sopenharmony_ci self.assertEqual(len(self.recording.records), 1) 50627db96d56Sopenharmony_ci record = self.recording.records[0] 50637db96d56Sopenharmony_ci self.assertEqual(record.levelno, logging.CRITICAL) 50647db96d56Sopenharmony_ci self.assertEqual(record.msg, f"Adapter AdapterAdapter {msg}") 50657db96d56Sopenharmony_ci self.assertEqual(record.args, (self.recording,)) 50667db96d56Sopenharmony_ci orig_manager = adapter_adapter.manager 50677db96d56Sopenharmony_ci self.assertIs(adapter.manager, orig_manager) 50687db96d56Sopenharmony_ci self.assertIs(self.logger.manager, orig_manager) 50697db96d56Sopenharmony_ci temp_manager = object() 50707db96d56Sopenharmony_ci try: 50717db96d56Sopenharmony_ci adapter_adapter.manager = temp_manager 50727db96d56Sopenharmony_ci self.assertIs(adapter_adapter.manager, temp_manager) 50737db96d56Sopenharmony_ci self.assertIs(adapter.manager, temp_manager) 50747db96d56Sopenharmony_ci self.assertIs(self.logger.manager, temp_manager) 50757db96d56Sopenharmony_ci finally: 50767db96d56Sopenharmony_ci adapter_adapter.manager = orig_manager 50777db96d56Sopenharmony_ci self.assertIs(adapter_adapter.manager, orig_manager) 50787db96d56Sopenharmony_ci self.assertIs(adapter.manager, orig_manager) 50797db96d56Sopenharmony_ci self.assertIs(self.logger.manager, orig_manager) 50807db96d56Sopenharmony_ci 50817db96d56Sopenharmony_ci 50827db96d56Sopenharmony_ciclass LoggerTest(BaseTest, AssertErrorMessage): 50837db96d56Sopenharmony_ci 50847db96d56Sopenharmony_ci def setUp(self): 50857db96d56Sopenharmony_ci super(LoggerTest, self).setUp() 50867db96d56Sopenharmony_ci self.recording = RecordingHandler() 50877db96d56Sopenharmony_ci self.logger = logging.Logger(name='blah') 50887db96d56Sopenharmony_ci self.logger.addHandler(self.recording) 50897db96d56Sopenharmony_ci self.addCleanup(self.logger.removeHandler, self.recording) 50907db96d56Sopenharmony_ci self.addCleanup(self.recording.close) 50917db96d56Sopenharmony_ci self.addCleanup(logging.shutdown) 50927db96d56Sopenharmony_ci 50937db96d56Sopenharmony_ci def test_set_invalid_level(self): 50947db96d56Sopenharmony_ci self.assert_error_message( 50957db96d56Sopenharmony_ci TypeError, 'Level not an integer or a valid string: None', 50967db96d56Sopenharmony_ci self.logger.setLevel, None) 50977db96d56Sopenharmony_ci self.assert_error_message( 50987db96d56Sopenharmony_ci TypeError, 'Level not an integer or a valid string: (0, 0)', 50997db96d56Sopenharmony_ci self.logger.setLevel, (0, 0)) 51007db96d56Sopenharmony_ci 51017db96d56Sopenharmony_ci def test_exception(self): 51027db96d56Sopenharmony_ci msg = 'testing exception: %r' 51037db96d56Sopenharmony_ci exc = None 51047db96d56Sopenharmony_ci try: 51057db96d56Sopenharmony_ci 1 / 0 51067db96d56Sopenharmony_ci except ZeroDivisionError as e: 51077db96d56Sopenharmony_ci exc = e 51087db96d56Sopenharmony_ci self.logger.exception(msg, self.recording) 51097db96d56Sopenharmony_ci 51107db96d56Sopenharmony_ci self.assertEqual(len(self.recording.records), 1) 51117db96d56Sopenharmony_ci record = self.recording.records[0] 51127db96d56Sopenharmony_ci self.assertEqual(record.levelno, logging.ERROR) 51137db96d56Sopenharmony_ci self.assertEqual(record.msg, msg) 51147db96d56Sopenharmony_ci self.assertEqual(record.args, (self.recording,)) 51157db96d56Sopenharmony_ci self.assertEqual(record.exc_info, 51167db96d56Sopenharmony_ci (exc.__class__, exc, exc.__traceback__)) 51177db96d56Sopenharmony_ci 51187db96d56Sopenharmony_ci def test_log_invalid_level_with_raise(self): 51197db96d56Sopenharmony_ci with support.swap_attr(logging, 'raiseExceptions', True): 51207db96d56Sopenharmony_ci self.assertRaises(TypeError, self.logger.log, '10', 'test message') 51217db96d56Sopenharmony_ci 51227db96d56Sopenharmony_ci def test_log_invalid_level_no_raise(self): 51237db96d56Sopenharmony_ci with support.swap_attr(logging, 'raiseExceptions', False): 51247db96d56Sopenharmony_ci self.logger.log('10', 'test message') # no exception happens 51257db96d56Sopenharmony_ci 51267db96d56Sopenharmony_ci def test_find_caller_with_stack_info(self): 51277db96d56Sopenharmony_ci called = [] 51287db96d56Sopenharmony_ci support.patch(self, logging.traceback, 'print_stack', 51297db96d56Sopenharmony_ci lambda f, file: called.append(file.getvalue())) 51307db96d56Sopenharmony_ci 51317db96d56Sopenharmony_ci self.logger.findCaller(stack_info=True) 51327db96d56Sopenharmony_ci 51337db96d56Sopenharmony_ci self.assertEqual(len(called), 1) 51347db96d56Sopenharmony_ci self.assertEqual('Stack (most recent call last):\n', called[0]) 51357db96d56Sopenharmony_ci 51367db96d56Sopenharmony_ci def test_find_caller_with_stacklevel(self): 51377db96d56Sopenharmony_ci the_level = 1 51387db96d56Sopenharmony_ci trigger = self.logger.warning 51397db96d56Sopenharmony_ci 51407db96d56Sopenharmony_ci def innermost(): 51417db96d56Sopenharmony_ci trigger('test', stacklevel=the_level) 51427db96d56Sopenharmony_ci 51437db96d56Sopenharmony_ci def inner(): 51447db96d56Sopenharmony_ci innermost() 51457db96d56Sopenharmony_ci 51467db96d56Sopenharmony_ci def outer(): 51477db96d56Sopenharmony_ci inner() 51487db96d56Sopenharmony_ci 51497db96d56Sopenharmony_ci records = self.recording.records 51507db96d56Sopenharmony_ci outer() 51517db96d56Sopenharmony_ci self.assertEqual(records[-1].funcName, 'innermost') 51527db96d56Sopenharmony_ci lineno = records[-1].lineno 51537db96d56Sopenharmony_ci the_level += 1 51547db96d56Sopenharmony_ci outer() 51557db96d56Sopenharmony_ci self.assertEqual(records[-1].funcName, 'inner') 51567db96d56Sopenharmony_ci self.assertGreater(records[-1].lineno, lineno) 51577db96d56Sopenharmony_ci lineno = records[-1].lineno 51587db96d56Sopenharmony_ci the_level += 1 51597db96d56Sopenharmony_ci outer() 51607db96d56Sopenharmony_ci self.assertEqual(records[-1].funcName, 'outer') 51617db96d56Sopenharmony_ci self.assertGreater(records[-1].lineno, lineno) 51627db96d56Sopenharmony_ci lineno = records[-1].lineno 51637db96d56Sopenharmony_ci root_logger = logging.getLogger() 51647db96d56Sopenharmony_ci root_logger.addHandler(self.recording) 51657db96d56Sopenharmony_ci trigger = logging.warning 51667db96d56Sopenharmony_ci outer() 51677db96d56Sopenharmony_ci self.assertEqual(records[-1].funcName, 'outer') 51687db96d56Sopenharmony_ci root_logger.removeHandler(self.recording) 51697db96d56Sopenharmony_ci trigger = self.logger.warning 51707db96d56Sopenharmony_ci the_level += 1 51717db96d56Sopenharmony_ci outer() 51727db96d56Sopenharmony_ci self.assertEqual(records[-1].funcName, 'test_find_caller_with_stacklevel') 51737db96d56Sopenharmony_ci self.assertGreater(records[-1].lineno, lineno) 51747db96d56Sopenharmony_ci 51757db96d56Sopenharmony_ci def test_make_record_with_extra_overwrite(self): 51767db96d56Sopenharmony_ci name = 'my record' 51777db96d56Sopenharmony_ci level = 13 51787db96d56Sopenharmony_ci fn = lno = msg = args = exc_info = func = sinfo = None 51797db96d56Sopenharmony_ci rv = logging._logRecordFactory(name, level, fn, lno, msg, args, 51807db96d56Sopenharmony_ci exc_info, func, sinfo) 51817db96d56Sopenharmony_ci 51827db96d56Sopenharmony_ci for key in ('message', 'asctime') + tuple(rv.__dict__.keys()): 51837db96d56Sopenharmony_ci extra = {key: 'some value'} 51847db96d56Sopenharmony_ci self.assertRaises(KeyError, self.logger.makeRecord, name, level, 51857db96d56Sopenharmony_ci fn, lno, msg, args, exc_info, 51867db96d56Sopenharmony_ci extra=extra, sinfo=sinfo) 51877db96d56Sopenharmony_ci 51887db96d56Sopenharmony_ci def test_make_record_with_extra_no_overwrite(self): 51897db96d56Sopenharmony_ci name = 'my record' 51907db96d56Sopenharmony_ci level = 13 51917db96d56Sopenharmony_ci fn = lno = msg = args = exc_info = func = sinfo = None 51927db96d56Sopenharmony_ci extra = {'valid_key': 'some value'} 51937db96d56Sopenharmony_ci result = self.logger.makeRecord(name, level, fn, lno, msg, args, 51947db96d56Sopenharmony_ci exc_info, extra=extra, sinfo=sinfo) 51957db96d56Sopenharmony_ci self.assertIn('valid_key', result.__dict__) 51967db96d56Sopenharmony_ci 51977db96d56Sopenharmony_ci def test_has_handlers(self): 51987db96d56Sopenharmony_ci self.assertTrue(self.logger.hasHandlers()) 51997db96d56Sopenharmony_ci 52007db96d56Sopenharmony_ci for handler in self.logger.handlers: 52017db96d56Sopenharmony_ci self.logger.removeHandler(handler) 52027db96d56Sopenharmony_ci self.assertFalse(self.logger.hasHandlers()) 52037db96d56Sopenharmony_ci 52047db96d56Sopenharmony_ci def test_has_handlers_no_propagate(self): 52057db96d56Sopenharmony_ci child_logger = logging.getLogger('blah.child') 52067db96d56Sopenharmony_ci child_logger.propagate = False 52077db96d56Sopenharmony_ci self.assertFalse(child_logger.hasHandlers()) 52087db96d56Sopenharmony_ci 52097db96d56Sopenharmony_ci def test_is_enabled_for(self): 52107db96d56Sopenharmony_ci old_disable = self.logger.manager.disable 52117db96d56Sopenharmony_ci self.logger.manager.disable = 23 52127db96d56Sopenharmony_ci self.addCleanup(setattr, self.logger.manager, 'disable', old_disable) 52137db96d56Sopenharmony_ci self.assertFalse(self.logger.isEnabledFor(22)) 52147db96d56Sopenharmony_ci 52157db96d56Sopenharmony_ci def test_is_enabled_for_disabled_logger(self): 52167db96d56Sopenharmony_ci old_disabled = self.logger.disabled 52177db96d56Sopenharmony_ci old_disable = self.logger.manager.disable 52187db96d56Sopenharmony_ci 52197db96d56Sopenharmony_ci self.logger.disabled = True 52207db96d56Sopenharmony_ci self.logger.manager.disable = 21 52217db96d56Sopenharmony_ci 52227db96d56Sopenharmony_ci self.addCleanup(setattr, self.logger, 'disabled', old_disabled) 52237db96d56Sopenharmony_ci self.addCleanup(setattr, self.logger.manager, 'disable', old_disable) 52247db96d56Sopenharmony_ci 52257db96d56Sopenharmony_ci self.assertFalse(self.logger.isEnabledFor(22)) 52267db96d56Sopenharmony_ci 52277db96d56Sopenharmony_ci def test_root_logger_aliases(self): 52287db96d56Sopenharmony_ci root = logging.getLogger() 52297db96d56Sopenharmony_ci self.assertIs(root, logging.root) 52307db96d56Sopenharmony_ci self.assertIs(root, logging.getLogger(None)) 52317db96d56Sopenharmony_ci self.assertIs(root, logging.getLogger('')) 52327db96d56Sopenharmony_ci self.assertIs(root, logging.getLogger('root')) 52337db96d56Sopenharmony_ci self.assertIs(root, logging.getLogger('foo').root) 52347db96d56Sopenharmony_ci self.assertIs(root, logging.getLogger('foo.bar').root) 52357db96d56Sopenharmony_ci self.assertIs(root, logging.getLogger('foo').parent) 52367db96d56Sopenharmony_ci 52377db96d56Sopenharmony_ci self.assertIsNot(root, logging.getLogger('\0')) 52387db96d56Sopenharmony_ci self.assertIsNot(root, logging.getLogger('foo.bar').parent) 52397db96d56Sopenharmony_ci 52407db96d56Sopenharmony_ci def test_invalid_names(self): 52417db96d56Sopenharmony_ci self.assertRaises(TypeError, logging.getLogger, any) 52427db96d56Sopenharmony_ci self.assertRaises(TypeError, logging.getLogger, b'foo') 52437db96d56Sopenharmony_ci 52447db96d56Sopenharmony_ci def test_pickling(self): 52457db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 52467db96d56Sopenharmony_ci for name in ('', 'root', 'foo', 'foo.bar', 'baz.bar'): 52477db96d56Sopenharmony_ci logger = logging.getLogger(name) 52487db96d56Sopenharmony_ci s = pickle.dumps(logger, proto) 52497db96d56Sopenharmony_ci unpickled = pickle.loads(s) 52507db96d56Sopenharmony_ci self.assertIs(unpickled, logger) 52517db96d56Sopenharmony_ci 52527db96d56Sopenharmony_ci def test_caching(self): 52537db96d56Sopenharmony_ci root = self.root_logger 52547db96d56Sopenharmony_ci logger1 = logging.getLogger("abc") 52557db96d56Sopenharmony_ci logger2 = logging.getLogger("abc.def") 52567db96d56Sopenharmony_ci 52577db96d56Sopenharmony_ci # Set root logger level and ensure cache is empty 52587db96d56Sopenharmony_ci root.setLevel(logging.ERROR) 52597db96d56Sopenharmony_ci self.assertEqual(logger2.getEffectiveLevel(), logging.ERROR) 52607db96d56Sopenharmony_ci self.assertEqual(logger2._cache, {}) 52617db96d56Sopenharmony_ci 52627db96d56Sopenharmony_ci # Ensure cache is populated and calls are consistent 52637db96d56Sopenharmony_ci self.assertTrue(logger2.isEnabledFor(logging.ERROR)) 52647db96d56Sopenharmony_ci self.assertFalse(logger2.isEnabledFor(logging.DEBUG)) 52657db96d56Sopenharmony_ci self.assertEqual(logger2._cache, {logging.ERROR: True, logging.DEBUG: False}) 52667db96d56Sopenharmony_ci self.assertEqual(root._cache, {}) 52677db96d56Sopenharmony_ci self.assertTrue(logger2.isEnabledFor(logging.ERROR)) 52687db96d56Sopenharmony_ci 52697db96d56Sopenharmony_ci # Ensure root cache gets populated 52707db96d56Sopenharmony_ci self.assertEqual(root._cache, {}) 52717db96d56Sopenharmony_ci self.assertTrue(root.isEnabledFor(logging.ERROR)) 52727db96d56Sopenharmony_ci self.assertEqual(root._cache, {logging.ERROR: True}) 52737db96d56Sopenharmony_ci 52747db96d56Sopenharmony_ci # Set parent logger level and ensure caches are emptied 52757db96d56Sopenharmony_ci logger1.setLevel(logging.CRITICAL) 52767db96d56Sopenharmony_ci self.assertEqual(logger2.getEffectiveLevel(), logging.CRITICAL) 52777db96d56Sopenharmony_ci self.assertEqual(logger2._cache, {}) 52787db96d56Sopenharmony_ci 52797db96d56Sopenharmony_ci # Ensure logger2 uses parent logger's effective level 52807db96d56Sopenharmony_ci self.assertFalse(logger2.isEnabledFor(logging.ERROR)) 52817db96d56Sopenharmony_ci 52827db96d56Sopenharmony_ci # Set level to NOTSET and ensure caches are empty 52837db96d56Sopenharmony_ci logger2.setLevel(logging.NOTSET) 52847db96d56Sopenharmony_ci self.assertEqual(logger2.getEffectiveLevel(), logging.CRITICAL) 52857db96d56Sopenharmony_ci self.assertEqual(logger2._cache, {}) 52867db96d56Sopenharmony_ci self.assertEqual(logger1._cache, {}) 52877db96d56Sopenharmony_ci self.assertEqual(root._cache, {}) 52887db96d56Sopenharmony_ci 52897db96d56Sopenharmony_ci # Verify logger2 follows parent and not root 52907db96d56Sopenharmony_ci self.assertFalse(logger2.isEnabledFor(logging.ERROR)) 52917db96d56Sopenharmony_ci self.assertTrue(logger2.isEnabledFor(logging.CRITICAL)) 52927db96d56Sopenharmony_ci self.assertFalse(logger1.isEnabledFor(logging.ERROR)) 52937db96d56Sopenharmony_ci self.assertTrue(logger1.isEnabledFor(logging.CRITICAL)) 52947db96d56Sopenharmony_ci self.assertTrue(root.isEnabledFor(logging.ERROR)) 52957db96d56Sopenharmony_ci 52967db96d56Sopenharmony_ci # Disable logging in manager and ensure caches are clear 52977db96d56Sopenharmony_ci logging.disable() 52987db96d56Sopenharmony_ci self.assertEqual(logger2.getEffectiveLevel(), logging.CRITICAL) 52997db96d56Sopenharmony_ci self.assertEqual(logger2._cache, {}) 53007db96d56Sopenharmony_ci self.assertEqual(logger1._cache, {}) 53017db96d56Sopenharmony_ci self.assertEqual(root._cache, {}) 53027db96d56Sopenharmony_ci 53037db96d56Sopenharmony_ci # Ensure no loggers are enabled 53047db96d56Sopenharmony_ci self.assertFalse(logger1.isEnabledFor(logging.CRITICAL)) 53057db96d56Sopenharmony_ci self.assertFalse(logger2.isEnabledFor(logging.CRITICAL)) 53067db96d56Sopenharmony_ci self.assertFalse(root.isEnabledFor(logging.CRITICAL)) 53077db96d56Sopenharmony_ci 53087db96d56Sopenharmony_ci 53097db96d56Sopenharmony_ciclass BaseFileTest(BaseTest): 53107db96d56Sopenharmony_ci "Base class for handler tests that write log files" 53117db96d56Sopenharmony_ci 53127db96d56Sopenharmony_ci def setUp(self): 53137db96d56Sopenharmony_ci BaseTest.setUp(self) 53147db96d56Sopenharmony_ci fd, self.fn = tempfile.mkstemp(".log", "test_logging-2-") 53157db96d56Sopenharmony_ci os.close(fd) 53167db96d56Sopenharmony_ci self.rmfiles = [] 53177db96d56Sopenharmony_ci 53187db96d56Sopenharmony_ci def tearDown(self): 53197db96d56Sopenharmony_ci for fn in self.rmfiles: 53207db96d56Sopenharmony_ci os.unlink(fn) 53217db96d56Sopenharmony_ci if os.path.exists(self.fn): 53227db96d56Sopenharmony_ci os.unlink(self.fn) 53237db96d56Sopenharmony_ci BaseTest.tearDown(self) 53247db96d56Sopenharmony_ci 53257db96d56Sopenharmony_ci def assertLogFile(self, filename): 53267db96d56Sopenharmony_ci "Assert a log file is there and register it for deletion" 53277db96d56Sopenharmony_ci self.assertTrue(os.path.exists(filename), 53287db96d56Sopenharmony_ci msg="Log file %r does not exist" % filename) 53297db96d56Sopenharmony_ci self.rmfiles.append(filename) 53307db96d56Sopenharmony_ci 53317db96d56Sopenharmony_ci def next_rec(self): 53327db96d56Sopenharmony_ci return logging.LogRecord('n', logging.DEBUG, 'p', 1, 53337db96d56Sopenharmony_ci self.next_message(), None, None, None) 53347db96d56Sopenharmony_ci 53357db96d56Sopenharmony_ciclass FileHandlerTest(BaseFileTest): 53367db96d56Sopenharmony_ci def test_delay(self): 53377db96d56Sopenharmony_ci os.unlink(self.fn) 53387db96d56Sopenharmony_ci fh = logging.FileHandler(self.fn, encoding='utf-8', delay=True) 53397db96d56Sopenharmony_ci self.assertIsNone(fh.stream) 53407db96d56Sopenharmony_ci self.assertFalse(os.path.exists(self.fn)) 53417db96d56Sopenharmony_ci fh.handle(logging.makeLogRecord({})) 53427db96d56Sopenharmony_ci self.assertIsNotNone(fh.stream) 53437db96d56Sopenharmony_ci self.assertTrue(os.path.exists(self.fn)) 53447db96d56Sopenharmony_ci fh.close() 53457db96d56Sopenharmony_ci 53467db96d56Sopenharmony_ci def test_emit_after_closing_in_write_mode(self): 53477db96d56Sopenharmony_ci # Issue #42378 53487db96d56Sopenharmony_ci os.unlink(self.fn) 53497db96d56Sopenharmony_ci fh = logging.FileHandler(self.fn, encoding='utf-8', mode='w') 53507db96d56Sopenharmony_ci fh.setFormatter(logging.Formatter('%(message)s')) 53517db96d56Sopenharmony_ci fh.emit(self.next_rec()) # '1' 53527db96d56Sopenharmony_ci fh.close() 53537db96d56Sopenharmony_ci fh.emit(self.next_rec()) # '2' 53547db96d56Sopenharmony_ci with open(self.fn) as fp: 53557db96d56Sopenharmony_ci self.assertEqual(fp.read().strip(), '1') 53567db96d56Sopenharmony_ci 53577db96d56Sopenharmony_ciclass RotatingFileHandlerTest(BaseFileTest): 53587db96d56Sopenharmony_ci @unittest.skipIf(support.is_wasi, "WASI does not have /dev/null.") 53597db96d56Sopenharmony_ci def test_should_not_rollover(self): 53607db96d56Sopenharmony_ci # If maxbytes is zero rollover never occurs 53617db96d56Sopenharmony_ci rh = logging.handlers.RotatingFileHandler( 53627db96d56Sopenharmony_ci self.fn, encoding="utf-8", maxBytes=0) 53637db96d56Sopenharmony_ci self.assertFalse(rh.shouldRollover(None)) 53647db96d56Sopenharmony_ci rh.close() 53657db96d56Sopenharmony_ci # bpo-45401 - test with special file 53667db96d56Sopenharmony_ci # We set maxBytes to 1 so that rollover would normally happen, except 53677db96d56Sopenharmony_ci # for the check for regular files 53687db96d56Sopenharmony_ci rh = logging.handlers.RotatingFileHandler( 53697db96d56Sopenharmony_ci os.devnull, encoding="utf-8", maxBytes=1) 53707db96d56Sopenharmony_ci self.assertFalse(rh.shouldRollover(self.next_rec())) 53717db96d56Sopenharmony_ci rh.close() 53727db96d56Sopenharmony_ci 53737db96d56Sopenharmony_ci def test_should_rollover(self): 53747db96d56Sopenharmony_ci rh = logging.handlers.RotatingFileHandler(self.fn, encoding="utf-8", maxBytes=1) 53757db96d56Sopenharmony_ci self.assertTrue(rh.shouldRollover(self.next_rec())) 53767db96d56Sopenharmony_ci rh.close() 53777db96d56Sopenharmony_ci 53787db96d56Sopenharmony_ci def test_file_created(self): 53797db96d56Sopenharmony_ci # checks that the file is created and assumes it was created 53807db96d56Sopenharmony_ci # by us 53817db96d56Sopenharmony_ci rh = logging.handlers.RotatingFileHandler(self.fn, encoding="utf-8") 53827db96d56Sopenharmony_ci rh.emit(self.next_rec()) 53837db96d56Sopenharmony_ci self.assertLogFile(self.fn) 53847db96d56Sopenharmony_ci rh.close() 53857db96d56Sopenharmony_ci 53867db96d56Sopenharmony_ci def test_rollover_filenames(self): 53877db96d56Sopenharmony_ci def namer(name): 53887db96d56Sopenharmony_ci return name + ".test" 53897db96d56Sopenharmony_ci rh = logging.handlers.RotatingFileHandler( 53907db96d56Sopenharmony_ci self.fn, encoding="utf-8", backupCount=2, maxBytes=1) 53917db96d56Sopenharmony_ci rh.namer = namer 53927db96d56Sopenharmony_ci rh.emit(self.next_rec()) 53937db96d56Sopenharmony_ci self.assertLogFile(self.fn) 53947db96d56Sopenharmony_ci rh.emit(self.next_rec()) 53957db96d56Sopenharmony_ci self.assertLogFile(namer(self.fn + ".1")) 53967db96d56Sopenharmony_ci rh.emit(self.next_rec()) 53977db96d56Sopenharmony_ci self.assertLogFile(namer(self.fn + ".2")) 53987db96d56Sopenharmony_ci self.assertFalse(os.path.exists(namer(self.fn + ".3"))) 53997db96d56Sopenharmony_ci rh.close() 54007db96d56Sopenharmony_ci 54017db96d56Sopenharmony_ci def test_namer_rotator_inheritance(self): 54027db96d56Sopenharmony_ci class HandlerWithNamerAndRotator(logging.handlers.RotatingFileHandler): 54037db96d56Sopenharmony_ci def namer(self, name): 54047db96d56Sopenharmony_ci return name + ".test" 54057db96d56Sopenharmony_ci 54067db96d56Sopenharmony_ci def rotator(self, source, dest): 54077db96d56Sopenharmony_ci if os.path.exists(source): 54087db96d56Sopenharmony_ci os.replace(source, dest + ".rotated") 54097db96d56Sopenharmony_ci 54107db96d56Sopenharmony_ci rh = HandlerWithNamerAndRotator( 54117db96d56Sopenharmony_ci self.fn, encoding="utf-8", backupCount=2, maxBytes=1) 54127db96d56Sopenharmony_ci self.assertEqual(rh.namer(self.fn), self.fn + ".test") 54137db96d56Sopenharmony_ci rh.emit(self.next_rec()) 54147db96d56Sopenharmony_ci self.assertLogFile(self.fn) 54157db96d56Sopenharmony_ci rh.emit(self.next_rec()) 54167db96d56Sopenharmony_ci self.assertLogFile(rh.namer(self.fn + ".1") + ".rotated") 54177db96d56Sopenharmony_ci self.assertFalse(os.path.exists(rh.namer(self.fn + ".1"))) 54187db96d56Sopenharmony_ci rh.close() 54197db96d56Sopenharmony_ci 54207db96d56Sopenharmony_ci @support.requires_zlib() 54217db96d56Sopenharmony_ci def test_rotator(self): 54227db96d56Sopenharmony_ci def namer(name): 54237db96d56Sopenharmony_ci return name + ".gz" 54247db96d56Sopenharmony_ci 54257db96d56Sopenharmony_ci def rotator(source, dest): 54267db96d56Sopenharmony_ci with open(source, "rb") as sf: 54277db96d56Sopenharmony_ci data = sf.read() 54287db96d56Sopenharmony_ci compressed = zlib.compress(data, 9) 54297db96d56Sopenharmony_ci with open(dest, "wb") as df: 54307db96d56Sopenharmony_ci df.write(compressed) 54317db96d56Sopenharmony_ci os.remove(source) 54327db96d56Sopenharmony_ci 54337db96d56Sopenharmony_ci rh = logging.handlers.RotatingFileHandler( 54347db96d56Sopenharmony_ci self.fn, encoding="utf-8", backupCount=2, maxBytes=1) 54357db96d56Sopenharmony_ci rh.rotator = rotator 54367db96d56Sopenharmony_ci rh.namer = namer 54377db96d56Sopenharmony_ci m1 = self.next_rec() 54387db96d56Sopenharmony_ci rh.emit(m1) 54397db96d56Sopenharmony_ci self.assertLogFile(self.fn) 54407db96d56Sopenharmony_ci m2 = self.next_rec() 54417db96d56Sopenharmony_ci rh.emit(m2) 54427db96d56Sopenharmony_ci fn = namer(self.fn + ".1") 54437db96d56Sopenharmony_ci self.assertLogFile(fn) 54447db96d56Sopenharmony_ci newline = os.linesep 54457db96d56Sopenharmony_ci with open(fn, "rb") as f: 54467db96d56Sopenharmony_ci compressed = f.read() 54477db96d56Sopenharmony_ci data = zlib.decompress(compressed) 54487db96d56Sopenharmony_ci self.assertEqual(data.decode("ascii"), m1.msg + newline) 54497db96d56Sopenharmony_ci rh.emit(self.next_rec()) 54507db96d56Sopenharmony_ci fn = namer(self.fn + ".2") 54517db96d56Sopenharmony_ci self.assertLogFile(fn) 54527db96d56Sopenharmony_ci with open(fn, "rb") as f: 54537db96d56Sopenharmony_ci compressed = f.read() 54547db96d56Sopenharmony_ci data = zlib.decompress(compressed) 54557db96d56Sopenharmony_ci self.assertEqual(data.decode("ascii"), m1.msg + newline) 54567db96d56Sopenharmony_ci rh.emit(self.next_rec()) 54577db96d56Sopenharmony_ci fn = namer(self.fn + ".2") 54587db96d56Sopenharmony_ci with open(fn, "rb") as f: 54597db96d56Sopenharmony_ci compressed = f.read() 54607db96d56Sopenharmony_ci data = zlib.decompress(compressed) 54617db96d56Sopenharmony_ci self.assertEqual(data.decode("ascii"), m2.msg + newline) 54627db96d56Sopenharmony_ci self.assertFalse(os.path.exists(namer(self.fn + ".3"))) 54637db96d56Sopenharmony_ci rh.close() 54647db96d56Sopenharmony_ci 54657db96d56Sopenharmony_ciclass TimedRotatingFileHandlerTest(BaseFileTest): 54667db96d56Sopenharmony_ci @unittest.skipIf(support.is_wasi, "WASI does not have /dev/null.") 54677db96d56Sopenharmony_ci def test_should_not_rollover(self): 54687db96d56Sopenharmony_ci # See bpo-45401. Should only ever rollover regular files 54697db96d56Sopenharmony_ci fh = logging.handlers.TimedRotatingFileHandler( 54707db96d56Sopenharmony_ci os.devnull, 'S', encoding="utf-8", backupCount=1) 54717db96d56Sopenharmony_ci time.sleep(1.1) # a little over a second ... 54727db96d56Sopenharmony_ci r = logging.makeLogRecord({'msg': 'testing - device file'}) 54737db96d56Sopenharmony_ci self.assertFalse(fh.shouldRollover(r)) 54747db96d56Sopenharmony_ci fh.close() 54757db96d56Sopenharmony_ci 54767db96d56Sopenharmony_ci # other test methods added below 54777db96d56Sopenharmony_ci def test_rollover(self): 54787db96d56Sopenharmony_ci fh = logging.handlers.TimedRotatingFileHandler( 54797db96d56Sopenharmony_ci self.fn, 'S', encoding="utf-8", backupCount=1) 54807db96d56Sopenharmony_ci fmt = logging.Formatter('%(asctime)s %(message)s') 54817db96d56Sopenharmony_ci fh.setFormatter(fmt) 54827db96d56Sopenharmony_ci r1 = logging.makeLogRecord({'msg': 'testing - initial'}) 54837db96d56Sopenharmony_ci fh.emit(r1) 54847db96d56Sopenharmony_ci self.assertLogFile(self.fn) 54857db96d56Sopenharmony_ci time.sleep(1.1) # a little over a second ... 54867db96d56Sopenharmony_ci r2 = logging.makeLogRecord({'msg': 'testing - after delay'}) 54877db96d56Sopenharmony_ci fh.emit(r2) 54887db96d56Sopenharmony_ci fh.close() 54897db96d56Sopenharmony_ci # At this point, we should have a recent rotated file which we 54907db96d56Sopenharmony_ci # can test for the existence of. However, in practice, on some 54917db96d56Sopenharmony_ci # machines which run really slowly, we don't know how far back 54927db96d56Sopenharmony_ci # in time to go to look for the log file. So, we go back a fair 54937db96d56Sopenharmony_ci # bit, and stop as soon as we see a rotated file. In theory this 54947db96d56Sopenharmony_ci # could of course still fail, but the chances are lower. 54957db96d56Sopenharmony_ci found = False 54967db96d56Sopenharmony_ci now = datetime.datetime.now() 54977db96d56Sopenharmony_ci GO_BACK = 5 * 60 # seconds 54987db96d56Sopenharmony_ci for secs in range(GO_BACK): 54997db96d56Sopenharmony_ci prev = now - datetime.timedelta(seconds=secs) 55007db96d56Sopenharmony_ci fn = self.fn + prev.strftime(".%Y-%m-%d_%H-%M-%S") 55017db96d56Sopenharmony_ci found = os.path.exists(fn) 55027db96d56Sopenharmony_ci if found: 55037db96d56Sopenharmony_ci self.rmfiles.append(fn) 55047db96d56Sopenharmony_ci break 55057db96d56Sopenharmony_ci msg = 'No rotated files found, went back %d seconds' % GO_BACK 55067db96d56Sopenharmony_ci if not found: 55077db96d56Sopenharmony_ci # print additional diagnostics 55087db96d56Sopenharmony_ci dn, fn = os.path.split(self.fn) 55097db96d56Sopenharmony_ci files = [f for f in os.listdir(dn) if f.startswith(fn)] 55107db96d56Sopenharmony_ci print('Test time: %s' % now.strftime("%Y-%m-%d %H-%M-%S"), file=sys.stderr) 55117db96d56Sopenharmony_ci print('The only matching files are: %s' % files, file=sys.stderr) 55127db96d56Sopenharmony_ci for f in files: 55137db96d56Sopenharmony_ci print('Contents of %s:' % f) 55147db96d56Sopenharmony_ci path = os.path.join(dn, f) 55157db96d56Sopenharmony_ci with open(path, 'r') as tf: 55167db96d56Sopenharmony_ci print(tf.read()) 55177db96d56Sopenharmony_ci self.assertTrue(found, msg=msg) 55187db96d56Sopenharmony_ci 55197db96d56Sopenharmony_ci def test_invalid(self): 55207db96d56Sopenharmony_ci assertRaises = self.assertRaises 55217db96d56Sopenharmony_ci assertRaises(ValueError, logging.handlers.TimedRotatingFileHandler, 55227db96d56Sopenharmony_ci self.fn, 'X', encoding="utf-8", delay=True) 55237db96d56Sopenharmony_ci assertRaises(ValueError, logging.handlers.TimedRotatingFileHandler, 55247db96d56Sopenharmony_ci self.fn, 'W', encoding="utf-8", delay=True) 55257db96d56Sopenharmony_ci assertRaises(ValueError, logging.handlers.TimedRotatingFileHandler, 55267db96d56Sopenharmony_ci self.fn, 'W7', encoding="utf-8", delay=True) 55277db96d56Sopenharmony_ci 55287db96d56Sopenharmony_ci def test_compute_rollover_daily_attime(self): 55297db96d56Sopenharmony_ci currentTime = 0 55307db96d56Sopenharmony_ci atTime = datetime.time(12, 0, 0) 55317db96d56Sopenharmony_ci rh = logging.handlers.TimedRotatingFileHandler( 55327db96d56Sopenharmony_ci self.fn, encoding="utf-8", when='MIDNIGHT', interval=1, backupCount=0, 55337db96d56Sopenharmony_ci utc=True, atTime=atTime) 55347db96d56Sopenharmony_ci try: 55357db96d56Sopenharmony_ci actual = rh.computeRollover(currentTime) 55367db96d56Sopenharmony_ci self.assertEqual(actual, currentTime + 12 * 60 * 60) 55377db96d56Sopenharmony_ci 55387db96d56Sopenharmony_ci actual = rh.computeRollover(currentTime + 13 * 60 * 60) 55397db96d56Sopenharmony_ci self.assertEqual(actual, currentTime + 36 * 60 * 60) 55407db96d56Sopenharmony_ci finally: 55417db96d56Sopenharmony_ci rh.close() 55427db96d56Sopenharmony_ci 55437db96d56Sopenharmony_ci #@unittest.skipIf(True, 'Temporarily skipped while failures investigated.') 55447db96d56Sopenharmony_ci def test_compute_rollover_weekly_attime(self): 55457db96d56Sopenharmony_ci currentTime = int(time.time()) 55467db96d56Sopenharmony_ci today = currentTime - currentTime % 86400 55477db96d56Sopenharmony_ci 55487db96d56Sopenharmony_ci atTime = datetime.time(12, 0, 0) 55497db96d56Sopenharmony_ci 55507db96d56Sopenharmony_ci wday = time.gmtime(today).tm_wday 55517db96d56Sopenharmony_ci for day in range(7): 55527db96d56Sopenharmony_ci rh = logging.handlers.TimedRotatingFileHandler( 55537db96d56Sopenharmony_ci self.fn, encoding="utf-8", when='W%d' % day, interval=1, backupCount=0, 55547db96d56Sopenharmony_ci utc=True, atTime=atTime) 55557db96d56Sopenharmony_ci try: 55567db96d56Sopenharmony_ci if wday > day: 55577db96d56Sopenharmony_ci # The rollover day has already passed this week, so we 55587db96d56Sopenharmony_ci # go over into next week 55597db96d56Sopenharmony_ci expected = (7 - wday + day) 55607db96d56Sopenharmony_ci else: 55617db96d56Sopenharmony_ci expected = (day - wday) 55627db96d56Sopenharmony_ci # At this point expected is in days from now, convert to seconds 55637db96d56Sopenharmony_ci expected *= 24 * 60 * 60 55647db96d56Sopenharmony_ci # Add in the rollover time 55657db96d56Sopenharmony_ci expected += 12 * 60 * 60 55667db96d56Sopenharmony_ci # Add in adjustment for today 55677db96d56Sopenharmony_ci expected += today 55687db96d56Sopenharmony_ci actual = rh.computeRollover(today) 55697db96d56Sopenharmony_ci if actual != expected: 55707db96d56Sopenharmony_ci print('failed in timezone: %d' % time.timezone) 55717db96d56Sopenharmony_ci print('local vars: %s' % locals()) 55727db96d56Sopenharmony_ci self.assertEqual(actual, expected) 55737db96d56Sopenharmony_ci if day == wday: 55747db96d56Sopenharmony_ci # goes into following week 55757db96d56Sopenharmony_ci expected += 7 * 24 * 60 * 60 55767db96d56Sopenharmony_ci actual = rh.computeRollover(today + 13 * 60 * 60) 55777db96d56Sopenharmony_ci if actual != expected: 55787db96d56Sopenharmony_ci print('failed in timezone: %d' % time.timezone) 55797db96d56Sopenharmony_ci print('local vars: %s' % locals()) 55807db96d56Sopenharmony_ci self.assertEqual(actual, expected) 55817db96d56Sopenharmony_ci finally: 55827db96d56Sopenharmony_ci rh.close() 55837db96d56Sopenharmony_ci 55847db96d56Sopenharmony_ci def test_compute_files_to_delete(self): 55857db96d56Sopenharmony_ci # See bpo-46063 for background 55867db96d56Sopenharmony_ci wd = tempfile.mkdtemp(prefix='test_logging_') 55877db96d56Sopenharmony_ci self.addCleanup(shutil.rmtree, wd) 55887db96d56Sopenharmony_ci times = [] 55897db96d56Sopenharmony_ci dt = datetime.datetime.now() 55907db96d56Sopenharmony_ci for i in range(10): 55917db96d56Sopenharmony_ci times.append(dt.strftime('%Y-%m-%d_%H-%M-%S')) 55927db96d56Sopenharmony_ci dt += datetime.timedelta(seconds=5) 55937db96d56Sopenharmony_ci prefixes = ('a.b', 'a.b.c', 'd.e', 'd.e.f') 55947db96d56Sopenharmony_ci files = [] 55957db96d56Sopenharmony_ci rotators = [] 55967db96d56Sopenharmony_ci for prefix in prefixes: 55977db96d56Sopenharmony_ci p = os.path.join(wd, '%s.log' % prefix) 55987db96d56Sopenharmony_ci rotator = logging.handlers.TimedRotatingFileHandler(p, when='s', 55997db96d56Sopenharmony_ci interval=5, 56007db96d56Sopenharmony_ci backupCount=7, 56017db96d56Sopenharmony_ci delay=True) 56027db96d56Sopenharmony_ci rotators.append(rotator) 56037db96d56Sopenharmony_ci if prefix.startswith('a.b'): 56047db96d56Sopenharmony_ci for t in times: 56057db96d56Sopenharmony_ci files.append('%s.log.%s' % (prefix, t)) 56067db96d56Sopenharmony_ci else: 56077db96d56Sopenharmony_ci rotator.namer = lambda name: name.replace('.log', '') + '.log' 56087db96d56Sopenharmony_ci for t in times: 56097db96d56Sopenharmony_ci files.append('%s.%s.log' % (prefix, t)) 56107db96d56Sopenharmony_ci # Create empty files 56117db96d56Sopenharmony_ci for fn in files: 56127db96d56Sopenharmony_ci p = os.path.join(wd, fn) 56137db96d56Sopenharmony_ci with open(p, 'wb') as f: 56147db96d56Sopenharmony_ci pass 56157db96d56Sopenharmony_ci # Now the checks that only the correct files are offered up for deletion 56167db96d56Sopenharmony_ci for i, prefix in enumerate(prefixes): 56177db96d56Sopenharmony_ci rotator = rotators[i] 56187db96d56Sopenharmony_ci candidates = rotator.getFilesToDelete() 56197db96d56Sopenharmony_ci self.assertEqual(len(candidates), 3) 56207db96d56Sopenharmony_ci if prefix.startswith('a.b'): 56217db96d56Sopenharmony_ci p = '%s.log.' % prefix 56227db96d56Sopenharmony_ci for c in candidates: 56237db96d56Sopenharmony_ci d, fn = os.path.split(c) 56247db96d56Sopenharmony_ci self.assertTrue(fn.startswith(p)) 56257db96d56Sopenharmony_ci else: 56267db96d56Sopenharmony_ci for c in candidates: 56277db96d56Sopenharmony_ci d, fn = os.path.split(c) 56287db96d56Sopenharmony_ci self.assertTrue(fn.endswith('.log')) 56297db96d56Sopenharmony_ci self.assertTrue(fn.startswith(prefix + '.') and 56307db96d56Sopenharmony_ci fn[len(prefix) + 2].isdigit()) 56317db96d56Sopenharmony_ci 56327db96d56Sopenharmony_ci 56337db96d56Sopenharmony_cidef secs(**kw): 56347db96d56Sopenharmony_ci return datetime.timedelta(**kw) // datetime.timedelta(seconds=1) 56357db96d56Sopenharmony_ci 56367db96d56Sopenharmony_cifor when, exp in (('S', 1), 56377db96d56Sopenharmony_ci ('M', 60), 56387db96d56Sopenharmony_ci ('H', 60 * 60), 56397db96d56Sopenharmony_ci ('D', 60 * 60 * 24), 56407db96d56Sopenharmony_ci ('MIDNIGHT', 60 * 60 * 24), 56417db96d56Sopenharmony_ci # current time (epoch start) is a Thursday, W0 means Monday 56427db96d56Sopenharmony_ci ('W0', secs(days=4, hours=24)), 56437db96d56Sopenharmony_ci ): 56447db96d56Sopenharmony_ci def test_compute_rollover(self, when=when, exp=exp): 56457db96d56Sopenharmony_ci rh = logging.handlers.TimedRotatingFileHandler( 56467db96d56Sopenharmony_ci self.fn, encoding="utf-8", when=when, interval=1, backupCount=0, utc=True) 56477db96d56Sopenharmony_ci currentTime = 0.0 56487db96d56Sopenharmony_ci actual = rh.computeRollover(currentTime) 56497db96d56Sopenharmony_ci if exp != actual: 56507db96d56Sopenharmony_ci # Failures occur on some systems for MIDNIGHT and W0. 56517db96d56Sopenharmony_ci # Print detailed calculation for MIDNIGHT so we can try to see 56527db96d56Sopenharmony_ci # what's going on 56537db96d56Sopenharmony_ci if when == 'MIDNIGHT': 56547db96d56Sopenharmony_ci try: 56557db96d56Sopenharmony_ci if rh.utc: 56567db96d56Sopenharmony_ci t = time.gmtime(currentTime) 56577db96d56Sopenharmony_ci else: 56587db96d56Sopenharmony_ci t = time.localtime(currentTime) 56597db96d56Sopenharmony_ci currentHour = t[3] 56607db96d56Sopenharmony_ci currentMinute = t[4] 56617db96d56Sopenharmony_ci currentSecond = t[5] 56627db96d56Sopenharmony_ci # r is the number of seconds left between now and midnight 56637db96d56Sopenharmony_ci r = logging.handlers._MIDNIGHT - ((currentHour * 60 + 56647db96d56Sopenharmony_ci currentMinute) * 60 + 56657db96d56Sopenharmony_ci currentSecond) 56667db96d56Sopenharmony_ci result = currentTime + r 56677db96d56Sopenharmony_ci print('t: %s (%s)' % (t, rh.utc), file=sys.stderr) 56687db96d56Sopenharmony_ci print('currentHour: %s' % currentHour, file=sys.stderr) 56697db96d56Sopenharmony_ci print('currentMinute: %s' % currentMinute, file=sys.stderr) 56707db96d56Sopenharmony_ci print('currentSecond: %s' % currentSecond, file=sys.stderr) 56717db96d56Sopenharmony_ci print('r: %s' % r, file=sys.stderr) 56727db96d56Sopenharmony_ci print('result: %s' % result, file=sys.stderr) 56737db96d56Sopenharmony_ci except Exception as e: 56747db96d56Sopenharmony_ci print('exception in diagnostic code: %s' % e, file=sys.stderr) 56757db96d56Sopenharmony_ci self.assertEqual(exp, actual) 56767db96d56Sopenharmony_ci rh.close() 56777db96d56Sopenharmony_ci setattr(TimedRotatingFileHandlerTest, "test_compute_rollover_%s" % when, test_compute_rollover) 56787db96d56Sopenharmony_ci 56797db96d56Sopenharmony_ci 56807db96d56Sopenharmony_ci@unittest.skipUnless(win32evtlog, 'win32evtlog/win32evtlogutil/pywintypes required for this test.') 56817db96d56Sopenharmony_ciclass NTEventLogHandlerTest(BaseTest): 56827db96d56Sopenharmony_ci def test_basic(self): 56837db96d56Sopenharmony_ci logtype = 'Application' 56847db96d56Sopenharmony_ci elh = win32evtlog.OpenEventLog(None, logtype) 56857db96d56Sopenharmony_ci num_recs = win32evtlog.GetNumberOfEventLogRecords(elh) 56867db96d56Sopenharmony_ci 56877db96d56Sopenharmony_ci try: 56887db96d56Sopenharmony_ci h = logging.handlers.NTEventLogHandler('test_logging') 56897db96d56Sopenharmony_ci except pywintypes.error as e: 56907db96d56Sopenharmony_ci if e.winerror == 5: # access denied 56917db96d56Sopenharmony_ci raise unittest.SkipTest('Insufficient privileges to run test') 56927db96d56Sopenharmony_ci raise 56937db96d56Sopenharmony_ci 56947db96d56Sopenharmony_ci r = logging.makeLogRecord({'msg': 'Test Log Message'}) 56957db96d56Sopenharmony_ci h.handle(r) 56967db96d56Sopenharmony_ci h.close() 56977db96d56Sopenharmony_ci # Now see if the event is recorded 56987db96d56Sopenharmony_ci self.assertLess(num_recs, win32evtlog.GetNumberOfEventLogRecords(elh)) 56997db96d56Sopenharmony_ci flags = win32evtlog.EVENTLOG_BACKWARDS_READ | \ 57007db96d56Sopenharmony_ci win32evtlog.EVENTLOG_SEQUENTIAL_READ 57017db96d56Sopenharmony_ci found = False 57027db96d56Sopenharmony_ci GO_BACK = 100 57037db96d56Sopenharmony_ci events = win32evtlog.ReadEventLog(elh, flags, GO_BACK) 57047db96d56Sopenharmony_ci for e in events: 57057db96d56Sopenharmony_ci if e.SourceName != 'test_logging': 57067db96d56Sopenharmony_ci continue 57077db96d56Sopenharmony_ci msg = win32evtlogutil.SafeFormatMessage(e, logtype) 57087db96d56Sopenharmony_ci if msg != 'Test Log Message\r\n': 57097db96d56Sopenharmony_ci continue 57107db96d56Sopenharmony_ci found = True 57117db96d56Sopenharmony_ci break 57127db96d56Sopenharmony_ci msg = 'Record not found in event log, went back %d records' % GO_BACK 57137db96d56Sopenharmony_ci self.assertTrue(found, msg=msg) 57147db96d56Sopenharmony_ci 57157db96d56Sopenharmony_ci 57167db96d56Sopenharmony_ciclass MiscTestCase(unittest.TestCase): 57177db96d56Sopenharmony_ci def test__all__(self): 57187db96d56Sopenharmony_ci not_exported = { 57197db96d56Sopenharmony_ci 'logThreads', 'logMultiprocessing', 'logProcesses', 'currentframe', 57207db96d56Sopenharmony_ci 'PercentStyle', 'StrFormatStyle', 'StringTemplateStyle', 57217db96d56Sopenharmony_ci 'Filterer', 'PlaceHolder', 'Manager', 'RootLogger', 'root', 57227db96d56Sopenharmony_ci 'threading'} 57237db96d56Sopenharmony_ci support.check__all__(self, logging, not_exported=not_exported) 57247db96d56Sopenharmony_ci 57257db96d56Sopenharmony_ci 57267db96d56Sopenharmony_ci# Set the locale to the platform-dependent default. I have no idea 57277db96d56Sopenharmony_ci# why the test does this, but in any case we save the current locale 57287db96d56Sopenharmony_ci# first and restore it at the end. 57297db96d56Sopenharmony_cidef setUpModule(): 57307db96d56Sopenharmony_ci unittest.enterModuleContext(support.run_with_locale('LC_ALL', '')) 57317db96d56Sopenharmony_ci 57327db96d56Sopenharmony_ci 57337db96d56Sopenharmony_ciif __name__ == "__main__": 57347db96d56Sopenharmony_ci unittest.main() 5735