✘✘ GRAYBYTE WORDPRESS FILE MANAGER ✘✘

​🇳​​🇦​​🇲​​🇪♯➤ beluga.o2switch.net ​🇻​♯➤ 4.18.0-553.123.2.lve.el8.x86_64 #1 SMP 🇾​♯➤ 2026

𝗛𝗢𝗠𝗘 𝗜𝗗 ♯➤ 185.154.139.77 ♯➤ 𝗔𝗗𝗠𝗜𝗡 𝗜𝗗 216.73.216.254
𝗢𝗣𝗧𝗜𝗢𝗡𝗦 ♯ CRL ♯➤ 𝗢𝗞 ┃ WGT ♯➤ 𝗢𝗞 ┃ SDO ♯➤ 𝗢𝗙𝗙 ┃ PKEX ♯➤ 𝗢𝗙𝗙
𝗗𝗘𝗔𝗖𝗧𝗜𝗩𝗔𝗧𝗘𝗗 ♯➤ 𝗔𝗟𝗟 𝗪𝗢𝗥𝗞𝗜𝗡𝗚....

𝗛𝗢𝗠𝗘
𝗖𝗨𝗥𝗥𝗘𝗡𝗧 𝗙𝗜𝗟𝗘 : /opt/alt/python37/lib64/python3.7/test//test_logging.py
# Copyright 2001-2017 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""Test harness for the logging module. Run all tests.

Copyright (C) 2001-2017 Vinay Sajip. All Rights Reserved.
"""

import logging
import logging.handlers
import logging.config

import codecs
import configparser
import datetime
import pathlib
import pickle
import io
import gc
import json
import os
import queue
import random
import re
import signal
import socket
import struct
import sys
import tempfile
from test.support.script_helper import assert_python_ok, assert_python_failure
from test import support
import textwrap
import threading
import time
import unittest
import warnings
import weakref

import asyncore
from http.server import HTTPServer, BaseHTTPRequestHandler
import smtpd
from urllib.parse import urlparse, parse_qs
from socketserver import (ThreadingUDPServer, DatagramRequestHandler,
                          ThreadingTCPServer, StreamRequestHandler)

try:
    import win32evtlog, win32evtlogutil, pywintypes
except ImportError:
    win32evtlog = win32evtlogutil = pywintypes = None

try:
    import zlib
except ImportError:
    pass

class BaseTest(unittest.TestCase):

    """Base class for logging tests."""

    log_format = "%(name)s -> %(levelname)s: %(message)s"
    expected_log_pat = r"^([\w.]+) -> (\w+): (\d+)$"
    message_num = 0

    def setUp(self):
        """Setup the default logging stream to an internal StringIO instance,
        so that we can examine log output as we want."""
        self._threading_key = support.threading_setup()

        logger_dict = logging.getLogger().manager.loggerDict
        logging._acquireLock()
        try:
            self.saved_handlers = logging._handlers.copy()
            self.saved_handler_list = logging._handlerList[:]
            self.saved_loggers = saved_loggers = logger_dict.copy()
            self.saved_name_to_level = logging._nameToLevel.copy()
            self.saved_level_to_name = logging._levelToName.copy()
            self.logger_states = logger_states = {}
            for name in saved_loggers:
                logger_states[name] = getattr(saved_loggers[name],
                                              'disabled', None)
        finally:
            logging._releaseLock()

        # Set two unused loggers
        self.logger1 = logging.getLogger("\xab\xd7\xbb")
        self.logger2 = logging.getLogger("\u013f\u00d6\u0047")

        self.root_logger = logging.getLogger("")
        self.original_logging_level = self.root_logger.getEffectiveLevel()

        self.stream = io.StringIO()
        self.root_logger.setLevel(logging.DEBUG)
        self.root_hdlr = logging.StreamHandler(self.stream)
        self.root_formatter = logging.Formatter(self.log_format)
        self.root_hdlr.setFormatter(self.root_formatter)
        if self.logger1.hasHandlers():
            hlist = self.logger1.handlers + self.root_logger.handlers
            raise AssertionError('Unexpected handlers: %s' % hlist)
        if self.logger2.hasHandlers():
            hlist = self.logger2.handlers + self.root_logger.handlers
            raise AssertionError('Unexpected handlers: %s' % hlist)
        self.root_logger.addHandler(self.root_hdlr)
        self.assertTrue(self.logger1.hasHandlers())
        self.assertTrue(self.logger2.hasHandlers())

    def tearDown(self):
        """Remove our logging stream, and restore the original logging
        level."""
        self.stream.close()
        self.root_logger.removeHandler(self.root_hdlr)
        while self.root_logger.handlers:
            h = self.root_logger.handlers[0]
            self.root_logger.removeHandler(h)
            h.close()
        self.root_logger.setLevel(self.original_logging_level)
        logging._acquireLock()
        try:
            logging._levelToName.clear()
            logging._levelToName.update(self.saved_level_to_name)
            logging._nameToLevel.clear()
            logging._nameToLevel.update(self.saved_name_to_level)
            logging._handlers.clear()
            logging._handlers.update(self.saved_handlers)
            logging._handlerList[:] = self.saved_handler_list
            manager = logging.getLogger().manager
            manager.disable = 0
            loggerDict = manager.loggerDict
            loggerDict.clear()
            loggerDict.update(self.saved_loggers)
            logger_states = self.logger_states
            for name in self.logger_states:
                if logger_states[name] is not None:
                    self.saved_loggers[name].disabled = logger_states[name]
        finally:
            logging._releaseLock()

        self.doCleanups()
        support.threading_cleanup(*self._threading_key)

    def assert_log_lines(self, expected_values, stream=None, pat=None):
        """Match the collected log lines against the regular expression
        self.expected_log_pat, and compare the extracted group values to
        the expected_values list of tuples."""
        stream = stream or self.stream
        pat = re.compile(pat or self.expected_log_pat)
        actual_lines = stream.getvalue().splitlines()
        self.assertEqual(len(actual_lines), len(expected_values))
        for actual, expected in zip(actual_lines, expected_values):
            match = pat.search(actual)
            if not match:
                self.fail("Log line does not match expected pattern:\n" +
                            actual)
            self.assertEqual(tuple(match.groups()), expected)
        s = stream.read()
        if s:
            self.fail("Remaining output at end of log stream:\n" + s)

    def next_message(self):
        """Generate a message consisting solely of an auto-incrementing
        integer."""
        self.message_num += 1
        return "%d" % self.message_num


class BuiltinLevelsTest(BaseTest):
    """Test builtin levels and their inheritance."""

    def test_flat(self):
        # Logging levels in a flat logger namespace.
        m = self.next_message

        ERR = logging.getLogger("ERR")
        ERR.setLevel(logging.ERROR)
        INF = logging.LoggerAdapter(logging.getLogger("INF"), {})
        INF.setLevel(logging.INFO)
        DEB = logging.getLogger("DEB")
        DEB.setLevel(logging.DEBUG)

        # These should log.
        ERR.log(logging.CRITICAL, m())
        ERR.error(m())

        INF.log(logging.CRITICAL, m())
        INF.error(m())
        INF.warning(m())
        INF.info(m())

        DEB.log(logging.CRITICAL, m())
        DEB.error(m())
        DEB.warning(m())
        DEB.info(m())
        DEB.debug(m())

        # These should not log.
        ERR.warning(m())
        ERR.info(m())
        ERR.debug(m())

        INF.debug(m())

        self.assert_log_lines([
            ('ERR', 'CRITICAL', '1'),
            ('ERR', 'ERROR', '2'),
            ('INF', 'CRITICAL', '3'),
            ('INF', 'ERROR', '4'),
            ('INF', 'WARNING', '5'),
            ('INF', 'INFO', '6'),
            ('DEB', 'CRITICAL', '7'),
            ('DEB', 'ERROR', '8'),
            ('DEB', 'WARNING', '9'),
            ('DEB', 'INFO', '10'),
            ('DEB', 'DEBUG', '11'),
        ])

    def test_nested_explicit(self):
        # Logging levels in a nested namespace, all explicitly set.
        m = self.next_message

        INF = logging.getLogger("INF")
        INF.setLevel(logging.INFO)
        INF_ERR  = logging.getLogger("INF.ERR")
        INF_ERR.setLevel(logging.ERROR)

        # These should log.
        INF_ERR.log(logging.CRITICAL, m())
        INF_ERR.error(m())

        # These should not log.
        INF_ERR.warning(m())
        INF_ERR.info(m())
        INF_ERR.debug(m())

        self.assert_log_lines([
            ('INF.ERR', 'CRITICAL', '1'),
            ('INF.ERR', 'ERROR', '2'),
        ])

    def test_nested_inherited(self):
        # Logging levels in a nested namespace, inherited from parent loggers.
        m = self.next_message

        INF = logging.getLogger("INF")
        INF.setLevel(logging.INFO)
        INF_ERR  = logging.getLogger("INF.ERR")
        INF_ERR.setLevel(logging.ERROR)
        INF_UNDEF = logging.getLogger("INF.UNDEF")
        INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF")
        UNDEF = logging.getLogger("UNDEF")

        # These should log.
        INF_UNDEF.log(logging.CRITICAL, m())
        INF_UNDEF.error(m())
        INF_UNDEF.warning(m())
        INF_UNDEF.info(m())
        INF_ERR_UNDEF.log(logging.CRITICAL, m())
        INF_ERR_UNDEF.error(m())

        # These should not log.
        INF_UNDEF.debug(m())
        INF_ERR_UNDEF.warning(m())
        INF_ERR_UNDEF.info(m())
        INF_ERR_UNDEF.debug(m())

        self.assert_log_lines([
            ('INF.UNDEF', 'CRITICAL', '1'),
            ('INF.UNDEF', 'ERROR', '2'),
            ('INF.UNDEF', 'WARNING', '3'),
            ('INF.UNDEF', 'INFO', '4'),
            ('INF.ERR.UNDEF', 'CRITICAL', '5'),
            ('INF.ERR.UNDEF', 'ERROR', '6'),
        ])

    def test_nested_with_virtual_parent(self):
        # Logging levels when some parent does not exist yet.
        m = self.next_message

        INF = logging.getLogger("INF")
        GRANDCHILD = logging.getLogger("INF.BADPARENT.UNDEF")
        CHILD = logging.getLogger("INF.BADPARENT")
        INF.setLevel(logging.INFO)

        # These should log.
        GRANDCHILD.log(logging.FATAL, m())
        GRANDCHILD.info(m())
        CHILD.log(logging.FATAL, m())
        CHILD.info(m())

        # These should not log.
        GRANDCHILD.debug(m())
        CHILD.debug(m())

        self.assert_log_lines([
            ('INF.BADPARENT.UNDEF', 'CRITICAL', '1'),
            ('INF.BADPARENT.UNDEF', 'INFO', '2'),
            ('INF.BADPARENT', 'CRITICAL', '3'),
            ('INF.BADPARENT', 'INFO', '4'),
        ])

    def test_regression_22386(self):
        """See issue #22386 for more information."""
        self.assertEqual(logging.getLevelName('INFO'), logging.INFO)
        self.assertEqual(logging.getLevelName(logging.INFO), 'INFO')

    def test_regression_29220(self):
        """See issue #29220 for more information."""
        logging.addLevelName(logging.INFO, '')
        self.addCleanup(logging.addLevelName, logging.INFO, 'INFO')
        self.assertEqual(logging.getLevelName(logging.INFO), '')

    def test_issue27935(self):
        fatal = logging.getLevelName('FATAL')
        self.assertEqual(fatal, logging.FATAL)

    def test_regression_29220(self):
        """See issue #29220 for more information."""
        logging.addLevelName(logging.INFO, '')
        self.addCleanup(logging.addLevelName, logging.INFO, 'INFO')
        self.assertEqual(logging.getLevelName(logging.INFO), '')
        self.assertEqual(logging.getLevelName(logging.NOTSET), 'NOTSET')
        self.assertEqual(logging.getLevelName('NOTSET'), logging.NOTSET)

class BasicFilterTest(BaseTest):

    """Test the bundled Filter class."""

    def test_filter(self):
        # Only messages satisfying the specified criteria pass through the
        #  filter.
        filter_ = logging.Filter("spam.eggs")
        handler = self.root_logger.handlers[0]
        try:
            handler.addFilter(filter_)
            spam = logging.getLogger("spam")
            spam_eggs = logging.getLogger("spam.eggs")
            spam_eggs_fish = logging.getLogger("spam.eggs.fish")
            spam_bakedbeans = logging.getLogger("spam.bakedbeans")

            spam.info(self.next_message())
            spam_eggs.info(self.next_message())  # Good.
            spam_eggs_fish.info(self.next_message())  # Good.
            spam_bakedbeans.info(self.next_message())

            self.assert_log_lines([
                ('spam.eggs', 'INFO', '2'),
                ('spam.eggs.fish', 'INFO', '3'),
            ])
        finally:
            handler.removeFilter(filter_)

    def test_callable_filter(self):
        # Only messages satisfying the specified criteria pass through the
        #  filter.

        def filterfunc(record):
            parts = record.name.split('.')
            prefix = '.'.join(parts[:2])
            return prefix == 'spam.eggs'

        handler = self.root_logger.handlers[0]
        try:
            handler.addFilter(filterfunc)
            spam = logging.getLogger("spam")
            spam_eggs = logging.getLogger("spam.eggs")
            spam_eggs_fish = logging.getLogger("spam.eggs.fish")
            spam_bakedbeans = logging.getLogger("spam.bakedbeans")

            spam.info(self.next_message())
            spam_eggs.info(self.next_message())  # Good.
            spam_eggs_fish.info(self.next_message())  # Good.
            spam_bakedbeans.info(self.next_message())

            self.assert_log_lines([
                ('spam.eggs', 'INFO', '2'),
                ('spam.eggs.fish', 'INFO', '3'),
            ])
        finally:
            handler.removeFilter(filterfunc)

    def test_empty_filter(self):
        f = logging.Filter()
        r = logging.makeLogRecord({'name': 'spam.eggs'})
        self.assertTrue(f.filter(r))

#
#   First, we define our levels. There can be as many as you want - the only
#     limitations are that they should be integers, the lowest should be > 0 and
#   larger values mean less information being logged. If you need specific
#   level values which do not fit into these limitations, you can use a
#   mapping dictionary to convert between your application levels and the
#   logging system.
#
SILENT      = 120
TACITURN    = 119
TERSE       = 118
EFFUSIVE    = 117
SOCIABLE    = 116
VERBOSE     = 115
TALKATIVE   = 114
GARRULOUS   = 113
CHATTERBOX  = 112
BORING      = 111

LEVEL_RANGE = range(BORING, SILENT + 1)

#
#   Next, we define names for our levels. You don't need to do this - in which
#   case the system will use "Level n" to denote the text for the level.
#
my_logging_levels = {
    SILENT      : 'Silent',
    TACITURN    : 'Taciturn',
    TERSE       : 'Terse',
    EFFUSIVE    : 'Effusive',
    SOCIABLE    : 'Sociable',
    VERBOSE     : 'Verbose',
    TALKATIVE   : 'Talkative',
    GARRULOUS   : 'Garrulous',
    CHATTERBOX  : 'Chatterbox',
    BORING      : 'Boring',
}

class GarrulousFilter(logging.Filter):

    """A filter which blocks garrulous messages."""

    def filter(self, record):
        return record.levelno != GARRULOUS

class VerySpecificFilter(logging.Filter):

    """A filter which blocks sociable and taciturn messages."""

    def filter(self, record):
        return record.levelno not in [SOCIABLE, TACITURN]


class CustomLevelsAndFiltersTest(BaseTest):

    """Test various filtering possibilities with custom logging levels."""

    # Skip the logger name group.
    expected_log_pat = r"^[\w.]+ -> (\w+): (\d+)$"

    def setUp(self):
        BaseTest.setUp(self)
        for k, v in my_logging_levels.items():
            logging.addLevelName(k, v)

    def log_at_all_levels(self, logger):
        for lvl in LEVEL_RANGE:
            logger.log(lvl, self.next_message())

    def test_logger_filter(self):
        # Filter at logger level.
        self.root_logger.setLevel(VERBOSE)
        # Levels >= 'Verbose' are good.
        self.log_at_all_levels(self.root_logger)
        self.assert_log_lines([
            ('Verbose', '5'),
            ('Sociable', '6'),
            ('Effusive', '7'),
            ('Terse', '8'),
            ('Taciturn', '9'),
            ('Silent', '10'),
        ])

    def test_handler_filter(self):
        # Filter at handler level.
        self.root_logger.handlers[0].setLevel(SOCIABLE)
        try:
            # Levels >= 'Sociable' are good.
            self.log_at_all_levels(self.root_logger)
            self.assert_log_lines([
                ('Sociable', '6'),
                ('Effusive', '7'),
                ('Terse', '8'),
                ('Taciturn', '9'),
                ('Silent', '10'),
            ])
        finally:
            self.root_logger.handlers[0].setLevel(logging.NOTSET)

    def test_specific_filters(self):
        # Set a specific filter object on the handler, and then add another
        #  filter object on the logger itself.
        handler = self.root_logger.handlers[0]
        specific_filter = None
        garr = GarrulousFilter()
        handler.addFilter(garr)
        try:
            self.log_at_all_levels(self.root_logger)
            first_lines = [
                # Notice how 'Garrulous' is missing
                ('Boring', '1'),
                ('Chatterbox', '2'),
                ('Talkative', '4'),
                ('Verbose', '5'),
                ('Sociable', '6'),
                ('Effusive', '7'),
                ('Terse', '8'),
                ('Taciturn', '9'),
                ('Silent', '10'),
            ]
            self.assert_log_lines(first_lines)

            specific_filter = VerySpecificFilter()
            self.root_logger.addFilter(specific_filter)
            self.log_at_all_levels(self.root_logger)
            self.assert_log_lines(first_lines + [
                # Not only 'Garrulous' is still missing, but also 'Sociable'
                # and 'Taciturn'
                ('Boring', '11'),
                ('Chatterbox', '12'),
                ('Talkative', '14'),
                ('Verbose', '15'),
                ('Effusive', '17'),
                ('Terse', '18'),
                ('Silent', '20'),
        ])
        finally:
            if specific_filter:
                self.root_logger.removeFilter(specific_filter)
            handler.removeFilter(garr)


class HandlerTest(BaseTest):
    def test_name(self):
        h = logging.Handler()
        h.name = 'generic'
        self.assertEqual(h.name, 'generic')
        h.name = 'anothergeneric'
        self.assertEqual(h.name, 'anothergeneric')
        self.assertRaises(NotImplementedError, h.emit, None)

    def test_builtin_handlers(self):
        # We can't actually *use* too many handlers in the tests,
        # but we can try instantiating them with various options
        if sys.platform in ('linux', 'darwin'):
            for existing in (True, False):
                fd, fn = tempfile.mkstemp()
                os.close(fd)
                if not existing:
                    os.unlink(fn)
                h = logging.handlers.WatchedFileHandler(fn, delay=True)
                if existing:
                    dev, ino = h.dev, h.ino
                    self.assertEqual(dev, -1)
                    self.assertEqual(ino, -1)
                    r = logging.makeLogRecord({'msg': 'Test'})
                    h.handle(r)
                    # Now remove the file.
                    os.unlink(fn)
                    self.assertFalse(os.path.exists(fn))
                    # The next call should recreate the file.
                    h.handle(r)
                    self.assertTrue(os.path.exists(fn))
                else:
                    self.assertEqual(h.dev, -1)
                    self.assertEqual(h.ino, -1)
                h.close()
                if existing:
                    os.unlink(fn)
            if sys.platform == 'darwin':
                sockname = '/var/run/syslog'
            else:
                sockname = '/dev/log'
            try:
                h = logging.handlers.SysLogHandler(sockname)
                self.assertEqual(h.facility, h.LOG_USER)
                self.assertTrue(h.unixsocket)
                h.close()
            except OSError: # syslogd might not be available
                pass
        for method in ('GET', 'POST', 'PUT'):
            if method == 'PUT':
                self.assertRaises(ValueError, logging.handlers.HTTPHandler,
                                  'localhost', '/log', method)
            else:
                h = logging.handlers.HTTPHandler('localhost', '/log', method)
                h.close()
        h = logging.handlers.BufferingHandler(0)
        r = logging.makeLogRecord({})
        self.assertTrue(h.shouldFlush(r))
        h.close()
        h = logging.handlers.BufferingHandler(1)
        self.assertFalse(h.shouldFlush(r))
        h.close()

    def test_path_objects(self):
        """
        Test that Path objects are accepted as filename arguments to handlers.

        See Issue #27493.
        """
        fd, fn = tempfile.mkstemp()
        os.close(fd)
        os.unlink(fn)
        pfn = pathlib.Path(fn)
        cases = (
                    (logging.FileHandler, (pfn, 'w')),
                    (logging.handlers.RotatingFileHandler, (pfn, 'a')),
                    (logging.handlers.TimedRotatingFileHandler, (pfn, 'h')),
                )
        if sys.platform in ('linux', 'darwin'):
            cases += ((logging.handlers.WatchedFileHandler, (pfn, 'w')),)
        for cls, args in cases:
            h = cls(*args)
            self.assertTrue(os.path.exists(fn))
            h.close()
            os.unlink(fn)

    @unittest.skipIf(os.name == 'nt', 'WatchedFileHandler not appropriate for Windows.')
    def test_race(self):
        # Issue #14632 refers.
        def remove_loop(fname, tries):
            for _ in range(tries):
                try:
                    os.unlink(fname)
                    self.deletion_time = time.time()
                except OSError:
                    pass
                time.sleep(0.004 * random.randint(0, 4))

        del_count = 500
        log_count = 500

        self.handle_time = None
        self.deletion_time = None

        for delay in (False, True):
            fd, fn = tempfile.mkstemp('.log', 'test_logging-3-')
            os.close(fd)
            remover = threading.Thread(target=remove_loop, args=(fn, del_count))
            remover.daemon = True
            remover.start()
            h = logging.handlers.WatchedFileHandler(fn, delay=delay)
            f = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s')
            h.setFormatter(f)
            try:
                for _ in range(log_count):
                    time.sleep(0.005)
                    r = logging.makeLogRecord({'msg': 'testing' })
                    try:
                        self.handle_time = time.time()
                        h.handle(r)
                    except Exception:
                        print('Deleted at %s, '
                              'opened at %s' % (self.deletion_time,
                                                self.handle_time))
                        raise
            finally:
                remover.join()
                h.close()
                if os.path.exists(fn):
                    os.unlink(fn)

    # The implementation relies on os.register_at_fork existing, but we test
    # based on os.fork existing because that is what users and this test use.
    # This helps ensure that when fork exists (the important concept) that the
    # register_at_fork mechanism is also present and used.
    @unittest.skipIf(not hasattr(os, 'fork'), 'Test requires os.fork().')
    def test_post_fork_child_no_deadlock(self):
        """Ensure child logging locks are not held; bpo-6721 & bpo-36533."""
        class _OurHandler(logging.Handler):
            def __init__(self):
                super().__init__()
                self.sub_handler = logging.StreamHandler(
                    stream=open('/dev/null', 'wt'))

            def emit(self, record):
                self.sub_handler.acquire()
                try:
                    self.sub_handler.emit(record)
                finally:
                    self.sub_handler.release()

        self.assertEqual(len(logging._handlers), 0)
        refed_h = _OurHandler()
        self.addCleanup(refed_h.sub_handler.stream.close)
        refed_h.name = 'because we need at least one for this test'
        self.assertGreater(len(logging._handlers), 0)
        self.assertGreater(len(logging._at_fork_reinit_lock_weakset), 1)
        test_logger = logging.getLogger('test_post_fork_child_no_deadlock')
        test_logger.addHandler(refed_h)
        test_logger.setLevel(logging.DEBUG)

        locks_held__ready_to_fork = threading.Event()
        fork_happened__release_locks_and_end_thread = threading.Event()

        def lock_holder_thread_fn():
            logging._acquireLock()
            try:
                refed_h.acquire()
                try:
                    # Tell the main thread to do the fork.
                    locks_held__ready_to_fork.set()

                    # If the deadlock bug exists, the fork will happen
                    # without dealing with the locks we hold, deadlocking
                    # the child.

                    # Wait for a successful fork or an unreasonable amount of
                    # time before releasing our locks.  To avoid a timing based
                    # test we'd need communication from os.fork() as to when it
                    # has actually happened.  Given this is a regression test
                    # for a fixed issue, potentially less reliably detecting
                    # regression via timing is acceptable for simplicity.
                    # The test will always take at least this long. :(
                    fork_happened__release_locks_and_end_thread.wait(0.5)
                finally:
                    refed_h.release()
            finally:
                logging._releaseLock()

        lock_holder_thread = threading.Thread(
                target=lock_holder_thread_fn,
                name='test_post_fork_child_no_deadlock lock holder')
        lock_holder_thread.start()

        locks_held__ready_to_fork.wait()
        pid = os.fork()
        if pid == 0:  # Child.
            try:
                test_logger.info(r'Child process did not deadlock. \o/')
            finally:
                os._exit(0)
        else:  # Parent.
            test_logger.info(r'Parent process returned from fork. \o/')
            fork_happened__release_locks_and_end_thread.set()
            lock_holder_thread.join()
            start_time = time.monotonic()
            while True:
                test_logger.debug('Waiting for child process.')
                waited_pid, status = os.waitpid(pid, os.WNOHANG)
                if waited_pid == pid:
                    break  # child process exited.
                if time.monotonic() - start_time > 7:
                    break  # so long? implies child deadlock.
                time.sleep(0.05)
            test_logger.debug('Done waiting.')
            if waited_pid != pid:
                os.kill(pid, signal.SIGKILL)
                waited_pid, status = os.waitpid(pid, 0)
                self.fail("child process deadlocked.")
            self.assertEqual(status, 0, msg="child process error")


class BadStream(object):
    def write(self, data):
        raise RuntimeError('deliberate mistake')

class TestStreamHandler(logging.StreamHandler):
    def handleError(self, record):
        self.error_record = record

class StreamWithIntName(object):
    level = logging.NOTSET
    name = 2

class StreamHandlerTest(BaseTest):
    def test_error_handling(self):
        h = TestStreamHandler(BadStream())
        r = logging.makeLogRecord({})
        old_raise = logging.raiseExceptions

        try:
            h.handle(r)
            self.assertIs(h.error_record, r)

            h = logging.StreamHandler(BadStream())
            with support.captured_stderr() as stderr:
                h.handle(r)
                msg = '\nRuntimeError: deliberate mistake\n'
                self.assertIn(msg, stderr.getvalue())

            logging.raiseExceptions = False
            with support.captured_stderr() as stderr:
                h.handle(r)
                self.assertEqual('', stderr.getvalue())
        finally:
            logging.raiseExceptions = old_raise

    def test_stream_setting(self):
        """
        Test setting the handler's stream
        """
        h = logging.StreamHandler()
        stream = io.StringIO()
        old = h.setStream(stream)
        self.assertIs(old, sys.stderr)
        actual = h.setStream(old)
        self.assertIs(actual, stream)
        # test that setting to existing value returns None
        actual = h.setStream(old)
        self.assertIsNone(actual)

    def test_can_represent_stream_with_int_name(self):
        h = logging.StreamHandler(StreamWithIntName())
        self.assertEqual(repr(h), '<StreamHandler 2 (NOTSET)>')

# -- The following section could be moved into a server_helper.py module
# -- if it proves to be of wider utility than just test_logging

class TestSMTPServer(smtpd.SMTPServer):
    """
    This class implements a test SMTP server.

    :param addr: A (host, port) tuple which the server listens on.
                 You can specify a port value of zero: the server's
                 *port* attribute will hold the actual port number
                 used, which can be used in client connections.
    :param handler: A callable which will be called to process
                    incoming messages. The handler will be passed
                    the client address tuple, who the message is from,
                    a list of recipients and the message data.
    :param poll_interval: The interval, in seconds, used in the underlying
                          :func:`select` or :func:`poll` call by
                          :func:`asyncore.loop`.
    :param sockmap: A dictionary which will be used to hold
                    :class:`asyncore.dispatcher` instances used by
                    :func:`asyncore.loop`. This avoids changing the
                    :mod:`asyncore` module's global state.
    """

    def __init__(self, addr, handler, poll_interval, sockmap):
        smtpd.SMTPServer.__init__(self, addr, None, map=sockmap,
                                  decode_data=True)
        self.port = self.socket.getsockname()[1]
        self._handler = handler
        self._thread = None
        self.poll_interval = poll_interval

    def process_message(self, peer, mailfrom, rcpttos, data):
        """
        Delegates to the handler passed in to the server's constructor.

        Typically, this will be a test case method.
        :param peer: The client (host, port) tuple.
        :param mailfrom: The address of the sender.
        :param rcpttos: The addresses of the recipients.
        :param data: The message.
        """
        self._handler(peer, mailfrom, rcpttos, data)

    def start(self):
        """
        Start the server running on a separate daemon thread.
        """
        self._thread = t = threading.Thread(target=self.serve_forever,
                                            args=(self.poll_interval,))
        t.setDaemon(True)
        t.start()

    def serve_forever(self, poll_interval):
        """
        Run the :mod:`asyncore` loop until normal termination
        conditions arise.
        :param poll_interval: The interval, in seconds, used in the underlying
                              :func:`select` or :func:`poll` call by
                              :func:`asyncore.loop`.
        """
        asyncore.loop(poll_interval, map=self._map)

    def stop(self, timeout=None):
        """
        Stop the thread by closing the server instance.
        Wait for the server thread to terminate.

        :param timeout: How long to wait for the server thread
                        to terminate.
        """
        self.close()
        support.join_thread(self._thread, timeout)
        self._thread = None
        asyncore.close_all(map=self._map, ignore_all=True)


class ControlMixin(object):
    """
    This mixin is used to start a server on a separate thread, and
    shut it down programmatically. Request handling is simplified - instead
    of needing to derive a suitable RequestHandler subclass, you just
    provide a callable which will be passed each received request to be
    processed.

    :param handler: A handler callable which will be called with a
                    single parameter - the request - in order to
                    process the request. This handler is called on the
                    server thread, effectively meaning that requests are
                    processed serially. While not quite Web scale ;-),
                    this should be fine for testing applications.
    :param poll_interval: The polling interval in seconds.
    """
    def __init__(self, handler, poll_interval):
        self._thread = None
        self.poll_interval = poll_interval
        self._handler = handler
        self.ready = threading.Event()

    def start(self):
        """
        Create a daemon thread to run the server, and start it.
        """
        self._thread = t = threading.Thread(target=self.serve_forever,
                                            args=(self.poll_interval,))
        t.setDaemon(True)
        t.start()

    def serve_forever(self, poll_interval):
        """
        Run the server. Set the ready flag before entering the
        service loop.
        """
        self.ready.set()
        super(ControlMixin, self).serve_forever(poll_interval)

    def stop(self, timeout=None):
        """
        Tell the server thread to stop, and wait for it to do so.

        :param timeout: How long to wait for the server thread
                        to terminate.
        """
        self.shutdown()
        if self._thread is not None:
            support.join_thread(self._thread, timeout)
            self._thread = None
        self.server_close()
        self.ready.clear()

class TestHTTPServer(ControlMixin, HTTPServer):
    """
    An HTTP server which is controllable using :class:`ControlMixin`.

    :param addr: A tuple with the IP address and port to listen on.
    :param handler: A handler callable which will be called with a
                    single parameter - the request - in order to
                    process the request.
    :param poll_interval: The polling interval in seconds.
    :param log: Pass ``True`` to enable log messages.
    """
    def __init__(self, addr, handler, poll_interval=0.5,
                 log=False, sslctx=None):
        class DelegatingHTTPRequestHandler(BaseHTTPRequestHandler):
            def __getattr__(self, name, default=None):
                if name.startswith('do_'):
                    return self.process_request
                raise AttributeError(name)

            def process_request(self):
                self.server._handler(self)

            def log_message(self, format, *args):
                if log:
                    super(DelegatingHTTPRequestHandler,
                          self).log_message(format, *args)
        HTTPServer.__init__(self, addr, DelegatingHTTPRequestHandler)
        ControlMixin.__init__(self, handler, poll_interval)
        self.sslctx = sslctx

    def get_request(self):
        try:
            sock, addr = self.socket.accept()
            if self.sslctx:
                sock = self.sslctx.wrap_socket(sock, server_side=True)
        except OSError as e:
            # socket errors are silenced by the caller, print them here
            sys.stderr.write("Got an error:\n%s\n" % e)
            raise
        return sock, addr

class TestTCPServer(ControlMixin, ThreadingTCPServer):
    """
    A TCP server which is controllable using :class:`ControlMixin`.

    :param addr: A tuple with the IP address and port to listen on.
    :param handler: A handler callable which will be called with a single
                    parameter - the request - in order to process the request.
    :param poll_interval: The polling interval in seconds.
    :bind_and_activate: If True (the default), binds the server and starts it
                        listening. If False, you need to call
                        :meth:`server_bind` and :meth:`server_activate` at
                        some later time before calling :meth:`start`, so that
                        the server will set up the socket and listen on it.
    """

    allow_reuse_address = True

    def __init__(self, addr, handler, poll_interval=0.5,
                 bind_and_activate=True):
        class DelegatingTCPRequestHandler(StreamRequestHandler):

            def handle(self):
                self.server._handler(self)
        ThreadingTCPServer.__init__(self, addr, DelegatingTCPRequestHandler,
                                    bind_and_activate)
        ControlMixin.__init__(self, handler, poll_interval)

    def server_bind(self):
        super(TestTCPServer, self).server_bind()
        self.port = self.socket.getsockname()[1]

class TestUDPServer(ControlMixin, ThreadingUDPServer):
    """
    A UDP server which is controllable using :class:`ControlMixin`.

    :param addr: A tuple with the IP address and port to listen on.
    :param handler: A handler callable which will be called with a
                    single parameter - the request - in order to
                    process the request.
    :param poll_interval: The polling interval for shutdown requests,
                          in seconds.
    :bind_and_activate: If True (the default), binds the server and
                        starts it listening. If False, you need to
                        call :meth:`server_bind` and
                        :meth:`server_activate` at some later time
                        before calling :meth:`start`, so that the server will
                        set up the socket and listen on it.
    """
    def __init__(self, addr, handler, poll_interval=0.5,
                 bind_and_activate=True):
        class DelegatingUDPRequestHandler(DatagramRequestHandler):

            def handle(self):
                self.server._handler(self)

            def finish(self):
                data = self.wfile.getvalue()
                if data:
                    try:
                        super(DelegatingUDPRequestHandler, self).finish()
                    except OSError:
                        if not self.server._closed:
                            raise

        ThreadingUDPServer.__init__(self, addr,
                                    DelegatingUDPRequestHandler,
                                    bind_and_activate)
        ControlMixin.__init__(self, handler, poll_interval)
        self._closed = False

    def server_bind(self):
        super(TestUDPServer, self).server_bind()
        self.port = self.socket.getsockname()[1]

    def server_close(self):
        super(TestUDPServer, self).server_close()
        self._closed = True

if hasattr(socket, "AF_UNIX"):
    class TestUnixStreamServer(TestTCPServer):
        address_family = socket.AF_UNIX

    class TestUnixDatagramServer(TestUDPServer):
        address_family = socket.AF_UNIX

# - end of server_helper section

class SMTPHandlerTest(BaseTest):
    # bpo-14314, bpo-19665, bpo-34092: don't wait forever, timeout of 1 minute
    TIMEOUT = 60.0

    def test_basic(self):
        sockmap = {}
        server = TestSMTPServer((support.HOST, 0), self.process_message, 0.001,
                                sockmap)
        server.start()
        addr = (support.HOST, server.port)
        h = logging.handlers.SMTPHandler(addr, 'me', 'you', 'Log',
                                         timeout=self.TIMEOUT)
        self.assertEqual(h.toaddrs, ['you'])
        self.messages = []
        r = logging.makeLogRecord({'msg': 'Hello \u2713'})
        self.handled = threading.Event()
        h.handle(r)
        self.handled.wait(self.TIMEOUT)
        server.stop()
        self.assertTrue(self.handled.is_set())
        self.assertEqual(len(self.messages), 1)
        peer, mailfrom, rcpttos, data = self.messages[0]
        self.assertEqual(mailfrom, 'me')
        self.assertEqual(rcpttos, ['you'])
        self.assertIn('\nSubject: Log\n', data)
        self.assertTrue(data.endswith('\n\nHello \u2713'))
        h.close()

    def process_message(self, *args):
        self.messages.append(args)
        self.handled.set()

class MemoryHandlerTest(BaseTest):

    """Tests for the MemoryHandler."""

    # Do not bother with a logger name group.
    expected_log_pat = r"^[\w.]+ -> (\w+): (\d+)$"

    def setUp(self):
        BaseTest.setUp(self)
        self.mem_hdlr = logging.handlers.MemoryHandler(10, logging.WARNING,
                                                       self.root_hdlr)
        self.mem_logger = logging.getLogger('mem')
        self.mem_logger.propagate = 0
        self.mem_logger.addHandler(self.mem_hdlr)

    def tearDown(self):
        self.mem_hdlr.close()
        BaseTest.tearDown(self)

    def test_flush(self):
        # The memory handler flushes to its target handler based on specific
        #  criteria (message count and message level).
        self.mem_logger.debug(self.next_message())
        self.assert_log_lines([])
        self.mem_logger.info(self.next_message())
        self.assert_log_lines([])
        # This will flush because the level is >= logging.WARNING
        self.mem_logger.warning(self.next_message())
        lines = [
            ('DEBUG', '1'),
            ('INFO', '2'),
            ('WARNING', '3'),
        ]
        self.assert_log_lines(lines)
        for n in (4, 14):
            for i in range(9):
                self.mem_logger.debug(self.next_message())
            self.assert_log_lines(lines)
            # This will flush because it's the 10th message since the last
            #  flush.
            self.mem_logger.debug(self.next_message())
            lines = lines + [('DEBUG', str(i)) for i in range(n, n + 10)]
            self.assert_log_lines(lines)

        self.mem_logger.debug(self.next_message())
        self.assert_log_lines(lines)

    def test_flush_on_close(self):
        """
        Test that the flush-on-close configuration works as expected.
        """
        self.mem_logger.debug(self.next_message())
        self.assert_log_lines([])
        self.mem_logger.info(self.next_message())
        self.assert_log_lines([])
        self.mem_logger.removeHandler(self.mem_hdlr)
        # Default behaviour is to flush on close. Check that it happens.
        self.mem_hdlr.close()
        lines = [
            ('DEBUG', '1'),
            ('INFO', '2'),
        ]
        self.assert_log_lines(lines)
        # Now configure for flushing not to be done on close.
        self.mem_hdlr = logging.handlers.MemoryHandler(10, logging.WARNING,
                                                       self.root_hdlr,
                                                       False)
        self.mem_logger.addHandler(self.mem_hdlr)
        self.mem_logger.debug(self.next_message())
        self.assert_log_lines(lines)  # no change
        self.mem_logger.info(self.next_message())
        self.assert_log_lines(lines)  # no change
        self.mem_logger.removeHandler(self.mem_hdlr)
        self.mem_hdlr.close()
        # assert that no new lines have been added
        self.assert_log_lines(lines)  # no change


class ExceptionFormatter(logging.Formatter):
    """A special exception formatter."""
    def formatException(self, ei):
        return "Got a [%s]" % ei[0].__name__


class ConfigFileTest(BaseTest):

    """Reading logging config from a .ini-style config file."""

    check_no_resource_warning = support.check_no_resource_warning
    expected_log_pat = r"^(\w+) \+\+ (\w+)$"

    # config0 is a standard configuration.
    config0 = """
    [loggers]
    keys=root

    [handlers]
    keys=hand1

    [formatters]
    keys=form1

    [logger_root]
    level=WARNING
    handlers=hand1

    [handler_hand1]
    class=StreamHandler
    level=NOTSET
    formatter=form1
    args=(sys.stdout,)

    [formatter_form1]
    format=%(levelname)s ++ %(message)s
    datefmt=
    """

    # config1 adds a little to the standard configuration.
    config1 = """
    [loggers]
    keys=root,parser

    [handlers]
    keys=hand1

    [formatters]
    keys=form1

    [logger_root]
    level=WARNING
    handlers=

    [logger_parser]
    level=DEBUG
    handlers=hand1
    propagate=1
    qualname=compiler.parser

    [handler_hand1]
    class=StreamHandler
    level=NOTSET
    formatter=form1
    args=(sys.stdout,)

    [formatter_form1]
    format=%(levelname)s ++ %(message)s
    datefmt=
    """

    # config1a moves the handler to the root.
    config1a = """
    [loggers]
    keys=root,parser

    [handlers]
    keys=hand1

    [formatters]
    keys=form1

    [logger_root]
    level=WARNING
    handlers=hand1

    [logger_parser]
    level=DEBUG
    handlers=
    propagate=1
    qualname=compiler.parser

    [handler_hand1]
    class=StreamHandler
    level=NOTSET
    formatter=form1
    args=(sys.stdout,)

    [formatter_form1]
    format=%(levelname)s ++ %(message)s
    datefmt=
    """

    # config2 has a subtle configuration error that should be reported
    config2 = config1.replace("sys.stdout", "sys.stbout")

    # config3 has a less subtle configuration error
    config3 = config1.replace("formatter=form1", "formatter=misspelled_name")

    # config4 specifies a custom formatter class to be loaded
    config4 = """
    [loggers]
    keys=root

    [handlers]
    keys=hand1

    [formatters]
    keys=form1

    [logger_root]
    level=NOTSET
    handlers=hand1

    [handler_hand1]
    class=StreamHandler
    level=NOTSET
    formatter=form1
    args=(sys.stdout,)

    [formatter_form1]
    class=""" + __name__ + """.ExceptionFormatter
    format=%(levelname)s:%(name)s:%(message)s
    datefmt=
    """

    # config5 specifies a custom handler class to be loaded
    config5 = config1.replace('class=StreamHandler', 'class=logging.StreamHandler')

    # config6 uses ', ' delimiters in the handlers and formatters sections
    config6 = """
    [loggers]
    keys=root,parser

    [handlers]
    keys=hand1, hand2

    [formatters]
    keys=form1, form2

    [logger_root]
    level=WARNING
    handlers=

    [logger_parser]
    level=DEBUG
    handlers=hand1
    propagate=1
    qualname=compiler.parser

    [handler_hand1]
    class=StreamHandler
    level=NOTSET
    formatter=form1
    args=(sys.stdout,)

    [handler_hand2]
    class=StreamHandler
    level=NOTSET
    formatter=form1
    args=(sys.stderr,)

    [formatter_form1]
    format=%(levelname)s ++ %(message)s
    datefmt=

    [formatter_form2]
    format=%(message)s
    datefmt=
    """

    # config7 adds a compiler logger, and uses kwargs instead of args.
    config7 = """
    [loggers]
    keys=root,parser,compiler

    [handlers]
    keys=hand1

    [formatters]
    keys=form1

    [logger_root]
    level=WARNING
    handlers=hand1

    [logger_compiler]
    level=DEBUG
    handlers=
    propagate=1
    qualname=compiler

    [logger_parser]
    level=DEBUG
    handlers=
    propagate=1
    qualname=compiler.parser

    [handler_hand1]
    class=StreamHandler
    level=NOTSET
    formatter=form1
    kwargs={'stream': sys.stdout,}

    [formatter_form1]
    format=%(levelname)s ++ %(message)s
    datefmt=
    """

    # config 8, check for resource warning
    config8 = r"""
    [loggers]
    keys=root

    [handlers]
    keys=file

    [formatters]
    keys=

    [logger_root]
    level=DEBUG
    handlers=file

    [handler_file]
    class=FileHandler
    level=DEBUG
    args=("{tempfile}",)
    """

    disable_test = """
    [loggers]
    keys=root

    [handlers]
    keys=screen

    [formatters]
    keys=

    [logger_root]
    level=DEBUG
    handlers=screen

    [handler_screen]
    level=DEBUG
    class=StreamHandler
    args=(sys.stdout,)
    formatter=
    """

    def apply_config(self, conf, **kwargs):
        file = io.StringIO(textwrap.dedent(conf))
        logging.config.fileConfig(file, **kwargs)

    def test_config0_ok(self):
        # A simple config file which overrides the default settings.
        with support.captured_stdout() as output:
            self.apply_config(self.config0)
            logger = logging.getLogger()
            # Won't output anything
            logger.info(self.next_message())
            # Outputs a message
            logger.error(self.next_message())
            self.assert_log_lines([
                ('ERROR', '2'),
            ], stream=output)
            # Original logger output is empty.
            self.assert_log_lines([])

    def test_config0_using_cp_ok(self):
        # A simple config file which overrides the default settings.
        with support.captured_stdout() as output:
            file = io.StringIO(textwrap.dedent(self.config0))
            cp = configparser.ConfigParser()
            cp.read_file(file)
            logging.config.fileConfig(cp)
            logger = logging.getLogger()
            # Won't output anything
            logger.info(self.next_message())
            # Outputs a message
            logger.error(self.next_message())
            self.assert_log_lines([
                ('ERROR', '2'),
            ], stream=output)
            # Original logger output is empty.
            self.assert_log_lines([])

    def test_config1_ok(self, config=config1):
        # A config file defining a sub-parser as well.
        with support.captured_stdout() as output:
            self.apply_config(config)
            logger = logging.getLogger("compiler.parser")
            # Both will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
            self.assert_log_lines([
                ('INFO', '1'),
                ('ERROR', '2'),
            ], stream=output)
            # Original logger output is empty.
            self.assert_log_lines([])

    def test_config2_failure(self):
        # A simple config file which overrides the default settings.
        self.assertRaises(Exception, self.apply_config, self.config2)

    def test_config3_failure(self):
        # A simple config file which overrides the default settings.
        self.assertRaises(Exception, self.apply_config, self.config3)

    def test_config4_ok(self):
        # A config file specifying a custom formatter class.
        with support.captured_stdout() as output:
            self.apply_config(self.config4)
            logger = logging.getLogger()
            try:
                raise RuntimeError()
            except RuntimeError:
                logging.exception("just testing")
            sys.stdout.seek(0)
            self.assertEqual(output.getvalue(),
                "ERROR:root:just testing\nGot a [RuntimeError]\n")
            # Original logger output is empty
            self.assert_log_lines([])

    def test_config5_ok(self):
        self.test_config1_ok(config=self.config5)

    def test_config6_ok(self):
        self.test_config1_ok(config=self.config6)

    def test_config7_ok(self):
        with support.captured_stdout() as output:
            self.apply_config(self.config1a)
            logger = logging.getLogger("compiler.parser")
            # See issue #11424. compiler-hyphenated sorts
            # between compiler and compiler.xyz and this
            # was preventing compiler.xyz from being included
            # in the child loggers of compiler because of an
            # overzealous loop termination condition.
            hyphenated = logging.getLogger('compiler-hyphenated')
            # All will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
            hyphenated.critical(self.next_message())
            self.assert_log_lines([
                ('INFO', '1'),
                ('ERROR', '2'),
                ('CRITICAL', '3'),
            ], stream=output)
            # Original logger output is empty.
            self.assert_log_lines([])
        with support.captured_stdout() as output:
            self.apply_config(self.config7)
            logger = logging.getLogger("compiler.parser")
            self.assertFalse(logger.disabled)
            # Both will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
            logger = logging.getLogger("compiler.lexer")
            # Both will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
            # Will not appear
            hyphenated.critical(self.next_message())
            self.assert_log_lines([
                ('INFO', '4'),
                ('ERROR', '5'),
                ('INFO', '6'),
                ('ERROR', '7'),
            ], stream=output)
            # Original logger output is empty.
            self.assert_log_lines([])

    def test_config8_ok(self):

        def cleanup(h1, fn):
            h1.close()
            os.remove(fn)

        with self.check_no_resource_warning():
            fd, fn = tempfile.mkstemp(".log", "test_logging-X-")
            os.close(fd)

            # Replace single backslash with double backslash in windows
            # to avoid unicode error during string formatting
            if os.name == "nt":
                fn = fn.replace("\\", "\\\\")

            config8 = self.config8.format(tempfile=fn)

            self.apply_config(config8)
            self.apply_config(config8)

        handler = logging.root.handlers[0]
        self.addCleanup(cleanup, handler, fn)

    def test_logger_disabling(self):
        self.apply_config(self.disable_test)
        logger = logging.getLogger('some_pristine_logger')
        self.assertFalse(logger.disabled)
        self.apply_config(self.disable_test)
        self.assertTrue(logger.disabled)
        self.apply_config(self.disable_test, disable_existing_loggers=False)
        self.assertFalse(logger.disabled)

    def test_defaults_do_no_interpolation(self):
        """bpo-33802 defaults should not get interpolated"""
        ini = textwrap.dedent("""
            [formatters]
            keys=default

            [formatter_default]

            [handlers]
            keys=console

            [handler_console]
            class=logging.StreamHandler
            args=tuple()

            [loggers]
            keys=root

            [logger_root]
            formatter=default
            handlers=console
            """).strip()
        fd, fn = tempfile.mkstemp(prefix='test_logging_', suffix='.ini')
        try:
            os.write(fd, ini.encode('ascii'))
            os.close(fd)
            logging.config.fileConfig(
                fn,
                defaults=dict(
                    version=1,
                    disable_existing_loggers=False,
                    formatters={
                        "generic": {
                            "format": "%(asctime)s [%(process)d] [%(levelname)s] %(message)s",
                            "datefmt": "[%Y-%m-%d %H:%M:%S %z]",
                            "class": "logging.Formatter"
                        },
                    },
                )
            )
        finally:
            os.unlink(fn)


class SocketHandlerTest(BaseTest):

    """Test for SocketHandler objects."""

    server_class = TestTCPServer
    address = ('localhost', 0)

    def setUp(self):
        """Set up a TCP server to receive log messages, and a SocketHandler
        pointing to that server's address and port."""
        BaseTest.setUp(self)
        # Issue #29177: deal with errors that happen during setup
        self.server = self.sock_hdlr = self.server_exception = None
        try:
            self.server = server = self.server_class(self.address,
                                                     self.handle_socket, 0.01)
            server.start()
            # Uncomment next line to test error recovery in setUp()
            # raise OSError('dummy error raised')
        except OSError as e:
            self.server_exception = e
            return
        server.ready.wait()
        hcls = logging.handlers.SocketHandler
        if isinstance(server.server_address, tuple):
            self.sock_hdlr = hcls('localhost', server.port)
        else:
            self.sock_hdlr = hcls(server.server_address, None)
        self.log_output = ''
        self.root_logger.removeHandler(self.root_logger.handlers[0])
        self.root_logger.addHandler(self.sock_hdlr)
        self.handled = threading.Semaphore(0)

    def tearDown(self):
        """Shutdown the TCP server."""
        try:
            if self.sock_hdlr:
                self.root_logger.removeHandler(self.sock_hdlr)
                self.sock_hdlr.close()
            if self.server:
                self.server.stop(2.0)
        finally:
            BaseTest.tearDown(self)

    def handle_socket(self, request):
        conn = request.connection
        while True:
            chunk = conn.recv(4)
            if len(chunk) < 4:
                break
            slen = struct.unpack(">L", chunk)[0]
            chunk = conn.recv(slen)
            while len(chunk) < slen:
                chunk = chunk + conn.recv(slen - len(chunk))
            obj = pickle.loads(chunk)
            record = logging.makeLogRecord(obj)
            self.log_output += record.msg + '\n'
            self.handled.release()

    def test_output(self):
        # The log message sent to the SocketHandler is properly received.
        if self.server_exception:
            self.skipTest(self.server_exception)
        logger = logging.getLogger("tcp")
        logger.error("spam")
        self.handled.acquire()
        logger.debug("eggs")
        self.handled.acquire()
        self.assertEqual(self.log_output, "spam\neggs\n")

    def test_noserver(self):
        if self.server_exception:
            self.skipTest(self.server_exception)
        # Avoid timing-related failures due to SocketHandler's own hard-wired
        # one-second timeout on socket.create_connection() (issue #16264).
        self.sock_hdlr.retryStart = 2.5
        # Kill the server
        self.server.stop(2.0)
        # The logging call should try to connect, which should fail
        try:
            raise RuntimeError('Deliberate mistake')
        except RuntimeError:
            self.root_logger.exception('Never sent')
        self.root_logger.error('Never sent, either')
        now = time.time()
        self.assertGreater(self.sock_hdlr.retryTime, now)
        time.sleep(self.sock_hdlr.retryTime - now + 0.001)
        self.root_logger.error('Nor this')

def _get_temp_domain_socket():
    fd, fn = tempfile.mkstemp(prefix='test_logging_', suffix='.sock')
    os.close(fd)
    # just need a name - file can't be present, or we'll get an
    # 'address already in use' error.
    os.remove(fn)
    return fn

@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
class UnixSocketHandlerTest(SocketHandlerTest):

    """Test for SocketHandler with unix sockets."""

    if hasattr(socket, "AF_UNIX"):
        server_class = TestUnixStreamServer

    def setUp(self):
        # override the definition in the base class
        self.address = _get_temp_domain_socket()
        SocketHandlerTest.setUp(self)

    def tearDown(self):
        SocketHandlerTest.tearDown(self)
        support.unlink(self.address)

class DatagramHandlerTest(BaseTest):

    """Test for DatagramHandler."""

    server_class = TestUDPServer
    address = ('localhost', 0)

    def setUp(self):
        """Set up a UDP server to receive log messages, and a DatagramHandler
        pointing to that server's address and port."""
        BaseTest.setUp(self)
        # Issue #29177: deal with errors that happen during setup
        self.server = self.sock_hdlr = self.server_exception = None
        try:
            self.server = server = self.server_class(self.address,
                                                     self.handle_datagram, 0.01)
            server.start()
            # Uncomment next line to test error recovery in setUp()
            # raise OSError('dummy error raised')
        except OSError as e:
            self.server_exception = e
            return
        server.ready.wait()
        hcls = logging.handlers.DatagramHandler
        if isinstance(server.server_address, tuple):
            self.sock_hdlr = hcls('localhost', server.port)
        else:
            self.sock_hdlr = hcls(server.server_address, None)
        self.log_output = ''
        self.root_logger.removeHandler(self.root_logger.handlers[0])
        self.root_logger.addHandler(self.sock_hdlr)
        self.handled = threading.Event()

    def tearDown(self):
        """Shutdown the UDP server."""
        try:
            if self.server:
                self.server.stop(2.0)
            if self.sock_hdlr:
                self.root_logger.removeHandler(self.sock_hdlr)
                self.sock_hdlr.close()
        finally:
            BaseTest.tearDown(self)

    def handle_datagram(self, request):
        slen = struct.pack('>L', 0) # length of prefix
        packet = request.packet[len(slen):]
        obj = pickle.loads(packet)
        record = logging.makeLogRecord(obj)
        self.log_output += record.msg + '\n'
        self.handled.set()

    def test_output(self):
        # The log message sent to the DatagramHandler is properly received.
        if self.server_exception:
            self.skipTest(self.server_exception)
        logger = logging.getLogger("udp")
        logger.error("spam")
        self.handled.wait()
        self.handled.clear()
        logger.error("eggs")
        self.handled.wait()
        self.assertEqual(self.log_output, "spam\neggs\n")

@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
class UnixDatagramHandlerTest(DatagramHandlerTest):

    """Test for DatagramHandler using Unix sockets."""

    if hasattr(socket, "AF_UNIX"):
        server_class = TestUnixDatagramServer

    def setUp(self):
        # override the definition in the base class
        self.address = _get_temp_domain_socket()
        DatagramHandlerTest.setUp(self)

    def tearDown(self):
        DatagramHandlerTest.tearDown(self)
        support.unlink(self.address)

class SysLogHandlerTest(BaseTest):

    """Test for SysLogHandler using UDP."""

    server_class = TestUDPServer
    address = ('localhost', 0)

    def setUp(self):
        """Set up a UDP server to receive log messages, and a SysLogHandler
        pointing to that server's address and port."""
        BaseTest.setUp(self)
        # Issue #29177: deal with errors that happen during setup
        self.server = self.sl_hdlr = self.server_exception = None
        try:
            self.server = server = self.server_class(self.address,
                                                     self.handle_datagram, 0.01)
            server.start()
            # Uncomment next line to test error recovery in setUp()
            # raise OSError('dummy error raised')
        except OSError as e:
            self.server_exception = e
            return
        server.ready.wait()
        hcls = logging.handlers.SysLogHandler
        if isinstance(server.server_address, tuple):
            self.sl_hdlr = hcls((server.server_address[0], server.port))
        else:
            self.sl_hdlr = hcls(server.server_address)
        self.log_output = ''
        self.root_logger.removeHandler(self.root_logger.handlers[0])
        self.root_logger.addHandler(self.sl_hdlr)
        self.handled = threading.Event()

    def tearDown(self):
        """Shutdown the server."""
        try:
            if self.server:
                self.server.stop(2.0)
            if self.sl_hdlr:
                self.root_logger.removeHandler(self.sl_hdlr)
                self.sl_hdlr.close()
        finally:
            BaseTest.tearDown(self)

    def handle_datagram(self, request):
        self.log_output = request.packet
        self.handled.set()

    def test_output(self):
        if self.server_exception:
            self.skipTest(self.server_exception)
        # The log message sent to the SysLogHandler is properly received.
        logger = logging.getLogger("slh")
        logger.error("sp\xe4m")
        self.handled.wait()
        self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m\x00')
        self.handled.clear()
        self.sl_hdlr.append_nul = False
        logger.error("sp\xe4m")
        self.handled.wait()
        self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m')
        self.handled.clear()
        self.sl_hdlr.ident = "h\xe4m-"
        logger.error("sp\xe4m")
        self.handled.wait()
        self.assertEqual(self.log_output, b'<11>h\xc3\xa4m-sp\xc3\xa4m')

@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
class UnixSysLogHandlerTest(SysLogHandlerTest):

    """Test for SysLogHandler with Unix sockets."""

    if hasattr(socket, "AF_UNIX"):
        server_class = TestUnixDatagramServer

    def setUp(self):
        # override the definition in the base class
        self.address = _get_temp_domain_socket()
        SysLogHandlerTest.setUp(self)

    def tearDown(self):
        SysLogHandlerTest.tearDown(self)
        support.unlink(self.address)

@unittest.skipUnless(support.IPV6_ENABLED,
                     'IPv6 support required for this test.')
class IPv6SysLogHandlerTest(SysLogHandlerTest):

    """Test for SysLogHandler with IPv6 host."""

    server_class = TestUDPServer
    address = ('::1', 0)

    def setUp(self):
        self.server_class.address_family = socket.AF_INET6
        super(IPv6SysLogHandlerTest, self).setUp()

    def tearDown(self):
        self.server_class.address_family = socket.AF_INET
        super(IPv6SysLogHandlerTest, self).tearDown()

class HTTPHandlerTest(BaseTest):
    """Test for HTTPHandler."""

    def setUp(self):
        """Set up an HTTP server to receive log messages, and a HTTPHandler
        pointing to that server's address and port."""
        BaseTest.setUp(self)
        self.handled = threading.Event()

    def handle_request(self, request):
        self.command = request.command
        self.log_data = urlparse(request.path)
        if self.command == 'POST':
            try:
                rlen = int(request.headers['Content-Length'])
                self.post_data = request.rfile.read(rlen)
            except:
                self.post_data = None
        request.send_response(200)
        request.end_headers()
        self.handled.set()

    def test_output(self):
        # The log message sent to the HTTPHandler is properly received.
        logger = logging.getLogger("http")
        root_logger = self.root_logger
        root_logger.removeHandler(self.root_logger.handlers[0])
        for secure in (False, True):
            addr = ('localhost', 0)
            if secure:
                try:
                    import ssl
                except ImportError:
                    sslctx = None
                else:
                    here = os.path.dirname(__file__)
                    localhost_cert = os.path.join(here, "keycert.pem")
                    sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
                    sslctx.load_cert_chain(localhost_cert)

                    context = ssl.create_default_context(cafile=localhost_cert)
            else:
                sslctx = None
                context = None
            self.server = server = TestHTTPServer(addr, self.handle_request,
                                                    0.01, sslctx=sslctx)
            server.start()
            server.ready.wait()
            host = 'localhost:%d' % server.server_port
            secure_client = secure and sslctx
            self.h_hdlr = logging.handlers.HTTPHandler(host, '/frob',
                                                       secure=secure_client,
                                                       context=context,
                                                       credentials=('foo', 'bar'))
            self.log_data = None
            root_logger.addHandler(self.h_hdlr)

            for method in ('GET', 'POST'):
                self.h_hdlr.method = method
                self.handled.clear()
                msg = "sp\xe4m"
                logger.error(msg)
                self.handled.wait()
                self.assertEqual(self.log_data.path, '/frob')
                self.assertEqual(self.command, method)
                if method == 'GET':
                    d = parse_qs(self.log_data.query)
                else:
                    d = parse_qs(self.post_data.decode('utf-8'))
                self.assertEqual(d['name'], ['http'])
                self.assertEqual(d['funcName'], ['test_output'])
                self.assertEqual(d['msg'], [msg])

            self.server.stop(2.0)
            self.root_logger.removeHandler(self.h_hdlr)
            self.h_hdlr.close()

class MemoryTest(BaseTest):

    """Test memory persistence of logger objects."""

    def setUp(self):
        """Create a dict to remember potentially destroyed objects."""
        BaseTest.setUp(self)
        self._survivors = {}

    def _watch_for_survival(self, *args):
        """Watch the given objects for survival, by creating weakrefs to
        them."""
        for obj in args:
            key = id(obj), repr(obj)
            self._survivors[key] = weakref.ref(obj)

    def _assertTruesurvival(self):
        """Assert that all objects watched for survival have survived."""
        # Trigger cycle breaking.
        gc.collect()
        dead = []
        for (id_, repr_), ref in self._survivors.items():
            if ref() is None:
                dead.append(repr_)
        if dead:
            self.fail("%d objects should have survived "
                "but have been destroyed: %s" % (len(dead), ", ".join(dead)))

    def test_persistent_loggers(self):
        # Logger objects are persistent and retain their configuration, even
        #  if visible references are destroyed.
        self.root_logger.setLevel(logging.INFO)
        foo = logging.getLogger("foo")
        self._watch_for_survival(foo)
        foo.setLevel(logging.DEBUG)
        self.root_logger.debug(self.next_message())
        foo.debug(self.next_message())
        self.assert_log_lines([
            ('foo', 'DEBUG', '2'),
        ])
        del foo
        # foo has survived.
        self._assertTruesurvival()
        # foo has retained its settings.
        bar = logging.getLogger("foo")
        bar.debug(self.next_message())
        self.assert_log_lines([
            ('foo', 'DEBUG', '2'),
            ('foo', 'DEBUG', '3'),
        ])


class EncodingTest(BaseTest):
    def test_encoding_plain_file(self):
        # In Python 2.x, a plain file object is treated as having no encoding.
        log = logging.getLogger("test")
        fd, fn = tempfile.mkstemp(".log", "test_logging-1-")
        os.close(fd)
        # the non-ascii data we write to the log.
        data = "foo\x80"
        try:
            handler = logging.FileHandler(fn, encoding="utf-8")
            log.addHandler(handler)
            try:
                # write non-ascii data to the log.
                log.warning(data)
            finally:
                log.removeHandler(handler)
                handler.close()
            # check we wrote exactly those bytes, ignoring trailing \n etc
            f = open(fn, encoding="utf-8")
            try:
                self.assertEqual(f.read().rstrip(), data)
            finally:
                f.close()
        finally:
            if os.path.isfile(fn):
                os.remove(fn)

    def test_encoding_cyrillic_unicode(self):
        log = logging.getLogger("test")
        # Get a message in Unicode: Do svidanya in Cyrillic (meaning goodbye)
        message = '\u0434\u043e \u0441\u0432\u0438\u0434\u0430\u043d\u0438\u044f'
        # Ensure it's written in a Cyrillic encoding
        writer_class = codecs.getwriter('cp1251')
        writer_class.encoding = 'cp1251'
        stream = io.BytesIO()
        writer = writer_class(stream, 'strict')
        handler = logging.StreamHandler(writer)
        log.addHandler(handler)
        try:
            log.warning(message)
        finally:
            log.removeHandler(handler)
            handler.close()
        # check we wrote exactly those bytes, ignoring trailing \n etc
        s = stream.getvalue()
        # Compare against what the data should be when encoded in CP-1251
        self.assertEqual(s, b'\xe4\xee \xf1\xe2\xe8\xe4\xe0\xed\xe8\xff\n')


class WarningsTest(BaseTest):

    def test_warnings(self):
        with warnings.catch_warnings():
            logging.captureWarnings(True)
            self.addCleanup(logging.captureWarnings, False)
            warnings.filterwarnings("always", category=UserWarning)
            stream = io.StringIO()
            h = logging.StreamHandler(stream)
            logger = logging.getLogger("py.warnings")
            logger.addHandler(h)
            warnings.warn("I'm warning you...")
            logger.removeHandler(h)
            s = stream.getvalue()
            h.close()
            self.assertGreater(s.find("UserWarning: I'm warning you...\n"), 0)

            # See if an explicit file uses the original implementation
            a_file = io.StringIO()
            warnings.showwarning("Explicit", UserWarning, "dummy.py", 42,
                                 a_file, "Dummy line")
            s = a_file.getvalue()
            a_file.close()
            self.assertEqual(s,
                "dummy.py:42: UserWarning: Explicit\n  Dummy line\n")

    def test_warnings_no_handlers(self):
        with warnings.catch_warnings():
            logging.captureWarnings(True)
            self.addCleanup(logging.captureWarnings, False)

            # confirm our assumption: no loggers are set
            logger = logging.getLogger("py.warnings")
            self.assertEqual(logger.handlers, [])

            warnings.showwarning("Explicit", UserWarning, "dummy.py", 42)
            self.assertEqual(len(logger.handlers), 1)
            self.assertIsInstance(logger.handlers[0], logging.NullHandler)


def formatFunc(format, datefmt=None):
    return logging.Formatter(format, datefmt)

def handlerFunc():
    return logging.StreamHandler()

class CustomHandler(logging.StreamHandler):
    pass

class ConfigDictTest(BaseTest):

    """Reading logging config from a dictionary."""

    check_no_resource_warning = support.check_no_resource_warning
    expected_log_pat = r"^(\w+) \+\+ (\w+)$"

    # config0 is a standard configuration.
    config0 = {
        'version': 1,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'root' : {
            'level' : 'WARNING',
            'handlers' : ['hand1'],
        },
    }

    # config1 adds a little to the standard configuration.
    config1 = {
        'version': 1,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'DEBUG',
                'handlers' : ['hand1'],
            },
        },
        'root' : {
            'level' : 'WARNING',
        },
    }

    # config1a moves the handler to the root. Used with config8a
    config1a = {
        'version': 1,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'DEBUG',
            },
        },
        'root' : {
            'level' : 'WARNING',
            'handlers' : ['hand1'],
        },
    }

    # config2 has a subtle configuration error that should be reported
    config2 = {
        'version': 1,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdbout',
            },
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'DEBUG',
                'handlers' : ['hand1'],
            },
        },
        'root' : {
            'level' : 'WARNING',
        },
    }

    # As config1 but with a misspelt level on a handler
    config2a = {
        'version': 1,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NTOSET',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'DEBUG',
                'handlers' : ['hand1'],
            },
        },
        'root' : {
            'level' : 'WARNING',
        },
    }


    # As config1 but with a misspelt level on a logger
    config2b = {
        'version': 1,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'DEBUG',
                'handlers' : ['hand1'],
            },
        },
        'root' : {
            'level' : 'WRANING',
        },
    }

    # config3 has a less subtle configuration error
    config3 = {
        'version': 1,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'misspelled_name',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'DEBUG',
                'handlers' : ['hand1'],
            },
        },
        'root' : {
            'level' : 'WARNING',
        },
    }

    # config4 specifies a custom formatter class to be loaded
    config4 = {
        'version': 1,
        'formatters': {
            'form1' : {
                '()' : __name__ + '.ExceptionFormatter',
                'format' : '%(levelname)s:%(name)s:%(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'root' : {
            'level' : 'NOTSET',
                'handlers' : ['hand1'],
        },
    }

    # As config4 but using an actual callable rather than a string
    config4a = {
        'version': 1,
        'formatters': {
            'form1' : {
                '()' : ExceptionFormatter,
                'format' : '%(levelname)s:%(name)s:%(message)s',
            },
            'form2' : {
                '()' : __name__ + '.formatFunc',
                'format' : '%(levelname)s:%(name)s:%(message)s',
            },
            'form3' : {
                '()' : formatFunc,
                'format' : '%(levelname)s:%(name)s:%(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
            },
            'hand2' : {
                '()' : handlerFunc,
            },
        },
        'root' : {
            'level' : 'NOTSET',
                'handlers' : ['hand1'],
        },
    }

    # config5 specifies a custom handler class to be loaded
    config5 = {
        'version': 1,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : __name__ + '.CustomHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'DEBUG',
                'handlers' : ['hand1'],
            },
        },
        'root' : {
            'level' : 'WARNING',
        },
    }

    # config6 specifies a custom handler class to be loaded
    # but has bad arguments
    config6 = {
        'version': 1,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : __name__ + '.CustomHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
                '9' : 'invalid parameter name',
            },
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'DEBUG',
                'handlers' : ['hand1'],
            },
        },
        'root' : {
            'level' : 'WARNING',
        },
    }

    # config 7 does not define compiler.parser but defines compiler.lexer
    # so compiler.parser should be disabled after applying it
    config7 = {
        'version': 1,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'loggers' : {
            'compiler.lexer' : {
                'level' : 'DEBUG',
                'handlers' : ['hand1'],
            },
        },
        'root' : {
            'level' : 'WARNING',
        },
    }

    # config8 defines both compiler and compiler.lexer
    # so compiler.parser should not be disabled (since
    # compiler is defined)
    config8 = {
        'version': 1,
        'disable_existing_loggers' : False,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'loggers' : {
            'compiler' : {
                'level' : 'DEBUG',
                'handlers' : ['hand1'],
            },
            'compiler.lexer' : {
            },
        },
        'root' : {
            'level' : 'WARNING',
        },
    }

    # config8a disables existing loggers
    config8a = {
        'version': 1,
        'disable_existing_loggers' : True,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'loggers' : {
            'compiler' : {
                'level' : 'DEBUG',
                'handlers' : ['hand1'],
            },
            'compiler.lexer' : {
            },
        },
        'root' : {
            'level' : 'WARNING',
        },
    }

    config9 = {
        'version': 1,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'WARNING',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'WARNING',
                'handlers' : ['hand1'],
            },
        },
        'root' : {
            'level' : 'NOTSET',
        },
    }

    config9a = {
        'version': 1,
        'incremental' : True,
        'handlers' : {
            'hand1' : {
                'level' : 'WARNING',
            },
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'INFO',
            },
        },
    }

    config9b = {
        'version': 1,
        'incremental' : True,
        'handlers' : {
            'hand1' : {
                'level' : 'INFO',
            },
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'INFO',
            },
        },
    }

    # As config1 but with a filter added
    config10 = {
        'version': 1,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'filters' : {
            'filt1' : {
                'name' : 'compiler.parser',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
                'filters' : ['filt1'],
            },
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'DEBUG',
                'filters' : ['filt1'],
            },
        },
        'root' : {
            'level' : 'WARNING',
            'handlers' : ['hand1'],
        },
    }

    # As config1 but using cfg:// references
    config11 = {
        'version': 1,
        'true_formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handler_configs': {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'formatters' : 'cfg://true_formatters',
        'handlers' : {
            'hand1' : 'cfg://handler_configs[hand1]',
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'DEBUG',
                'handlers' : ['hand1'],
            },
        },
        'root' : {
            'level' : 'WARNING',
        },
    }

    # As config11 but missing the version key
    config12 = {
        'true_formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handler_configs': {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'formatters' : 'cfg://true_formatters',
        'handlers' : {
            'hand1' : 'cfg://handler_configs[hand1]',
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'DEBUG',
                'handlers' : ['hand1'],
            },
        },
        'root' : {
            'level' : 'WARNING',
        },
    }

    # As config11 but using an unsupported version
    config13 = {
        'version': 2,
        'true_formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handler_configs': {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
            },
        },
        'formatters' : 'cfg://true_formatters',
        'handlers' : {
            'hand1' : 'cfg://handler_configs[hand1]',
        },
        'loggers' : {
            'compiler.parser' : {
                'level' : 'DEBUG',
                'handlers' : ['hand1'],
            },
        },
        'root' : {
            'level' : 'WARNING',
        },
    }

    # As config0, but with properties
    config14 = {
        'version': 1,
        'formatters': {
            'form1' : {
                'format' : '%(levelname)s ++ %(message)s',
            },
        },
        'handlers' : {
            'hand1' : {
                'class' : 'logging.StreamHandler',
                'formatter' : 'form1',
                'level' : 'NOTSET',
                'stream'  : 'ext://sys.stdout',
                '.': {
                    'foo': 'bar',
                    'terminator': '!\n',
                }
            },
        },
        'root' : {
            'level' : 'WARNING',
            'handlers' : ['hand1'],
        },
    }

    out_of_order = {
        "version": 1,
        "formatters": {
            "mySimpleFormatter": {
                "format": "%(asctime)s (%(name)s) %(levelname)s: %(message)s",
                "style": "$"
            }
        },
        "handlers": {
            "fileGlobal": {
                "class": "logging.StreamHandler",
                "level": "DEBUG",
                "formatter": "mySimpleFormatter"
            },
            "bufferGlobal": {
                "class": "logging.handlers.MemoryHandler",
                "capacity": 5,
                "formatter": "mySimpleFormatter",
                "target": "fileGlobal",
                "level": "DEBUG"
                }
        },
        "loggers": {
            "mymodule": {
                "level": "DEBUG",
                "handlers": ["bufferGlobal"],
                "propagate": "true"
            }
        }
    }

    def apply_config(self, conf):
        logging.config.dictConfig(conf)

    def test_config0_ok(self):
        # A simple config which overrides the default settings.
        with support.captured_stdout() as output:
            self.apply_config(self.config0)
            logger = logging.getLogger()
            # Won't output anything
            logger.info(self.next_message())
            # Outputs a message
            logger.error(self.next_message())
            self.assert_log_lines([
                ('ERROR', '2'),
            ], stream=output)
            # Original logger output is empty.
            self.assert_log_lines([])

    def test_config1_ok(self, config=config1):
        # A config defining a sub-parser as well.
        with support.captured_stdout() as output:
            self.apply_config(config)
            logger = logging.getLogger("compiler.parser")
            # Both will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
            self.assert_log_lines([
                ('INFO', '1'),
                ('ERROR', '2'),
            ], stream=output)
            # Original logger output is empty.
            self.assert_log_lines([])

    def test_config2_failure(self):
        # A simple config which overrides the default settings.
        self.assertRaises(Exception, self.apply_config, self.config2)

    def test_config2a_failure(self):
        # A simple config which overrides the default settings.
        self.assertRaises(Exception, self.apply_config, self.config2a)

    def test_config2b_failure(self):
        # A simple config which overrides the default settings.
        self.assertRaises(Exception, self.apply_config, self.config2b)

    def test_config3_failure(self):
        # A simple config which overrides the default settings.
        self.assertRaises(Exception, self.apply_config, self.config3)

    def test_config4_ok(self):
        # A config specifying a custom formatter class.
        with support.captured_stdout() as output:
            self.apply_config(self.config4)
            #logger = logging.getLogger()
            try:
                raise RuntimeError()
            except RuntimeError:
                logging.exception("just testing")
            sys.stdout.seek(0)
            self.assertEqual(output.getvalue(),
                "ERROR:root:just testing\nGot a [RuntimeError]\n")
            # Original logger output is empty
            self.assert_log_lines([])

    def test_config4a_ok(self):
        # A config specifying a custom formatter class.
        with support.captured_stdout() as output:
            self.apply_config(self.config4a)
            #logger = logging.getLogger()
            try:
                raise RuntimeError()
            except RuntimeError:
                logging.exception("just testing")
            sys.stdout.seek(0)
            self.assertEqual(output.getvalue(),
                "ERROR:root:just testing\nGot a [RuntimeError]\n")
            # Original logger output is empty
            self.assert_log_lines([])

    def test_config5_ok(self):
        self.test_config1_ok(config=self.config5)

    def test_config6_failure(self):
        self.assertRaises(Exception, self.apply_config, self.config6)

    def test_config7_ok(self):
        with support.captured_stdout() as output:
            self.apply_config(self.config1)
            logger = logging.getLogger("compiler.parser")
            # Both will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
            self.assert_log_lines([
                ('INFO', '1'),
                ('ERROR', '2'),
            ], stream=output)
            # Original logger output is empty.
            self.assert_log_lines([])
        with support.captured_stdout() as output:
            self.apply_config(self.config7)
            logger = logging.getLogger("compiler.parser")
            self.assertTrue(logger.disabled)
            logger = logging.getLogger("compiler.lexer")
            # Both will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
            self.assert_log_lines([
                ('INFO', '3'),
                ('ERROR', '4'),
            ], stream=output)
            # Original logger output is empty.
            self.assert_log_lines([])

    # Same as test_config_7_ok but don't disable old loggers.
    def test_config_8_ok(self):
        with support.captured_stdout() as output:
            self.apply_config(self.config1)
            logger = logging.getLogger("compiler.parser")
            # All will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
            self.assert_log_lines([
                ('INFO', '1'),
                ('ERROR', '2'),
            ], stream=output)
            # Original logger output is empty.
            self.assert_log_lines([])
        with support.captured_stdout() as output:
            self.apply_config(self.config8)
            logger = logging.getLogger("compiler.parser")
            self.assertFalse(logger.disabled)
            # Both will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
            logger = logging.getLogger("compiler.lexer")
            # Both will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
            self.assert_log_lines([
                ('INFO', '3'),
                ('ERROR', '4'),
                ('INFO', '5'),
                ('ERROR', '6'),
            ], stream=output)
            # Original logger output is empty.
            self.assert_log_lines([])

    def test_config_8a_ok(self):
        with support.captured_stdout() as output:
            self.apply_config(self.config1a)
            logger = logging.getLogger("compiler.parser")
            # See issue #11424. compiler-hyphenated sorts
            # between compiler and compiler.xyz and this
            # was preventing compiler.xyz from being included
            # in the child loggers of compiler because of an
            # overzealous loop termination condition.
            hyphenated = logging.getLogger('compiler-hyphenated')
            # All will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
            hyphenated.critical(self.next_message())
            self.assert_log_lines([
                ('INFO', '1'),
                ('ERROR', '2'),
                ('CRITICAL', '3'),
            ], stream=output)
            # Original logger output is empty.
            self.assert_log_lines([])
        with support.captured_stdout() as output:
            self.apply_config(self.config8a)
            logger = logging.getLogger("compiler.parser")
            self.assertFalse(logger.disabled)
            # Both will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
            logger = logging.getLogger("compiler.lexer")
            # Both will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
            # Will not appear
            hyphenated.critical(self.next_message())
            self.assert_log_lines([
                ('INFO', '4'),
                ('ERROR', '5'),
                ('INFO', '6'),
                ('ERROR', '7'),
            ], stream=output)
            # Original logger output is empty.
            self.assert_log_lines([])

    def test_config_9_ok(self):
        with support.captured_stdout() as output:
            self.apply_config(self.config9)
            logger = logging.getLogger("compiler.parser")
            # Nothing will be output since both handler and logger are set to WARNING
            logger.info(self.next_message())
            self.assert_log_lines([], stream=output)
            self.apply_config(self.config9a)
            # Nothing will be output since handler is still set to WARNING
            logger.info(self.next_message())
            self.assert_log_lines([], stream=output)
            self.apply_config(self.config9b)
            # Message should now be output
            logger.info(self.next_message())
            self.assert_log_lines([
                ('INFO', '3'),
            ], stream=output)

    def test_config_10_ok(self):
        with support.captured_stdout() as output:
            self.apply_config(self.config10)
            logger = logging.getLogger("compiler.parser")
            logger.warning(self.next_message())
            logger = logging.getLogger('compiler')
            # Not output, because filtered
            logger.warning(self.next_message())
            logger = logging.getLogger('compiler.lexer')
            # Not output, because filtered
            logger.warning(self.next_message())
            logger = logging.getLogger("compiler.parser.codegen")
            # Output, as not filtered
            logger.error(self.next_message())
            self.assert_log_lines([
                ('WARNING', '1'),
                ('ERROR', '4'),
            ], stream=output)

    def test_config11_ok(self):
        self.test_config1_ok(self.config11)

    def test_config12_failure(self):
        self.assertRaises(Exception, self.apply_config, self.config12)

    def test_config13_failure(self):
        self.assertRaises(Exception, self.apply_config, self.config13)

    def test_config14_ok(self):
        with support.captured_stdout() as output:
            self.apply_config(self.config14)
            h = logging._handlers['hand1']
            self.assertEqual(h.foo, 'bar')
            self.assertEqual(h.terminator, '!\n')
            logging.warning('Exclamation')
            self.assertTrue(output.getvalue().endswith('Exclamation!\n'))

    def test_config15_ok(self):

        def cleanup(h1, fn):
            h1.close()
            os.remove(fn)

        with self.check_no_resource_warning():
            fd, fn = tempfile.mkstemp(".log", "test_logging-X-")
            os.close(fd)

            config = {
                "version": 1,
                "handlers": {
                    "file": {
                        "class": "logging.FileHandler",
                        "filename": fn
                    }
                },
                "root": {
                    "handlers": ["file"]
                }
            }

            self.apply_config(config)
            self.apply_config(config)

        handler = logging.root.handlers[0]
        self.addCleanup(cleanup, handler, fn)

    def setup_via_listener(self, text, verify=None):
        text = text.encode("utf-8")
        # Ask for a randomly assigned port (by using port 0)
        t = logging.config.listen(0, verify)
        t.start()
        t.ready.wait()
        # Now get the port allocated
        port = t.port
        t.ready.clear()
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(2.0)
            sock.connect(('localhost', port))

            slen = struct.pack('>L', len(text))
            s = slen + text
            sentsofar = 0
            left = len(s)
            while left > 0:
                sent = sock.send(s[sentsofar:])
                sentsofar += sent
                left -= sent
            sock.close()
        finally:
            t.ready.wait(2.0)
            logging.config.stopListening()
            support.join_thread(t, 2.0)

    def test_listen_config_10_ok(self):
        with support.captured_stdout() as output:
            self.setup_via_listener(json.dumps(self.config10))
            logger = logging.getLogger("compiler.parser")
            logger.warning(self.next_message())
            logger = logging.getLogger('compiler')
            # Not output, because filtered
            logger.warning(self.next_message())
            logger = logging.getLogger('compiler.lexer')
            # Not output, because filtered
            logger.warning(self.next_message())
            logger = logging.getLogger("compiler.parser.codegen")
            # Output, as not filtered
            logger.error(self.next_message())
            self.assert_log_lines([
                ('WARNING', '1'),
                ('ERROR', '4'),
            ], stream=output)

    def test_listen_config_1_ok(self):
        with support.captured_stdout() as output:
            self.setup_via_listener(textwrap.dedent(ConfigFileTest.config1))
            logger = logging.getLogger("compiler.parser")
            # Both will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
            self.assert_log_lines([
                ('INFO', '1'),
                ('ERROR', '2'),
            ], stream=output)
            # Original logger output is empty.
            self.assert_log_lines([])

    def test_listen_verify(self):

        def verify_fail(stuff):
            return None

        def verify_reverse(stuff):
            return stuff[::-1]

        logger = logging.getLogger("compiler.parser")
        to_send = textwrap.dedent(ConfigFileTest.config1)
        # First, specify a verification function that will fail.
        # We expect to see no output, since our configuration
        # never took effect.
        with support.captured_stdout() as output:
            self.setup_via_listener(to_send, verify_fail)
            # Both will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
        self.assert_log_lines([], stream=output)
        # Original logger output has the stuff we logged.
        self.assert_log_lines([
            ('INFO', '1'),
            ('ERROR', '2'),
        ], pat=r"^[\w.]+ -> (\w+): (\d+)$")

        # Now, perform no verification. Our configuration
        # should take effect.

        with support.captured_stdout() as output:
            self.setup_via_listener(to_send)    # no verify callable specified
            logger = logging.getLogger("compiler.parser")
            # Both will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
        self.assert_log_lines([
            ('INFO', '3'),
            ('ERROR', '4'),
        ], stream=output)
        # Original logger output still has the stuff we logged before.
        self.assert_log_lines([
            ('INFO', '1'),
            ('ERROR', '2'),
        ], pat=r"^[\w.]+ -> (\w+): (\d+)$")

        # Now, perform verification which transforms the bytes.

        with support.captured_stdout() as output:
            self.setup_via_listener(to_send[::-1], verify_reverse)
            logger = logging.getLogger("compiler.parser")
            # Both will output a message
            logger.info(self.next_message())
            logger.error(self.next_message())
        self.assert_log_lines([
            ('INFO', '5'),
            ('ERROR', '6'),
        ], stream=output)
        # Original logger output still has the stuff we logged before.
        self.assert_log_lines([
            ('INFO', '1'),
            ('ERROR', '2'),
        ], pat=r"^[\w.]+ -> (\w+): (\d+)$")

    def test_out_of_order(self):
        self.apply_config(self.out_of_order)
        handler = logging.getLogger('mymodule').handlers[0]
        self.assertIsInstance(handler.target, logging.Handler)
        self.assertIsInstance(handler.formatter._style,
                              logging.StringTemplateStyle)

    def test_baseconfig(self):
        d = {
            'atuple': (1, 2, 3),
            'alist': ['a', 'b', 'c'],
            'adict': {'d': 'e', 'f': 3 },
            'nest1': ('g', ('h', 'i'), 'j'),
            'nest2': ['k', ['l', 'm'], 'n'],
            'nest3': ['o', 'cfg://alist', 'p'],
        }
        bc = logging.config.BaseConfigurator(d)
        self.assertEqual(bc.convert('cfg://atuple[1]'), 2)
        self.assertEqual(bc.convert('cfg://alist[1]'), 'b')
        self.assertEqual(bc.convert('cfg://nest1[1][0]'), 'h')
        self.assertEqual(bc.convert('cfg://nest2[1][1]'), 'm')
        self.assertEqual(bc.convert('cfg://adict.d'), 'e')
        self.assertEqual(bc.convert('cfg://adict[f]'), 3)
        v = bc.convert('cfg://nest3')
        self.assertEqual(v.pop(1), ['a', 'b', 'c'])
        self.assertRaises(KeyError, bc.convert, 'cfg://nosuch')
        self.assertRaises(ValueError, bc.convert, 'cfg://!')
        self.assertRaises(KeyError, bc.convert, 'cfg://adict[2]')

    def test_namedtuple(self):
        # see bpo-39142
        from collections import namedtuple

        class MyHandler(logging.StreamHandler):
            def __init__(self, resource, *args, **kwargs):
                super().__init__(*args, **kwargs)
                self.resource: namedtuple = resource

            def emit(self, record):
                record.msg += f' {self.resource.type}'
                return super().emit(record)

        Resource = namedtuple('Resource', ['type', 'labels'])
        resource = Resource(type='my_type', labels=['a'])

        config = {
            'version': 1,
            'handlers': {
                'myhandler': {
                    '()': MyHandler,
                    'resource': resource
                }
            },
            'root':  {'level': 'INFO', 'handlers': ['myhandler']},
        }
        with support.captured_stderr() as stderr:
            self.apply_config(config)
            logging.info('some log')
        self.assertEqual(stderr.getvalue(), 'some log my_type\n')

class ManagerTest(BaseTest):
    def test_manager_loggerclass(self):
        logged = []

        class MyLogger(logging.Logger):
            def _log(self, level, msg, args, exc_info=None, extra=None):
                logged.append(msg)

        man = logging.Manager(None)
        self.assertRaises(TypeError, man.setLoggerClass, int)
        man.setLoggerClass(MyLogger)
        logger = man.getLogger('test')
        logger.warning('should appear in logged')
        logging.warning('should not appear in logged')

        self.assertEqual(logged, ['should appear in logged'])

    def test_set_log_record_factory(self):
        man = logging.Manager(None)
        expected = object()
        man.setLogRecordFactory(expected)
        self.assertEqual(man.logRecordFactory, expected)

class ChildLoggerTest(BaseTest):
    def test_child_loggers(self):
        r = logging.getLogger()
        l1 = logging.getLogger('abc')
        l2 = logging.getLogger('def.ghi')
        c1 = r.getChild('xyz')
        c2 = r.getChild('uvw.xyz')
        self.assertIs(c1, logging.getLogger('xyz'))
        self.assertIs(c2, logging.getLogger('uvw.xyz'))
        c1 = l1.getChild('def')
        c2 = c1.getChild('ghi')
        c3 = l1.getChild('def.ghi')
        self.assertIs(c1, logging.getLogger('abc.def'))
        self.assertIs(c2, logging.getLogger('abc.def.ghi'))
        self.assertIs(c2, c3)


class DerivedLogRecord(logging.LogRecord):
    pass

class LogRecordFactoryTest(BaseTest):

    def setUp(self):
        class CheckingFilter(logging.Filter):
            def __init__(self, cls):
                self.cls = cls

            def filter(self, record):
                t = type(record)
                if t is not self.cls:
                    msg = 'Unexpected LogRecord type %s, expected %s' % (t,
                            self.cls)
                    raise TypeError(msg)
                return True

        BaseTest.setUp(self)
        self.filter = CheckingFilter(DerivedLogRecord)
        self.root_logger.addFilter(self.filter)
        self.orig_factory = logging.getLogRecordFactory()

    def tearDown(self):
        self.root_logger.removeFilter(self.filter)
        BaseTest.tearDown(self)
        logging.setLogRecordFactory(self.orig_factory)

    def test_logrecord_class(self):
        self.assertRaises(TypeError, self.root_logger.warning,
                          self.next_message())
        logging.setLogRecordFactory(DerivedLogRecord)
        self.root_logger.error(self.next_message())
        self.assert_log_lines([
           ('root', 'ERROR', '2'),
        ])


class QueueHandlerTest(BaseTest):
    # Do not bother with a logger name group.
    expected_log_pat = r"^[\w.]+ -> (\w+): (\d+)$"

    def setUp(self):
        BaseTest.setUp(self)
        self.queue = queue.Queue(-1)
        self.que_hdlr = logging.handlers.QueueHandler(self.queue)
        self.name = 'que'
        self.que_logger = logging.getLogger('que')
        self.que_logger.propagate = False
        self.que_logger.setLevel(logging.WARNING)
        self.que_logger.addHandler(self.que_hdlr)

    def tearDown(self):
        self.que_hdlr.close()
        BaseTest.tearDown(self)

    def test_queue_handler(self):
        self.que_logger.debug(self.next_message())
        self.assertRaises(queue.Empty, self.queue.get_nowait)
        self.que_logger.info(self.next_message())
        self.assertRaises(queue.Empty, self.queue.get_nowait)
        msg = self.next_message()
        self.que_logger.warning(msg)
        data = self.queue.get_nowait()
        self.assertTrue(isinstance(data, logging.LogRecord))
        self.assertEqual(data.name, self.que_logger.name)
        self.assertEqual((data.msg, data.args), (msg, None))

    def test_formatting(self):
        msg = self.next_message()
        levelname = logging.getLevelName(logging.WARNING)
        log_format_str = '{name} -> {levelname}: {message}'
        formatted_msg = log_format_str.format(name=self.name,
                                              levelname=levelname, message=msg)
        formatter = logging.Formatter(self.log_format)
        self.que_hdlr.setFormatter(formatter)
        self.que_logger.warning(msg)
        log_record = self.queue.get_nowait()
        self.assertEqual(formatted_msg, log_record.msg)
        self.assertEqual(formatted_msg, log_record.message)

    @unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'),
                         'logging.handlers.QueueListener required for this test')
    def test_queue_listener(self):
        handler = support.TestHandler(support.Matcher())
        listener = logging.handlers.QueueListener(self.queue, handler)
        listener.start()
        try:
            self.que_logger.warning(self.next_message())
            self.que_logger.error(self.next_message())
            self.que_logger.critical(self.next_message())
        finally:
            listener.stop()
        self.assertTrue(handler.matches(levelno=logging.WARNING, message='1'))
        self.assertTrue(handler.matches(levelno=logging.ERROR, message='2'))
        self.assertTrue(handler.matches(levelno=logging.CRITICAL, message='3'))
        handler.close()

        # Now test with respect_handler_level set

        handler = support.TestHandler(support.Matcher())
        handler.setLevel(logging.CRITICAL)
        listener = logging.handlers.QueueListener(self.queue, handler,
                                                  respect_handler_level=True)
        listener.start()
        try:
            self.que_logger.warning(self.next_message())
            self.que_logger.error(self.next_message())
            self.que_logger.critical(self.next_message())
        finally:
            listener.stop()
        self.assertFalse(handler.matches(levelno=logging.WARNING, message='4'))
        self.assertFalse(handler.matches(levelno=logging.ERROR, message='5'))
        self.assertTrue(handler.matches(levelno=logging.CRITICAL, message='6'))
        handler.close()

    @unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'),
                         'logging.handlers.QueueListener required for this test')
    def test_queue_listener_with_StreamHandler(self):
        # Test that traceback only appends once (bpo-34334).
        listener = logging.handlers.QueueListener(self.queue, self.root_hdlr)
        listener.start()
        try:
            1 / 0
        except ZeroDivisionError as e:
            exc = e
            self.que_logger.exception(self.next_message(), exc_info=exc)
        listener.stop()
        self.assertEqual(self.stream.getvalue().strip().count('Traceback'), 1)

    @unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'),
                         'logging.handlers.QueueListener required for this test')
    def test_queue_listener_with_multiple_handlers(self):
        # Test that queue handler format doesn't affect other handler formats (bpo-35726).
        self.que_hdlr.setFormatter(self.root_formatter)
        self.que_logger.addHandler(self.root_hdlr)

        listener = logging.handlers.QueueListener(self.queue, self.que_hdlr)
        listener.start()
        self.que_logger.error("error")
        listener.stop()
        self.assertEqual(self.stream.getvalue().strip(), "que -> ERROR: error")

if hasattr(logging.handlers, 'QueueListener'):
    import multiprocessing
    from unittest.mock import patch

    class QueueListenerTest(BaseTest):
        """
        Tests based on patch submitted for issue #27930. Ensure that
        QueueListener handles all log messages.
        """

        repeat = 20

        @staticmethod
        def setup_and_log(log_queue, ident):
            """
            Creates a logger with a QueueHandler that logs to a queue read by a
            QueueListener. Starts the listener, logs five messages, and stops
            the listener.
            """
            logger = logging.getLogger('test_logger_with_id_%s' % ident)
            logger.setLevel(logging.DEBUG)
            handler = logging.handlers.QueueHandler(log_queue)
            logger.addHandler(handler)
            listener = logging.handlers.QueueListener(log_queue)
            listener.start()

            logger.info('one')
            logger.info('two')
            logger.info('three')
            logger.info('four')
            logger.info('five')

            listener.stop()
            logger.removeHandler(handler)
            handler.close()

        @patch.object(logging.handlers.QueueListener, 'handle')
        def test_handle_called_with_queue_queue(self, mock_handle):
            for i in range(self.repeat):
                log_queue = queue.Queue()
                self.setup_and_log(log_queue, '%s_%s' % (self.id(), i))
            self.assertEqual(mock_handle.call_count, 5 * self.repeat,
                             'correct number of handled log messages')

        @patch.object(logging.handlers.QueueListener, 'handle')
        def test_handle_called_with_mp_queue(self, mock_handle):
            # Issue 28668: The multiprocessing (mp) module is not functional
            # when the mp.synchronize module cannot be imported.
            support.import_module('multiprocessing.synchronize')
            for i in range(self.repeat):
                log_queue = multiprocessing.Queue()
                self.setup_and_log(log_queue, '%s_%s' % (self.id(), i))
                log_queue.close()
                log_queue.join_thread()
            self.assertEqual(mock_handle.call_count, 5 * self.repeat,
                             'correct number of handled log messages')

        @staticmethod
        def get_all_from_queue(log_queue):
            try:
                while True:
                    yield log_queue.get_nowait()
            except queue.Empty:
                return []

        def test_no_messages_in_queue_after_stop(self):
            """
            Five messages are logged then the QueueListener is stopped. This
            test then gets everything off the queue. Failure of this test
            indicates that messages were not registered on the queue until
            _after_ the QueueListener stopped.
            """
            # Issue 28668: The multiprocessing (mp) module is not functional
            # when the mp.synchronize module cannot be imported.
            support.import_module('multiprocessing.synchronize')
            for i in range(self.repeat):
                queue = multiprocessing.Queue()
                self.setup_and_log(queue, '%s_%s' %(self.id(), i))
                # time.sleep(1)
                items = list(self.get_all_from_queue(queue))
                queue.close()
                queue.join_thread()

                expected = [[], [logging.handlers.QueueListener._sentinel]]
                self.assertIn(items, expected,
                              'Found unexpected messages in queue: %s' % (
                                    [m.msg if isinstance(m, logging.LogRecord)
                                     else m for m in items]))

        def test_calls_task_done_after_stop(self):
            # Issue 36813: Make sure queue.join does not deadlock.
            log_queue = queue.Queue()
            listener = logging.handlers.QueueListener(log_queue)
            listener.start()
            listener.stop()
            with self.assertRaises(ValueError):
                # Make sure all tasks are done and .join won't block.
                log_queue.task_done()


ZERO = datetime.timedelta(0)

class UTC(datetime.tzinfo):
    def utcoffset(self, dt):
        return ZERO

    dst = utcoffset

    def tzname(self, dt):
        return 'UTC'

utc = UTC()

class FormatterTest(unittest.TestCase):
    def setUp(self):
        self.common = {
            'name': 'formatter.test',
            'level': logging.DEBUG,
            'pathname': os.path.join('path', 'to', 'dummy.ext'),
            'lineno': 42,
            'exc_info': None,
            'func': None,
            'msg': 'Message with %d %s',
            'args': (2, 'placeholders'),
        }
        self.variants = {
        }

    def get_record(self, name=None):
        result = dict(self.common)
        if name is not None:
            result.update(self.variants[name])
        return logging.makeLogRecord(result)

    def test_percent(self):
        # Test %-formatting
        r = self.get_record()
        f = logging.Formatter('${%(message)s}')
        self.assertEqual(f.format(r), '${Message with 2 placeholders}')
        f = logging.Formatter('%(random)s')
        self.assertRaises(KeyError, f.format, r)
        self.assertFalse(f.usesTime())
        f = logging.Formatter('%(asctime)s')
        self.assertTrue(f.usesTime())
        f = logging.Formatter('%(asctime)-15s')
        self.assertTrue(f.usesTime())
        f = logging.Formatter('asctime')
        self.assertFalse(f.usesTime())

    def test_braces(self):
        # Test {}-formatting
        r = self.get_record()
        f = logging.Formatter('$%{message}%$', style='{')
        self.assertEqual(f.format(r), '$%Message with 2 placeholders%$')
        f = logging.Formatter('{random}', style='{')
        self.assertRaises(KeyError, f.format, r)
        self.assertFalse(f.usesTime())
        f = logging.Formatter('{asctime}', style='{')
        self.assertTrue(f.usesTime())
        f = logging.Formatter('{asctime!s:15}', style='{')
        self.assertTrue(f.usesTime())
        f = logging.Formatter('{asctime:15}', style='{')
        self.assertTrue(f.usesTime())
        f = logging.Formatter('asctime', style='{')
        self.assertFalse(f.usesTime())

    def test_dollars(self):
        # Test $-formatting
        r = self.get_record()
        f = logging.Formatter('$message', style='$')
        self.assertEqual(f.format(r), 'Message with 2 placeholders')
        f = logging.Formatter('$$%${message}%$$', style='$')
        self.assertEqual(f.format(r), '$%Message with 2 placeholders%$')
        f = logging.Formatter('${random}', style='$')
        self.assertRaises(KeyError, f.format, r)
        self.assertFalse(f.usesTime())
        f = logging.Formatter('${asctime}', style='$')
        self.assertTrue(f.usesTime())
        f = logging.Formatter('${asctime', style='$')
        self.assertFalse(f.usesTime())
        f = logging.Formatter('$asctime', style='$')
        self.assertTrue(f.usesTime())
        f = logging.Formatter('asctime', style='$')
        self.assertFalse(f.usesTime())

    def test_invalid_style(self):
        self.assertRaises(ValueError, logging.Formatter, None, None, 'x')

    def test_time(self):
        r = self.get_record()
        dt = datetime.datetime(1993, 4, 21, 8, 3, 0, 0, utc)
        # We use None to indicate we want the local timezone
        # We're essentially converting a UTC time to local time
        r.created = time.mktime(dt.astimezone(None).timetuple())
        r.msecs = 123
        f = logging.Formatter('%(asctime)s %(message)s')
        f.converter = time.gmtime
        self.assertEqual(f.formatTime(r), '1993-04-21 08:03:00,123')
        self.assertEqual(f.formatTime(r, '%Y:%d'), '1993:21')
        f.format(r)
        self.assertEqual(r.asctime, '1993-04-21 08:03:00,123')

class TestBufferingFormatter(logging.BufferingFormatter):
    def formatHeader(self, records):
        return '[(%d)' % len(records)

    def formatFooter(self, records):
        return '(%d)]' % len(records)

class BufferingFormatterTest(unittest.TestCase):
    def setUp(self):
        self.records = [
            logging.makeLogRecord({'msg': 'one'}),
            logging.makeLogRecord({'msg': 'two'}),
        ]

    def test_default(self):
        f = logging.BufferingFormatter()
        self.assertEqual('', f.format([]))
        self.assertEqual('onetwo', f.format(self.records))

    def test_custom(self):
        f = TestBufferingFormatter()
        self.assertEqual('[(2)onetwo(2)]', f.format(self.records))
        lf = logging.Formatter('<%(message)s>')
        f = TestBufferingFormatter(lf)
        self.assertEqual('[(2)<one><two>(2)]', f.format(self.records))

class ExceptionTest(BaseTest):
    def test_formatting(self):
        r = self.root_logger
        h = RecordingHandler()
        r.addHandler(h)
        try:
            raise RuntimeError('deliberate mistake')
        except:
            logging.exception('failed', stack_info=True)
        r.removeHandler(h)
        h.close()
        r = h.records[0]
        self.assertTrue(r.exc_text.startswith('Traceback (most recent '
                                              'call last):\n'))
        self.assertTrue(r.exc_text.endswith('\nRuntimeError: '
                                            'deliberate mistake'))
        self.assertTrue(r.stack_info.startswith('Stack (most recent '
                                              'call last):\n'))
        self.assertTrue(r.stack_info.endswith('logging.exception(\'failed\', '
                                            'stack_info=True)'))


class LastResortTest(BaseTest):
    def test_last_resort(self):
        # Test the last resort handler
        root = self.root_logger
        root.removeHandler(self.root_hdlr)
        old_lastresort = logging.lastResort
        old_raise_exceptions = logging.raiseExceptions

        try:
            with support.captured_stderr() as stderr:
                root.debug('This should not appear')
                self.assertEqual(stderr.getvalue(), '')
                root.warning('Final chance!')
                self.assertEqual(stderr.getvalue(), 'Final chance!\n')

            # No handlers and no last resort, so 'No handlers' message
            logging.lastResort = None
            with support.captured_stderr() as stderr:
                root.warning('Final chance!')
                msg = 'No handlers could be found for logger "root"\n'
                self.assertEqual(stderr.getvalue(), msg)

            # 'No handlers' message only printed once
            with support.captured_stderr() as stderr:
                root.warning('Final chance!')
                self.assertEqual(stderr.getvalue(), '')

            # If raiseExceptions is False, no message is printed
            root.manager.emittedNoHandlerWarning = False
            logging.raiseExceptions = False
            with support.captured_stderr() as stderr:
                root.warning('Final chance!')
                self.assertEqual(stderr.getvalue(), '')
        finally:
            root.addHandler(self.root_hdlr)
            logging.lastResort = old_lastresort
            logging.raiseExceptions = old_raise_exceptions


class FakeHandler:

    def __init__(self, identifier, called):
        for method in ('acquire', 'flush', 'close', 'release'):
            setattr(self, method, self.record_call(identifier, method, called))

    def record_call(self, identifier, method_name, called):
        def inner():
            called.append('{} - {}'.format(identifier, method_name))
        return inner


class RecordingHandler(logging.NullHandler):

    def __init__(self, *args, **kwargs):
        super(RecordingHandler, self).__init__(*args, **kwargs)
        self.records = []

    def handle(self, record):
        """Keep track of all the emitted records."""
        self.records.append(record)


class ShutdownTest(BaseTest):

    """Test suite for the shutdown method."""

    def setUp(self):
        super(ShutdownTest, self).setUp()
        self.called = []

        raise_exceptions = logging.raiseExceptions
        self.addCleanup(setattr, logging, 'raiseExceptions', raise_exceptions)

    def raise_error(self, error):
        def inner():
            raise error()
        return inner

    def test_no_failure(self):
        # create some fake handlers
        handler0 = FakeHandler(0, self.called)
        handler1 = FakeHandler(1, self.called)
        handler2 = FakeHandler(2, self.called)

        # create live weakref to those handlers
        handlers = map(logging.weakref.ref, [handler0, handler1, handler2])

        logging.shutdown(handlerList=list(handlers))

        expected = ['2 - acquire', '2 - flush', '2 - close', '2 - release',
                    '1 - acquire', '1 - flush', '1 - close', '1 - release',
                    '0 - acquire', '0 - flush', '0 - close', '0 - release']
        self.assertEqual(expected, self.called)

    def _test_with_failure_in_method(self, method, error):
        handler = FakeHandler(0, self.called)
        setattr(handler, method, self.raise_error(error))
        handlers = [logging.weakref.ref(handler)]

        logging.shutdown(handlerList=list(handlers))

        self.assertEqual('0 - release', self.called[-1])

    def test_with_ioerror_in_acquire(self):
        self._test_with_failure_in_method('acquire', OSError)

    def test_with_ioerror_in_flush(self):
        self._test_with_failure_in_method('flush', OSError)

    def test_with_ioerror_in_close(self):
        self._test_with_failure_in_method('close', OSError)

    def test_with_valueerror_in_acquire(self):
        self._test_with_failure_in_method('acquire', ValueError)

    def test_with_valueerror_in_flush(self):
        self._test_with_failure_in_method('flush', ValueError)

    def test_with_valueerror_in_close(self):
        self._test_with_failure_in_method('close', ValueError)

    def test_with_other_error_in_acquire_without_raise(self):
        logging.raiseExceptions = False
        self._test_with_failure_in_method('acquire', IndexError)

    def test_with_other_error_in_flush_without_raise(self):
        logging.raiseExceptions = False
        self._test_with_failure_in_method('flush', IndexError)

    def test_with_other_error_in_close_without_raise(self):
        logging.raiseExceptions = False
        self._test_with_failure_in_method('close', IndexError)

    def test_with_other_error_in_acquire_with_raise(self):
        logging.raiseExceptions = True
        self.assertRaises(IndexError, self._test_with_failure_in_method,
                          'acquire', IndexError)

    def test_with_other_error_in_flush_with_raise(self):
        logging.raiseExceptions = True
        self.assertRaises(IndexError, self._test_with_failure_in_method,
                          'flush', IndexError)

    def test_with_other_error_in_close_with_raise(self):
        logging.raiseExceptions = True
        self.assertRaises(IndexError, self._test_with_failure_in_method,
                          'close', IndexError)


class ModuleLevelMiscTest(BaseTest):

    """Test suite for some module level methods."""

    def test_disable(self):
        old_disable = logging.root.manager.disable
        # confirm our assumptions are correct
        self.assertEqual(old_disable, 0)
        self.addCleanup(logging.disable, old_disable)

        logging.disable(83)
        self.assertEqual(logging.root.manager.disable, 83)

        # test the default value introduced in 3.7
        # (Issue #28524)
        logging.disable()
        self.assertEqual(logging.root.manager.disable, logging.CRITICAL)

    def _test_log(self, method, level=None):
        called = []
        support.patch(self, logging, 'basicConfig',
                      lambda *a, **kw: called.append((a, kw)))

        recording = RecordingHandler()
        logging.root.addHandler(recording)

        log_method = getattr(logging, method)
        if level is not None:
            log_method(level, "test me: %r", recording)
        else:
            log_method("test me: %r", recording)

        self.assertEqual(len(recording.records), 1)
        record = recording.records[0]
        self.assertEqual(record.getMessage(), "test me: %r" % recording)

        expected_level = level if level is not None else getattr(logging, method.upper())
        self.assertEqual(record.levelno, expected_level)

        # basicConfig was not called!
        self.assertEqual(called, [])

    def test_log(self):
        self._test_log('log', logging.ERROR)

    def test_debug(self):
        self._test_log('debug')

    def test_info(self):
        self._test_log('info')

    def test_warning(self):
        self._test_log('warning')

    def test_error(self):
        self._test_log('error')

    def test_critical(self):
        self._test_log('critical')

    def test_set_logger_class(self):
        self.assertRaises(TypeError, logging.setLoggerClass, object)

        class MyLogger(logging.Logger):
            pass

        logging.setLoggerClass(MyLogger)
        self.assertEqual(logging.getLoggerClass(), MyLogger)

        logging.setLoggerClass(logging.Logger)
        self.assertEqual(logging.getLoggerClass(), logging.Logger)

    def test_subclass_logger_cache(self):
        # bpo-37258
        message = []

        class MyLogger(logging.getLoggerClass()):
            def __init__(self, name='MyLogger', level=logging.NOTSET):
                super().__init__(name, level)
                message.append('initialized')

        logging.setLoggerClass(MyLogger)
        logger = logging.getLogger('just_some_logger')
        self.assertEqual(message, ['initialized'])
        stream = io.StringIO()
        h = logging.StreamHandler(stream)
        logger.addHandler(h)
        try:
            logger.setLevel(logging.DEBUG)
            logger.debug("hello")
            self.assertEqual(stream.getvalue().strip(), "hello")

            stream.truncate(0)
            stream.seek(0)

            logger.setLevel(logging.INFO)
            logger.debug("hello")
            self.assertEqual(stream.getvalue(), "")
        finally:
            logger.removeHandler(h)
            h.close()
            logging.setLoggerClass(logging.Logger)

    @support.requires_type_collecting
    def test_logging_at_shutdown(self):
        # Issue #20037
        code = """if 1:
            import logging

            class A:
                def __del__(self):
                    try:
                        raise ValueError("some error")
                    except Exception:
                        logging.exception("exception in __del__")

            a = A()"""
        rc, out, err = assert_python_ok("-c", code)
        err = err.decode()
        self.assertIn("exception in __del__", err)
        self.assertIn("ValueError: some error", err)

    def test_recursion_error(self):
        # Issue 36272
        code = """if 1:
            import logging

            def rec():
                logging.error("foo")
                rec()

            rec()"""
        rc, out, err = assert_python_failure("-c", code)
        err = err.decode()
        self.assertNotIn("Cannot recover from stack overflow.", err)
        self.assertEqual(rc, 1)


class LogRecordTest(BaseTest):
    def test_str_rep(self):
        r = logging.makeLogRecord({})
        s = str(r)
        self.assertTrue(s.startswith('<LogRecord: '))
        self.assertTrue(s.endswith('>'))

    def test_dict_arg(self):
        h = RecordingHandler()
        r = logging.getLogger()
        r.addHandler(h)
        d = {'less' : 'more' }
        logging.warning('less is %(less)s', d)
        self.assertIs(h.records[0].args, d)
        self.assertEqual(h.records[0].message, 'less is more')
        r.removeHandler(h)
        h.close()

    def test_multiprocessing(self):
        r = logging.makeLogRecord({})
        self.assertEqual(r.processName, 'MainProcess')
        try:
            import multiprocessing as mp
            r = logging.makeLogRecord({})
            self.assertEqual(r.processName, mp.current_process().name)
        except ImportError:
            pass

    def test_optional(self):
        r = logging.makeLogRecord({})
        NOT_NONE = self.assertIsNotNone
        NOT_NONE(r.thread)
        NOT_NONE(r.threadName)
        NOT_NONE(r.process)
        NOT_NONE(r.processName)
        log_threads = logging.logThreads
        log_processes = logging.logProcesses
        log_multiprocessing = logging.logMultiprocessing
        try:
            logging.logThreads = False
            logging.logProcesses = False
            logging.logMultiprocessing = False
            r = logging.makeLogRecord({})
            NONE = self.assertIsNone
            NONE(r.thread)
            NONE(r.threadName)
            NONE(r.process)
            NONE(r.processName)
        finally:
            logging.logThreads = log_threads
            logging.logProcesses = log_processes
            logging.logMultiprocessing = log_multiprocessing

class BasicConfigTest(unittest.TestCase):

    """Test suite for logging.basicConfig."""

    def setUp(self):
        super(BasicConfigTest, self).setUp()
        self.handlers = logging.root.handlers
        self.saved_handlers = logging._handlers.copy()
        self.saved_handler_list = logging._handlerList[:]
        self.original_logging_level = logging.root.level
        self.addCleanup(self.cleanup)
        logging.root.handlers = []

    def tearDown(self):
        for h in logging.root.handlers[:]:
            logging.root.removeHandler(h)
            h.close()
        super(BasicConfigTest, self).tearDown()

    def cleanup(self):
        setattr(logging.root, 'handlers', self.handlers)
        logging._handlers.clear()
        logging._handlers.update(self.saved_handlers)
        logging._handlerList[:] = self.saved_handler_list
        logging.root.setLevel(self.original_logging_level)

    def test_no_kwargs(self):
        logging.basicConfig()

        # handler defaults to a StreamHandler to sys.stderr
        self.assertEqual(len(logging.root.handlers), 1)
        handler = logging.root.handlers[0]
        self.assertIsInstance(handler, logging.StreamHandler)
        self.assertEqual(handler.stream, sys.stderr)

        formatter = handler.formatter
        # format defaults to logging.BASIC_FORMAT
        self.assertEqual(formatter._style._fmt, logging.BASIC_FORMAT)
        # datefmt defaults to None
        self.assertIsNone(formatter.datefmt)
        # style defaults to %
        self.assertIsInstance(formatter._style, logging.PercentStyle)

        # level is not explicitly set
        self.assertEqual(logging.root.level, self.original_logging_level)

    def test_strformatstyle(self):
        with support.captured_stdout() as output:
            logging.basicConfig(stream=sys.stdout, style="{")
            logging.error("Log an error")
            sys.stdout.seek(0)
            self.assertEqual(output.getvalue().strip(),
                "ERROR:root:Log an error")

    def test_stringtemplatestyle(self):
        with support.captured_stdout() as output:
            logging.basicConfig(stream=sys.stdout, style="$")
            logging.error("Log an error")
            sys.stdout.seek(0)
            self.assertEqual(output.getvalue().strip(),
                "ERROR:root:Log an error")

    def test_filename(self):

        def cleanup(h1, h2, fn):
            h1.close()
            h2.close()
            os.remove(fn)

        logging.basicConfig(filename='test.log')

        self.assertEqual(len(logging.root.handlers), 1)
        handler = logging.root.handlers[0]
        self.assertIsInstance(handler, logging.FileHandler)

        expected = logging.FileHandler('test.log', 'a')
        self.assertEqual(handler.stream.mode, expected.stream.mode)
        self.assertEqual(handler.stream.name, expected.stream.name)
        self.addCleanup(cleanup, handler, expected, 'test.log')

    def test_filemode(self):

        def cleanup(h1, h2, fn):
            h1.close()
            h2.close()
            os.remove(fn)

        logging.basicConfig(filename='test.log', filemode='wb')

        handler = logging.root.handlers[0]
        expected = logging.FileHandler('test.log', 'wb')
        self.assertEqual(handler.stream.mode, expected.stream.mode)
        self.addCleanup(cleanup, handler, expected, 'test.log')

    def test_stream(self):
        stream = io.StringIO()
        self.addCleanup(stream.close)
        logging.basicConfig(stream=stream)

        self.assertEqual(len(logging.root.handlers), 1)
        handler = logging.root.handlers[0]
        self.assertIsInstance(handler, logging.StreamHandler)
        self.assertEqual(handler.stream, stream)

    def test_format(self):
        logging.basicConfig(format='foo')

        formatter = logging.root.handlers[0].formatter
        self.assertEqual(formatter._style._fmt, 'foo')

    def test_datefmt(self):
        logging.basicConfig(datefmt='bar')

        formatter = logging.root.handlers[0].formatter
        self.assertEqual(formatter.datefmt, 'bar')

    def test_style(self):
        logging.basicConfig(style='$')

        formatter = logging.root.handlers[0].formatter
        self.assertIsInstance(formatter._style, logging.StringTemplateStyle)

    def test_level(self):
        old_level = logging.root.level
        self.addCleanup(logging.root.setLevel, old_level)

        logging.basicConfig(level=57)
        self.assertEqual(logging.root.level, 57)
        # Test that second call has no effect
        logging.basicConfig(level=58)
        self.assertEqual(logging.root.level, 57)

    def test_incompatible(self):
        assertRaises = self.assertRaises
        handlers = [logging.StreamHandler()]
        stream = sys.stderr
        assertRaises(ValueError, logging.basicConfig, filename='test.log',
                                                     stream=stream)
        assertRaises(ValueError, logging.basicConfig, filename='test.log',
                                                     handlers=handlers)
        assertRaises(ValueError, logging.basicConfig, stream=stream,
                                                     handlers=handlers)
        # Issue 23207: test for invalid kwargs
        assertRaises(ValueError, logging.basicConfig, loglevel=logging.INFO)
        # Should pop both filename and filemode even if filename is None
        logging.basicConfig(filename=None, filemode='a')

    def test_handlers(self):
        handlers = [
            logging.StreamHandler(),
            logging.StreamHandler(sys.stdout),
            logging.StreamHandler(),
        ]
        f = logging.Formatter()
        handlers[2].setFormatter(f)
        logging.basicConfig(handlers=handlers)
        self.assertIs(handlers[0], logging.root.handlers[0])
        self.assertIs(handlers[1], logging.root.handlers[1])
        self.assertIs(handlers[2], logging.root.handlers[2])
        self.assertIsNotNone(handlers[0].formatter)
        self.assertIsNotNone(handlers[1].formatter)
        self.assertIs(handlers[2].formatter, f)
        self.assertIs(handlers[0].formatter, handlers[1].formatter)

    def _test_log(self, method, level=None):
        # logging.root has no handlers so basicConfig should be called
        called = []

        old_basic_config = logging.basicConfig
        def my_basic_config(*a, **kw):
            old_basic_config()
            old_level = logging.root.level
            logging.root.setLevel(100)  # avoid having messages in stderr
            self.addCleanup(logging.root.setLevel, old_level)
            called.append((a, kw))

        support.patch(self, logging, 'basicConfig', my_basic_config)

        log_method = getattr(logging, method)
        if level is not None:
            log_method(level, "test me")
        else:
            log_method("test me")

        # basicConfig was called with no arguments
        self.assertEqual(called, [((), {})])

    def test_log(self):
        self._test_log('log', logging.WARNING)

    def test_debug(self):
        self._test_log('debug')

    def test_info(self):
        self._test_log('info')

    def test_warning(self):
        self._test_log('warning')

    def test_error(self):
        self._test_log('error')

    def test_critical(self):
        self._test_log('critical')


class LoggerAdapterTest(unittest.TestCase):
    def setUp(self):
        super(LoggerAdapterTest, self).setUp()
        old_handler_list = logging._handlerList[:]

        self.recording = RecordingHandler()
        self.logger = logging.root
        self.logger.addHandler(self.recording)
        self.addCleanup(self.logger.removeHandler, self.recording)
        self.addCleanup(self.recording.close)

        def cleanup():
            logging._handlerList[:] = old_handler_list

        self.addCleanup(cleanup)
        self.addCleanup(logging.shutdown)
        self.adapter = logging.LoggerAdapter(logger=self.logger, extra=None)

    def test_exception(self):
        msg = 'testing exception: %r'
        exc = None
        try:
            1 / 0
        except ZeroDivisionError as e:
            exc = e
            self.adapter.exception(msg, self.recording)

        self.assertEqual(len(self.recording.records), 1)
        record = self.recording.records[0]
        self.assertEqual(record.levelno, logging.ERROR)
        self.assertEqual(record.msg, msg)
        self.assertEqual(record.args, (self.recording,))
        self.assertEqual(record.exc_info,
                         (exc.__class__, exc, exc.__traceback__))

    def test_exception_excinfo(self):
        try:
            1 / 0
        except ZeroDivisionError as e:
            exc = e

        self.adapter.exception('exc_info test', exc_info=exc)

        self.assertEqual(len(self.recording.records), 1)
        record = self.recording.records[0]
        self.assertEqual(record.exc_info,
                         (exc.__class__, exc, exc.__traceback__))

    def test_critical(self):
        msg = 'critical test! %r'
        self.adapter.critical(msg, self.recording)

        self.assertEqual(len(self.recording.records), 1)
        record = self.recording.records[0]
        self.assertEqual(record.levelno, logging.CRITICAL)
        self.assertEqual(record.msg, msg)
        self.assertEqual(record.args, (self.recording,))

    def test_is_enabled_for(self):
        old_disable = self.adapter.logger.manager.disable
        self.adapter.logger.manager.disable = 33
        self.addCleanup(setattr, self.adapter.logger.manager, 'disable',
                        old_disable)
        self.assertFalse(self.adapter.isEnabledFor(32))

    def test_has_handlers(self):
        self.assertTrue(self.adapter.hasHandlers())

        for handler in self.logger.handlers:
            self.logger.removeHandler(handler)

        self.assertFalse(self.logger.hasHandlers())
        self.assertFalse(self.adapter.hasHandlers())

    def test_nested(self):
        class Adapter(logging.LoggerAdapter):
            prefix = 'Adapter'

            def process(self, msg, kwargs):
                return f"{self.prefix} {msg}", kwargs

        msg = 'Adapters can be nested, yo.'
        adapter = Adapter(logger=self.logger, extra=None)
        adapter_adapter = Adapter(logger=adapter, extra=None)
        adapter_adapter.prefix = 'AdapterAdapter'
        self.assertEqual(repr(adapter), repr(adapter_adapter))
        adapter_adapter.log(logging.CRITICAL, msg, self.recording)
        self.assertEqual(len(self.recording.records), 1)
        record = self.recording.records[0]
        self.assertEqual(record.levelno, logging.CRITICAL)
        self.assertEqual(record.msg, f"Adapter AdapterAdapter {msg}")
        self.assertEqual(record.args, (self.recording,))
        orig_manager = adapter_adapter.manager
        self.assertIs(adapter.manager, orig_manager)
        self.assertIs(self.logger.manager, orig_manager)
        temp_manager = object()
        try:
            adapter_adapter.manager = temp_manager
            self.assertIs(adapter_adapter.manager, temp_manager)
            self.assertIs(adapter.manager, temp_manager)
            self.assertIs(self.logger.manager, temp_manager)
        finally:
            adapter_adapter.manager = orig_manager
        self.assertIs(adapter_adapter.manager, orig_manager)
        self.assertIs(adapter.manager, orig_manager)
        self.assertIs(self.logger.manager, orig_manager)


class LoggerTest(BaseTest):

    def setUp(self):
        super(LoggerTest, self).setUp()
        self.recording = RecordingHandler()
        self.logger = logging.Logger(name='blah')
        self.logger.addHandler(self.recording)
        self.addCleanup(self.logger.removeHandler, self.recording)
        self.addCleanup(self.recording.close)
        self.addCleanup(logging.shutdown)

    def test_set_invalid_level(self):
        self.assertRaises(TypeError, self.logger.setLevel, object())

    def test_exception(self):
        msg = 'testing exception: %r'
        exc = None
        try:
            1 / 0
        except ZeroDivisionError as e:
            exc = e
            self.logger.exception(msg, self.recording)

        self.assertEqual(len(self.recording.records), 1)
        record = self.recording.records[0]
        self.assertEqual(record.levelno, logging.ERROR)
        self.assertEqual(record.msg, msg)
        self.assertEqual(record.args, (self.recording,))
        self.assertEqual(record.exc_info,
                         (exc.__class__, exc, exc.__traceback__))

    def test_log_invalid_level_with_raise(self):
        with support.swap_attr(logging, 'raiseExceptions', True):
            self.assertRaises(TypeError, self.logger.log, '10', 'test message')

    def test_log_invalid_level_no_raise(self):
        with support.swap_attr(logging, 'raiseExceptions', False):
            self.logger.log('10', 'test message')  # no exception happens

    def test_find_caller_with_stack_info(self):
        called = []
        support.patch(self, logging.traceback, 'print_stack',
                      lambda f, file: called.append(file.getvalue()))

        self.logger.findCaller(stack_info=True)

        self.assertEqual(len(called), 1)
        self.assertEqual('Stack (most recent call last):\n', called[0])

    def test_make_record_with_extra_overwrite(self):
        name = 'my record'
        level = 13
        fn = lno = msg = args = exc_info = func = sinfo = None
        rv = logging._logRecordFactory(name, level, fn, lno, msg, args,
                                       exc_info, func, sinfo)

        for key in ('message', 'asctime') + tuple(rv.__dict__.keys()):
            extra = {key: 'some value'}
            self.assertRaises(KeyError, self.logger.makeRecord, name, level,
                              fn, lno, msg, args, exc_info,
                              extra=extra, sinfo=sinfo)

    def test_make_record_with_extra_no_overwrite(self):
        name = 'my record'
        level = 13
        fn = lno = msg = args = exc_info = func = sinfo = None
        extra = {'valid_key': 'some value'}
        result = self.logger.makeRecord(name, level, fn, lno, msg, args,
                                        exc_info, extra=extra, sinfo=sinfo)
        self.assertIn('valid_key', result.__dict__)

    def test_has_handlers(self):
        self.assertTrue(self.logger.hasHandlers())

        for handler in self.logger.handlers:
            self.logger.removeHandler(handler)
        self.assertFalse(self.logger.hasHandlers())

    def test_has_handlers_no_propagate(self):
        child_logger = logging.getLogger('blah.child')
        child_logger.propagate = False
        self.assertFalse(child_logger.hasHandlers())

    def test_is_enabled_for(self):
        old_disable = self.logger.manager.disable
        self.logger.manager.disable = 23
        self.addCleanup(setattr, self.logger.manager, 'disable', old_disable)
        self.assertFalse(self.logger.isEnabledFor(22))

    def test_root_logger_aliases(self):
        root = logging.getLogger()
        self.assertIs(root, logging.root)
        self.assertIs(root, logging.getLogger(None))
        self.assertIs(root, logging.getLogger(''))
        self.assertIs(root, logging.getLogger('foo').root)
        self.assertIs(root, logging.getLogger('foo.bar').root)
        self.assertIs(root, logging.getLogger('foo').parent)

        self.assertIsNot(root, logging.getLogger('\0'))
        self.assertIsNot(root, logging.getLogger('foo.bar').parent)

    def test_invalid_names(self):
        self.assertRaises(TypeError, logging.getLogger, any)
        self.assertRaises(TypeError, logging.getLogger, b'foo')

    def test_pickling(self):
        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
            for name in ('', 'root', 'foo', 'foo.bar', 'baz.bar'):
                logger = logging.getLogger(name)
                s = pickle.dumps(logger, proto)
                unpickled = pickle.loads(s)
                self.assertIs(unpickled, logger)

    def test_caching(self):
        root = self.root_logger
        logger1 = logging.getLogger("abc")
        logger2 = logging.getLogger("abc.def")

        # Set root logger level and ensure cache is empty
        root.setLevel(logging.ERROR)
        self.assertEqual(logger2.getEffectiveLevel(), logging.ERROR)
        self.assertEqual(logger2._cache, {})

        # Ensure cache is populated and calls are consistent
        self.assertTrue(logger2.isEnabledFor(logging.ERROR))
        self.assertFalse(logger2.isEnabledFor(logging.DEBUG))
        self.assertEqual(logger2._cache, {logging.ERROR: True, logging.DEBUG: False})
        self.assertEqual(root._cache, {})
        self.assertTrue(logger2.isEnabledFor(logging.ERROR))

        # Ensure root cache gets populated
        self.assertEqual(root._cache, {})
        self.assertTrue(root.isEnabledFor(logging.ERROR))
        self.assertEqual(root._cache, {logging.ERROR: True})

        # Set parent logger level and ensure caches are emptied
        logger1.setLevel(logging.CRITICAL)
        self.assertEqual(logger2.getEffectiveLevel(), logging.CRITICAL)
        self.assertEqual(logger2._cache, {})

        # Ensure logger2 uses parent logger's effective level
        self.assertFalse(logger2.isEnabledFor(logging.ERROR))

        # Set level to NOTSET and ensure caches are empty
        logger2.setLevel(logging.NOTSET)
        self.assertEqual(logger2.getEffectiveLevel(), logging.CRITICAL)
        self.assertEqual(logger2._cache, {})
        self.assertEqual(logger1._cache, {})
        self.assertEqual(root._cache, {})

        # Verify logger2 follows parent and not root
        self.assertFalse(logger2.isEnabledFor(logging.ERROR))
        self.assertTrue(logger2.isEnabledFor(logging.CRITICAL))
        self.assertFalse(logger1.isEnabledFor(logging.ERROR))
        self.assertTrue(logger1.isEnabledFor(logging.CRITICAL))
        self.assertTrue(root.isEnabledFor(logging.ERROR))

        # Disable logging in manager and ensure caches are clear
        logging.disable()
        self.assertEqual(logger2.getEffectiveLevel(), logging.CRITICAL)
        self.assertEqual(logger2._cache, {})
        self.assertEqual(logger1._cache, {})
        self.assertEqual(root._cache, {})

        # Ensure no loggers are enabled
        self.assertFalse(logger1.isEnabledFor(logging.CRITICAL))
        self.assertFalse(logger2.isEnabledFor(logging.CRITICAL))
        self.assertFalse(root.isEnabledFor(logging.CRITICAL))


class BaseFileTest(BaseTest):
    "Base class for handler tests that write log files"

    def setUp(self):
        BaseTest.setUp(self)
        fd, self.fn = tempfile.mkstemp(".log", "test_logging-2-")
        os.close(fd)
        self.rmfiles = []

    def tearDown(self):
        for fn in self.rmfiles:
            os.unlink(fn)
        if os.path.exists(self.fn):
            os.unlink(self.fn)
        BaseTest.tearDown(self)

    def assertLogFile(self, filename):
        "Assert a log file is there and register it for deletion"
        self.assertTrue(os.path.exists(filename),
                        msg="Log file %r does not exist" % filename)
        self.rmfiles.append(filename)


class FileHandlerTest(BaseFileTest):
    def test_delay(self):
        os.unlink(self.fn)
        fh = logging.FileHandler(self.fn, delay=True)
        self.assertIsNone(fh.stream)
        self.assertFalse(os.path.exists(self.fn))
        fh.handle(logging.makeLogRecord({}))
        self.assertIsNotNone(fh.stream)
        self.assertTrue(os.path.exists(self.fn))
        fh.close()

class RotatingFileHandlerTest(BaseFileTest):
    def next_rec(self):
        return logging.LogRecord('n', logging.DEBUG, 'p', 1,
                                 self.next_message(), None, None, None)

    def test_should_not_rollover(self):
        # If maxbytes is zero rollover never occurs
        rh = logging.handlers.RotatingFileHandler(self.fn, maxBytes=0)
        self.assertFalse(rh.shouldRollover(None))
        rh.close()

    def test_should_rollover(self):
        rh = logging.handlers.RotatingFileHandler(self.fn, maxBytes=1)
        self.assertTrue(rh.shouldRollover(self.next_rec()))
        rh.close()

    def test_file_created(self):
        # checks that the file is created and assumes it was created
        # by us
        rh = logging.handlers.RotatingFileHandler(self.fn)
        rh.emit(self.next_rec())
        self.assertLogFile(self.fn)
        rh.close()

    def test_rollover_filenames(self):
        def namer(name):
            return name + ".test"
        rh = logging.handlers.RotatingFileHandler(
            self.fn, backupCount=2, maxBytes=1)
        rh.namer = namer
        rh.emit(self.next_rec())
        self.assertLogFile(self.fn)
        rh.emit(self.next_rec())
        self.assertLogFile(namer(self.fn + ".1"))
        rh.emit(self.next_rec())
        self.assertLogFile(namer(self.fn + ".2"))
        self.assertFalse(os.path.exists(namer(self.fn + ".3")))
        rh.close()

    @support.requires_zlib
    def test_rotator(self):
        def namer(name):
            return name + ".gz"

        def rotator(source, dest):
            with open(source, "rb") as sf:
                data = sf.read()
                compressed = zlib.compress(data, 9)
                with open(dest, "wb") as df:
                    df.write(compressed)
            os.remove(source)

        rh = logging.handlers.RotatingFileHandler(
            self.fn, backupCount=2, maxBytes=1)
        rh.rotator = rotator
        rh.namer = namer
        m1 = self.next_rec()
        rh.emit(m1)
        self.assertLogFile(self.fn)
        m2 = self.next_rec()
        rh.emit(m2)
        fn = namer(self.fn + ".1")
        self.assertLogFile(fn)
        newline = os.linesep
        with open(fn, "rb") as f:
            compressed = f.read()
            data = zlib.decompress(compressed)
            self.assertEqual(data.decode("ascii"), m1.msg + newline)
        rh.emit(self.next_rec())
        fn = namer(self.fn + ".2")
        self.assertLogFile(fn)
        with open(fn, "rb") as f:
            compressed = f.read()
            data = zlib.decompress(compressed)
            self.assertEqual(data.decode("ascii"), m1.msg + newline)
        rh.emit(self.next_rec())
        fn = namer(self.fn + ".2")
        with open(fn, "rb") as f:
            compressed = f.read()
            data = zlib.decompress(compressed)
            self.assertEqual(data.decode("ascii"), m2.msg + newline)
        self.assertFalse(os.path.exists(namer(self.fn + ".3")))
        rh.close()

class TimedRotatingFileHandlerTest(BaseFileTest):
    # other test methods added below
    def test_rollover(self):
        fh = logging.handlers.TimedRotatingFileHandler(self.fn, 'S',
                                                       backupCount=1)
        fmt = logging.Formatter('%(asctime)s %(message)s')
        fh.setFormatter(fmt)
        r1 = logging.makeLogRecord({'msg': 'testing - initial'})
        fh.emit(r1)
        self.assertLogFile(self.fn)
        time.sleep(1.1)    # a little over a second ...
        r2 = logging.makeLogRecord({'msg': 'testing - after delay'})
        fh.emit(r2)
        fh.close()
        # At this point, we should have a recent rotated file which we
        # can test for the existence of. However, in practice, on some
        # machines which run really slowly, we don't know how far back
        # in time to go to look for the log file. So, we go back a fair
        # bit, and stop as soon as we see a rotated file. In theory this
        # could of course still fail, but the chances are lower.
        found = False
        now = datetime.datetime.now()
        GO_BACK = 5 * 60 # seconds
        for secs in range(GO_BACK):
            prev = now - datetime.timedelta(seconds=secs)
            fn = self.fn + prev.strftime(".%Y-%m-%d_%H-%M-%S")
            found = os.path.exists(fn)
            if found:
                self.rmfiles.append(fn)
                break
        msg = 'No rotated files found, went back %d seconds' % GO_BACK
        if not found:
            # print additional diagnostics
            dn, fn = os.path.split(self.fn)
            files = [f for f in os.listdir(dn) if f.startswith(fn)]
            print('Test time: %s' % now.strftime("%Y-%m-%d %H-%M-%S"), file=sys.stderr)
            print('The only matching files are: %s' % files, file=sys.stderr)
            for f in files:
                print('Contents of %s:' % f)
                path = os.path.join(dn, f)
                with open(path, 'r') as tf:
                    print(tf.read())
        self.assertTrue(found, msg=msg)

    def test_invalid(self):
        assertRaises = self.assertRaises
        assertRaises(ValueError, logging.handlers.TimedRotatingFileHandler,
                     self.fn, 'X', delay=True)
        assertRaises(ValueError, logging.handlers.TimedRotatingFileHandler,
                     self.fn, 'W', delay=True)
        assertRaises(ValueError, logging.handlers.TimedRotatingFileHandler,
                     self.fn, 'W7', delay=True)

    def test_compute_rollover_daily_attime(self):
        currentTime = 0
        atTime = datetime.time(12, 0, 0)
        rh = logging.handlers.TimedRotatingFileHandler(
            self.fn, when='MIDNIGHT', interval=1, backupCount=0, utc=True,
            atTime=atTime)
        try:
            actual = rh.computeRollover(currentTime)
            self.assertEqual(actual, currentTime + 12 * 60 * 60)

            actual = rh.computeRollover(currentTime + 13 * 60 * 60)
            self.assertEqual(actual, currentTime + 36 * 60 * 60)
        finally:
            rh.close()

    #@unittest.skipIf(True, 'Temporarily skipped while failures investigated.')
    def test_compute_rollover_weekly_attime(self):
        currentTime = int(time.time())
        today = currentTime - currentTime % 86400

        atTime = datetime.time(12, 0, 0)

        wday = time.gmtime(today).tm_wday
        for day in range(7):
            rh = logging.handlers.TimedRotatingFileHandler(
                self.fn, when='W%d' % day, interval=1, backupCount=0, utc=True,
                atTime=atTime)
            try:
                if wday > day:
                    # The rollover day has already passed this week, so we
                    # go over into next week
                    expected = (7 - wday + day)
                else:
                    expected = (day - wday)
                # At this point expected is in days from now, convert to seconds
                expected *= 24 * 60 * 60
                # Add in the rollover time
                expected += 12 * 60 * 60
                # Add in adjustment for today
                expected += today
                actual = rh.computeRollover(today)
                if actual != expected:
                    print('failed in timezone: %d' % time.timezone)
                    print('local vars: %s' % locals())
                self.assertEqual(actual, expected)
                if day == wday:
                    # goes into following week
                    expected += 7 * 24 * 60 * 60
                actual = rh.computeRollover(today + 13 * 60 * 60)
                if actual != expected:
                    print('failed in timezone: %d' % time.timezone)
                    print('local vars: %s' % locals())
                self.assertEqual(actual, expected)
            finally:
                rh.close()


def secs(**kw):
    return datetime.timedelta(**kw) // datetime.timedelta(seconds=1)

for when, exp in (('S', 1),
                  ('M', 60),
                  ('H', 60 * 60),
                  ('D', 60 * 60 * 24),
                  ('MIDNIGHT', 60 * 60 * 24),
                  # current time (epoch start) is a Thursday, W0 means Monday
                  ('W0', secs(days=4, hours=24)),
                 ):
    def test_compute_rollover(self, when=when, exp=exp):
        rh = logging.handlers.TimedRotatingFileHandler(
            self.fn, when=when, interval=1, backupCount=0, utc=True)
        currentTime = 0.0
        actual = rh.computeRollover(currentTime)
        if exp != actual:
            # Failures occur on some systems for MIDNIGHT and W0.
            # Print detailed calculation for MIDNIGHT so we can try to see
            # what's going on
            if when == 'MIDNIGHT':
                try:
                    if rh.utc:
                        t = time.gmtime(currentTime)
                    else:
                        t = time.localtime(currentTime)
                    currentHour = t[3]
                    currentMinute = t[4]
                    currentSecond = t[5]
                    # r is the number of seconds left between now and midnight
                    r = logging.handlers._MIDNIGHT - ((currentHour * 60 +
                                                       currentMinute) * 60 +
                            currentSecond)
                    result = currentTime + r
                    print('t: %s (%s)' % (t, rh.utc), file=sys.stderr)
                    print('currentHour: %s' % currentHour, file=sys.stderr)
                    print('currentMinute: %s' % currentMinute, file=sys.stderr)
                    print('currentSecond: %s' % currentSecond, file=sys.stderr)
                    print('r: %s' % r, file=sys.stderr)
                    print('result: %s' % result, file=sys.stderr)
                except Exception:
                    print('exception in diagnostic code: %s' % sys.exc_info()[1], file=sys.stderr)
        self.assertEqual(exp, actual)
        rh.close()
    setattr(TimedRotatingFileHandlerTest, "test_compute_rollover_%s" % when, test_compute_rollover)


@unittest.skipUnless(win32evtlog, 'win32evtlog/win32evtlogutil/pywintypes required for this test.')
class NTEventLogHandlerTest(BaseTest):
    def test_basic(self):
        logtype = 'Application'
        elh = win32evtlog.OpenEventLog(None, logtype)
        num_recs = win32evtlog.GetNumberOfEventLogRecords(elh)

        try:
            h = logging.handlers.NTEventLogHandler('test_logging')
        except pywintypes.error as e:
            if e.winerror == 5:  # access denied
                raise unittest.SkipTest('Insufficient privileges to run test')
            raise

        r = logging.makeLogRecord({'msg': 'Test Log Message'})
        h.handle(r)
        h.close()
        # Now see if the event is recorded
        self.assertLess(num_recs, win32evtlog.GetNumberOfEventLogRecords(elh))
        flags = win32evtlog.EVENTLOG_BACKWARDS_READ | \
                win32evtlog.EVENTLOG_SEQUENTIAL_READ
        found = False
        GO_BACK = 100
        events = win32evtlog.ReadEventLog(elh, flags, GO_BACK)
        for e in events:
            if e.SourceName != 'test_logging':
                continue
            msg = win32evtlogutil.SafeFormatMessage(e, logtype)
            if msg != 'Test Log Message\r\n':
                continue
            found = True
            break
        msg = 'Record not found in event log, went back %d records' % GO_BACK
        self.assertTrue(found, msg=msg)


class MiscTestCase(unittest.TestCase):
    def test__all__(self):
        blacklist = {'logThreads', 'logMultiprocessing',
                     'logProcesses', 'currentframe',
                     'PercentStyle', 'StrFormatStyle', 'StringTemplateStyle',
                     'Filterer', 'PlaceHolder', 'Manager', 'RootLogger',
                     'root', 'threading'}
        support.check__all__(self, logging, blacklist=blacklist)


# Set the locale to the platform-dependent default.  I have no idea
# why the test does this, but in any case we save the current locale
# first and restore it at the end.
@support.run_with_locale('LC_ALL', '')
def test_main():
    tests = [
        BuiltinLevelsTest, BasicFilterTest, CustomLevelsAndFiltersTest,
        HandlerTest, MemoryHandlerTest, ConfigFileTest, SocketHandlerTest,
        DatagramHandlerTest, MemoryTest, EncodingTest, WarningsTest,
        ConfigDictTest, ManagerTest, FormatterTest, BufferingFormatterTest,
        StreamHandlerTest, LogRecordFactoryTest, ChildLoggerTest,
        QueueHandlerTest, ShutdownTest, ModuleLevelMiscTest, BasicConfigTest,
        LoggerAdapterTest, LoggerTest, SMTPHandlerTest, FileHandlerTest,
        RotatingFileHandlerTest,  LastResortTest, LogRecordTest,
        ExceptionTest, SysLogHandlerTest, IPv6SysLogHandlerTest, HTTPHandlerTest,
        NTEventLogHandlerTest, TimedRotatingFileHandlerTest,
        UnixSocketHandlerTest, UnixDatagramHandlerTest, UnixSysLogHandlerTest,
        MiscTestCase
    ]
    if hasattr(logging.handlers, 'QueueListener'):
        tests.append(QueueListenerTest)
    support.run_unittest(*tests)

if __name__ == "__main__":
    test_main()


Current_dir [ 𝗡𝗢𝗧 𝗪𝗥𝗜𝗧𝗘𝗔𝗕𝗟𝗘 ] Document_root [ 𝗪𝗥𝗜𝗧𝗘𝗔𝗕𝗟𝗘 ]


[ Back ]
𝗡𝗔𝗠𝗘
𝗦𝗜𝗭𝗘
𝗟𝗔𝗦𝗧 𝗧𝗢𝗨𝗖𝗛
𝗨𝗦𝗘𝗥
𝗦𝗧𝗔𝗧𝗨𝗦
𝗙𝗨𝗡𝗖𝗧𝗜𝗢𝗡𝗦
..
--
25 Jul 2024 8.44 AM
root / linksafe
0755
__pycache__
--
25 Jul 2024 8.42 AM
root / linksafe
0755
audiodata
--
25 Jul 2024 8.42 AM
root / linksafe
0755
capath
--
25 Jul 2024 8.42 AM
root / linksafe
0755
cjkencodings
--
25 Jul 2024 8.42 AM
root / linksafe
0755
data
--
25 Jul 2024 8.42 AM
root / linksafe
0755
decimaltestdata
--
25 Jul 2024 8.42 AM
root / linksafe
0755
dtracedata
--
25 Jul 2024 8.42 AM
root / linksafe
0755
eintrdata
--
25 Jul 2024 8.42 AM
root / linksafe
0755
encoded_modules
--
25 Jul 2024 8.42 AM
root / linksafe
0755
imghdrdata
--
25 Jul 2024 8.42 AM
root / linksafe
0755
libregrtest
--
25 Jul 2024 8.42 AM
root / linksafe
0755
sndhdrdata
--
25 Jul 2024 8.42 AM
root / linksafe
0755
subprocessdata
--
25 Jul 2024 8.42 AM
root / linksafe
0755
support
--
25 Jul 2024 8.42 AM
root / linksafe
0755
test_asyncio
--
25 Jul 2024 8.42 AM
root / linksafe
0755
test_email
--
25 Jul 2024 8.42 AM
root / linksafe
0755
test_import
--
25 Jul 2024 8.42 AM
root / linksafe
0755
test_importlib
--
25 Jul 2024 8.42 AM
root / linksafe
0755
test_json
--
25 Jul 2024 8.42 AM
root / linksafe
0755
test_tools
--
25 Jul 2024 8.42 AM
root / linksafe
0755
test_warnings
--
25 Jul 2024 8.42 AM
root / linksafe
0755
tracedmodules
--
25 Jul 2024 8.42 AM
root / linksafe
0755
xmltestdata
--
25 Jul 2024 8.42 AM
root / linksafe
0755
Sine-1000Hz-300ms.aif
60.25 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
__init__.py
0.046 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
__main__.py
0.04 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
_test_multiprocessing.py
157.176 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
allsans.pem
4.919 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
ann_module.py
1.078 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
ann_module2.py
0.507 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
ann_module3.py
0.438 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
audiotests.py
12.462 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
autotest.py
0.204 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
bad_coding.py
0.023 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
bad_coding2.py
0.029 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
bad_getattr.py
0.06 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
bad_getattr2.py
0.075 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
bad_getattr3.py
0.136 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
badcert.pem
1.883 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
badkey.pem
2.111 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
badsyntax_3131.py
0.031 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
badsyntax_future10.py
0.093 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
badsyntax_future3.py
0.168 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
badsyntax_future4.py
0.149 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
badsyntax_future5.py
0.18 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
badsyntax_future6.py
0.157 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
badsyntax_future7.py
0.191 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
badsyntax_future8.py
0.119 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
badsyntax_future9.py
0.139 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
badsyntax_pep3120.py
0.014 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
bisect_cmd.py
4.862 KB
17 Apr 2024 5.36 PM
root / linksafe
0755
bytecode_helper.py
1.563 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
cfgparser.1
0.065 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
cfgparser.2
19.016 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
cfgparser.3
1.55 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
clinic.test
36.313 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
cmath_testcases.txt
141.047 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
coding20731.py
0.018 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
curses_tests.py
1.225 KB
17 Apr 2024 5.36 PM
root / linksafe
0755
dataclass_module_1.py
0.817 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
dataclass_module_1_str.py
0.815 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
dataclass_module_2.py
0.738 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
dataclass_module_2_str.py
0.736 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
dataclass_textanno.py
0.123 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
datetimetester.py
230.635 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
dis_module.py
0.074 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
doctest_aliases.py
0.234 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
double_const.py
1.184 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
empty.vbs
0.068 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
exception_hierarchy.txt
1.779 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
ffdh3072.pem
2.16 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
final_a.py
0.401 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
final_b.py
0.401 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
floating_points.txt
15.92 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
fork_wait.py
2.53 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
formatfloat_testcases.txt
7.451 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
future_test1.py
0.224 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
future_test2.py
0.146 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
gdb_sample.py
0.149 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
good_getattr.py
0.193 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
idnsans.pem
9.709 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
ieee754.txt
3.206 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
imp_dummy.py
0.062 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
inspect_fodder.py
1.238 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
inspect_fodder2.py
1.773 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
keycert.passwd.pem
4.126 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
keycert.pem
3.963 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
keycert2.pem
3.971 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
keycert3.pem
9.219 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
keycert4.pem
9.232 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
keycertecc.pem
5.501 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
list_tests.py
16.539 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
lock_tests.py
28.265 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
mailcap.txt
1.24 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
make_ssl_certs.py
8.523 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
mapping_tests.py
21.746 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
math_testcases.txt
23.186 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
memory_watchdog.py
0.839 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
mime.types
47.372 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
mock_socket.py
3.526 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
mod_generics_cache.py
1.133 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
mp_fork_bomb.py
0.438 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
mp_preload.py
0.343 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
multibytecodec_support.py
14.169 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
nokia.pem
1.878 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
nullbytecert.pem
5.308 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
nullcert.pem
0 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
outstanding_bugs.py
0.361 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
pickletester.py
108.893 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
profilee.py
2.97 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
pstats.pck
65.046 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
pycacert.pem
5.523 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
pycakey.pem
2.426 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
pyclbr_input.py
0.633 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
pydoc_mod.py
0.696 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
pydocfodder.py
6.184 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
pythoninfo.py
18.748 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
randv2_32.pck
7.341 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
randv2_64.pck
7.192 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
randv3.pck
7.816 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
re_tests.py
31.058 KB
17 Apr 2024 5.36 PM
root / linksafe
0755
recursion.tar
0.504 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
regrtest.py
1.345 KB
17 Apr 2024 5.36 PM
root / linksafe
0755
relimport.py
0.026 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
reperf.py
0.525 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
revocation.crl
0.781 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
sample_doctest.py
1.017 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
sample_doctest_no_docstrings.py
0.222 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
sample_doctest_no_doctests.py
0.263 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
secp384r1.pem
0.25 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
selfsigned_pythontestdotnet.pem
2.08 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
seq_tests.py
14.183 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
sgml_input.html
8.1 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
signalinterproctester.py
2.696 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
sortperf.py
4.693 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
ssl_cert.pem
1.533 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
ssl_key.passwd.pem
2.592 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
ssl_key.pem
2.43 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
ssl_servers.py
7.042 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
ssltests.py
1.026 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
string_tests.py
64.655 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
talos-2019-0758.pem
1.299 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
test___all__.py
3.809 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test___future__.py
2.364 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test__locale.py
7.71 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test__opcode.py
0.83 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test__osx_support.py
13.655 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_abc.py
18.001 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_abstract_numbers.py
1.492 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_aifc.py
17.7 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_argparse.py
169.132 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_array.py
47.38 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_asdl_parser.py
3.924 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_ast.py
56.941 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_asyncgen.py
33.206 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_asynchat.py
9.309 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_asyncore.py
25.812 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_atexit.py
5.812 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_audioop.py
28.236 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_augassign.py
7.684 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_base64.py
30.169 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_baseexception.py
6.864 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_bdb.py
41.21 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_bigaddrspace.py
2.92 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_bigmem.py
44.883 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_binascii.py
16.938 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_binhex.py
1.463 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_binop.py
14.14 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_bisect.py
13.633 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_bool.py
12.519 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_buffer.py
159.076 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_bufio.py
2.536 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_builtin.py
71.426 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_bytes.py
68.752 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_bz2.py
36.694 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_c_locale_coercion.py
18.344 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_calendar.py
48.715 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_call.py
14.591 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_capi.py
22.542 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_cgi.py
23.439 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_cgitb.py
2.505 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_charmapcodec.py
1.678 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_class.py
16.935 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_clinic.py
21.24 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_cmath.py
24.275 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_cmd.py
6.103 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_cmd_line.py
31.752 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_cmd_line_script.py
29.146 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_code.py
10.402 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_code_module.py
5.514 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_codeccallbacks.py
42.796 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_codecencodings_cn.py
3.857 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_codecencodings_hk.py
0.685 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_codecencodings_iso2022.py
1.357 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_codecencodings_jp.py
4.792 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_codecencodings_kr.py
2.957 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_codecencodings_tw.py
0.665 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_codecmaps_cn.py
0.729 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_codecmaps_hk.py
0.377 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_codecmaps_jp.py
1.703 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_codecmaps_kr.py
1.16 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_codecmaps_tw.py
0.688 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_codecs.py
130.731 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_codeop.py
7.626 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_collections.py
79.609 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_colorsys.py
3.835 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_compare.py
3.822 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_compile.py
34.987 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_compileall.py
26.775 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_complex.py
29.677 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_concurrent_futures.py
43.15 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_configparser.py
84.69 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_contains.py
3.485 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_context.py
30.744 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_contextlib.py
32.498 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_contextlib_async.py
14.695 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_copy.py
25.813 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_copyreg.py
4.393 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_coroutines.py
62.272 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_cprofile.py
6.154 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_crashers.py
1.156 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_crypt.py
3.505 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_csv.py
47.06 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_ctypes.py
0.18 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_curses.py
18.85 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_dataclasses.py
107.41 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_datetime.py
2.149 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_dbm.py
6.436 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_dbm_dumb.py
10.772 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_dbm_gnu.py
5.219 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_dbm_ndbm.py
4.306 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_decimal.py
207.145 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_decorators.py
9.477 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_defaultdict.py
5.876 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_deque.py
33.839 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_descr.py
185.702 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_descrtut.py
11.527 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_devpoll.py
4.51 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_dict.py
40.024 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_dict_version.py
5.869 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_dictcomps.py
3.668 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_dictviews.py
11.684 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_difflib.py
19.358 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_difflib_expect.html
100.846 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
test_dis.py
48.528 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_distutils.py
0.366 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_doctest.py
98.512 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_doctest.txt
0.293 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
test_doctest2.py
2.304 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_doctest2.txt
0.383 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
test_doctest3.txt
0.08 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
test_doctest4.txt
0.238 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
test_docxmlrpc.py
8.697 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_dtrace.py
5.23 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_dummy_thread.py
9.694 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_dummy_threading.py
1.702 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_dynamic.py
4.291 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_dynamicclassattribute.py
9.565 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_eintr.py
1.321 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_embed.py
20.383 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_ensurepip.py
9.828 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_enum.py
106.033 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_enumerate.py
7.897 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_eof.py
0.784 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_epoll.py
8.993 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_errno.py
1.044 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_exception_hierarchy.py
7.229 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_exception_variations.py
3.855 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_exceptions.py
47.483 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_extcall.py
12.09 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_faulthandler.py
27.983 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_fcntl.py
6.23 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_file.py
10.613 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_file_eintr.py
10.6 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_filecmp.py
8.686 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_fileinput.py
37.294 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_fileio.py
19.188 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_finalization.py
14.162 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_float.py
63.005 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_flufl.py
1.315 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_fnmatch.py
5.065 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_fork1.py
3.715 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_format.py
22.473 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_fractions.py
27.029 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_frame.py
5.67 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_frozen.py
0.947 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_fstring.py
40.232 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_ftplib.py
39.749 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_funcattrs.py
13.252 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_functools.py
82.598 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_future.py
9.983 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_future3.py
0.479 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_future4.py
0.217 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_future5.py
0.498 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_gc.py
36.082 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_gdb.py
40.089 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_generator_stop.py
0.921 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_generators.py
58.475 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_genericclass.py
9.282 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_genericpath.py
20.54 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_genexps.py
7.115 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_getargs2.py
45.504 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_getopt.py
6.748 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_getpass.py
6.286 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_gettext.py
33.118 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_glob.py
12.391 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_global.py
1.309 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_grammar.py
48.456 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_grp.py
3.543 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_gzip.py
27.717 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_hash.py
11.447 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_hashlib.py
39.089 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_heapq.py
15.657 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_hmac.py
21.513 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_html.py
4.234 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_htmlparser.py
31.932 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_http_cookiejar.py
75.636 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_http_cookies.py
18.126 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_httplib.py
76.63 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_httpservers.py
47.562 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_idle.py
0.803 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_imaplib.py
38.823 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_imghdr.py
4.655 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_imp.py
17.316 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_index.py
8.366 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_inspect.py
145.165 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_int.py
26.926 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_int_literal.py
6.888 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_io.py
160.77 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_ioctl.py
3.194 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_ipaddress.py
91.434 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_isinstance.py
9.913 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_iter.py
31.508 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_iterlen.py
7.096 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_itertools.py
99.188 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_keyword.py
5.703 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_keywordonlyarg.py
6.853 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_kqueue.py
8.806 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_largefile.py
6.831 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_lib2to3.py
0.099 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_linecache.py
7.793 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_list.py
7.688 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_listcomps.py
3.763 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_locale.py
23.556 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_logging.py
166.707 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_long.py
52.805 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_longexp.py
0.228 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_lzma.py
87.864 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_macpath.py
6.199 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_mailbox.py
90.645 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_mailcap.py
10.03 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_marshal.py
19.622 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_math.py
63.88 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_memoryio.py
31.483 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_memoryview.py
17.438 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_metaclass.py
6.201 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_mimetypes.py
8.615 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_minidom.py
65.824 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_mmap.py
27.792 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_module.py
10.302 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_modulefinder.py
9.055 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_msilib.py
4.371 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_multibytecodec.py
10.064 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_multiprocessing_fork.py
0.466 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_multiprocessing_forkserver.py
0.383 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_multiprocessing_main_handling.py
11.446 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_multiprocessing_spawn.py
0.271 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_netrc.py
5.935 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_nis.py
1.129 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_nntplib.py
61.695 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_normalization.py
3.323 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_ntpath.py
23.954 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_numeric_tower.py
7.18 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_opcodes.py
3.605 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_openpty.py
0.586 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_operator.py
22.744 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_optparse.py
60.994 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_ordered_dict.py
29.375 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_os.py
139.152 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_ossaudiodev.py
7.057 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_osx_env.py
1.297 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_parser.py
33.129 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pathlib.py
91.461 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pdb.py
49.149 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_peepholer.py
12.809 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pickle.py
18.572 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pickletools.py
4.231 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pipes.py
6.593 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pkg.py
9.594 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pkgimport.py
2.665 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pkgutil.py
17.612 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_platform.py
17.387 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_plistlib.py
37.006 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_poll.py
7.231 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_popen.py
1.978 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_poplib.py
16.885 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_posix.py
61.465 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_posixpath.py
28.659 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pow.py
4.366 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pprint.py
43.489 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_print.py
7.37 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_profile.py
7.707 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_property.py
8.77 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pstats.py
2.889 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pty.py
11.968 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pulldom.py
12.332 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pwd.py
4.165 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_py_compile.py
8.137 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pyclbr.py
9.45 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pydoc.py
46.614 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_pyexpat.py
26.522 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_queue.py
19.069 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_quopri.py
7.775 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_raise.py
12.778 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_random.py
41.092 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_range.py
23.351 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_re.py
104.304 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_readline.py
12.946 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_regrtest.py
44.921 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_repl.py
2.249 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_reprlib.py
15.115 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_resource.py
6.796 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_richcmp.py
11.91 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_rlcompleter.py
6.298 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_robotparser.py
10.015 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_runpy.py
31.047 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_sax.py
45.459 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_sched.py
6.407 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_scope.py
19.704 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_script_helper.py
5.777 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_secrets.py
4.278 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_select.py
2.646 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_selectors.py
17.788 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_set.py
64.411 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_setcomps.py
3.703 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_shelve.py
6.239 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_shlex.py
11.244 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_shutil.py
78.63 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_signal.py
40.195 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_site.py
27.055 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_slice.py
8.247 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_smtpd.py
40.145 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_smtplib.py
52.911 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_smtpnet.py
2.868 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_sndhdr.py
1.426 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_socket.py
223.554 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_socketserver.py
16.872 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_sort.py
13.425 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_source_encoding.py
7.891 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_spwd.py
2.709 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_sqlite.py
0.926 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_ssl.py
195.891 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_startfile.py
1.165 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_stat.py
7.963 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_statistics.py
74.347 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_strftime.py
7.542 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_string.py
19.797 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_string_literals.py
9.827 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_stringprep.py
3.04 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_strptime.py
34.205 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_strtod.py
20.056 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_struct.py
33.4 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_structmembers.py
4.703 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_structseq.py
3.871 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_subclassinit.py
8.118 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_subprocess.py
139.503 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_sunau.py
6.068 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_sundry.py
2.038 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_super.py
10.652 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_support.py
23.45 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_symbol.py
1.855 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_symtable.py
6.931 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_syntax.py
22.135 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_sys.py
49.65 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_sys_setprofile.py
11.421 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_sys_settrace.py
39.976 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_sysconfig.py
18.339 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_syslog.py
1.15 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_tarfile.py
97.462 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_tcl.py
29.202 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_telnetlib.py
12.698 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_tempfile.py
51.009 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_textwrap.py
38.838 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_thread.py
8.419 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_threaded_import.py
8.913 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_threadedtempfile.py
1.865 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_threading.py
44.214 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_threading_local.py
6.088 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_threadsignals.py
10.092 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_time.py
38.884 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_timeit.py
14.799 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_timeout.py
11.189 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_tix.py
0.738 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_tk.py
0.354 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_tokenize.py
62.677 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_trace.py
17.454 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_traceback.py
43.482 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_tracemalloc.py
36.438 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_ttk_guionly.py
0.729 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_ttk_textonly.py
0.292 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_tuple.py
7.578 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_turtle.py
12.36 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_typechecks.py
2.554 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_types.py
57.998 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_typing.py
92.67 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_ucn.py
9.352 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_unary.py
1.626 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_unicode.py
130.275 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_unicode_file.py
5.729 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_unicode_file_functions.py
6.84 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_unicode_identifiers.py
0.87 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_unicodedata.py
12.6 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_unittest.py
0.279 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_univnewlines.py
3.83 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_unpack.py
3.014 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_unpack_ex.py
8.731 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_urllib.py
68.913 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_urllib2.py
77.008 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_urllib2_localnet.py
24.258 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_urllib2net.py
12.394 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_urllib_response.py
1.688 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_urllibnet.py
8.901 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_urlparse.py
63.231 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_userdict.py
7.638 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_userlist.py
1.969 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_userstring.py
1.435 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_utf8_mode.py
9.168 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_utf8source.py
1.147 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_uu.py
8.834 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_uuid.py
34.146 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_venv.py
19.97 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_wait3.py
1.155 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_wait4.py
1.154 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_wave.py
6.573 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_weakref.py
68.941 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_weakset.py
14.952 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_webbrowser.py
10.471 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_winconsoleio.py
6.146 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_winreg.py
21.246 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_winsound.py
4.567 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_with.py
25.779 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_wsgiref.py
29.722 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_xdrlib.py
2.174 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_xml_dom_minicompat.py
4.182 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_xml_etree.py
116.47 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_xml_etree_c.py
8.114 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_xmlrpc.py
54.092 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_xmlrpc_net.py
0.991 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_xxtestfuzz.py
0.583 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_yield_from.py
29.964 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_zipapp.py
15.92 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_zipfile.py
104.497 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_zipfile64.py
5.723 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_zipimport.py
30.342 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_zipimport_support.py
10.463 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
test_zlib.py
34.032 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
testcodec.py
1.021 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
testtar.tar
425 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
tf_inherit_check.py
0.697 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
threaded_import_hangers.py
1.449 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
time_hashlib.py
2.874 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt
0.433 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
tokenize_tests-no-coding-cookie-and-utf8-bom-sig-only.txt
0.295 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
tokenize_tests-utf8-coding-cookie-and-no-utf8-bom-sig.txt
0.411 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
tokenize_tests-utf8-coding-cookie-and-utf8-bom-sig.txt
0.318 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
tokenize_tests.txt
2.653 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
win_console_handler.py
1.383 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
xmltests.py
0.487 KB
17 Apr 2024 5.36 PM
root / linksafe
0644
zip_cp437_header.zip
0.264 KB
5 Jun 2023 8.45 PM
root / linksafe
0644
zipdir.zip
0.365 KB
5 Jun 2023 8.45 PM
root / linksafe
0644

✘✘ GRAYBYTE WORDPRESS FILE MANAGER @ 2026 CONTACT ME ✘✘
Static GIF Static GIF