##############################################################################
#
# Copyright (c) 2003 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""logging handler for tests that check logging output.

.. caution:: This is deprecated and may not work on Python 3.

"""
import logging
import warnings


warnings.warn(
    'zope.testing.loghandler.Handler is deprecated. It probably'
    ' does not work on Python 3.', DeprecationWarning, stacklevel=2)


class Handler(logging.Handler):
    """Handler for use with `unittest.TestCase` objects.

    The handler takes a ``TestCase`` instance as a constructor argument.
    It can be registered with one or more loggers and collects log
    records they generate.

    The `assertLogsMessage` and `failIfLogsMessage` methods can be
    used to check the logger output and causes the test to fail as
    appropriate.
    """

    def __init__(self, testcase, propagate=False):
        logging.Handler.__init__(self)
        self.records = []
        # loggers stores (logger, propagate) tuples
        self.loggers = []
        self.closed = False
        self.propagate = propagate
        self.testcase = testcase

    def close(self):
        """Remove handler from any loggers it was added to."""
        if self.closed:
            return
        for logger, propagate in self.loggers:
            logger.removeHandler(self)
            logger.propagate = propagate
        self.closed = True

    def add(self, name):
        """Add handler to logger named name."""
        logger = logging.getLogger(name)
        old_prop = logger.propagate
        logger.addHandler(self)
        if self.propagate:
            logger.propagate = 1
        else:
            logger.propagate = 0
        self.loggers.append((logger, old_prop))

    def emit(self, record):
        self.records.append(record)

    def assertLogsMessage(self, msg, level=None):
        """
        Check that a record whose message equals *msg*
        (and optionally at *level*) has been emitted, failing
        if not.
        """
        for r in self.records:
            if r.getMessage() == msg:
                if level is not None and r.levelno == level:
                    return
        msg = "No log message contained %r" % msg
        if level is not None:
            msg += " at level %d" % level
        self.testcase.fail(msg)

    def failIfLogsMessage(self, msg):
        """
        Check that a record whose message equals *msg*
        has **not** been emitted, failing if it has.
        """
        for r in self.records:
            if r.getMessage() == msg:
                self.testcase.fail("Found log message %r" % msg)
