"""
Unit testing assertions.

This module contains several standard assertions that can be used in unit
tests. Users are encouraged to define their own assertions, possibly using
assertions from this package as a basis.

"""

__version__ = "$Revision: 9183 $"

__all__ = ["fail", "assert_true", "assert_false", "assert_equals",
           "assert_not_equals", "assert_same", "assert_not_same",
           "assert_raises", "assert_raises_errno", "assert_none",
           "assert_not_none", "assert_contains"]


def fail(msg=None):
    """Fail immediately, with the given message."""
    raise AssertionError(msg)


def assert_true(condition, msg=None):
    """Fail the test unless the condition is True."""
    if not condition:
        fail(msg)


def assert_false(condition, msg=None):
    """Fail the test unless the condition is False."""
    if condition:
        fail(msg)


def assert_equals(expected, actual, msg=None):
    """Fail if actual does not equal expected, as determined by the '=='
    operator.
    
    """
    if not expected == actual:
        fail(msg or "%r != %r" % (expected, actual))


def assert_not_equals(expected, actual, msg=None):
    """Fail if the two objects are equal as determined by the '=='
    operator.
    
    """
    if expected == actual:
        fail(msg or '%r == %r' % (expected, actual))


def assert_same(expected, actual, msg=None):
    """Fail if the two objects are not the same object."""
    if expected is not actual:
        fail(msg or '%r is not %r' % (expected, actual))


def assert_not_same(expected, actual, msg=None):
    """Fail if the two objects are the same object."""
    if expected is actual:
        fail(msg or '%r is %r' % (expected, actual))


def assert_raises(exc_cls, func, *args, **kwargs):
    """Fail unless an exception of class exc_cls is thrown by func when
    invoked with arguments args and keyword arguments kwargs. If a
    different type of exception is thrown, it will not be caught, and the
    test case will be deemed to have suffered an error, exactly as for an
    unexpected exception.

    """
    try:
        func(*args, **kwargs)
    except exc_cls:
        pass
    else:
        exc_name = getattr(exc_cls, "__name__", str(exc_cls))
        fail("%s not raised" % exc_name)


def assert_raises_errno(exc_cls, errno, func, *args, **kwargs):
    """Fail unless an exception of class exc_cls is thrown and its errno
    attribute equals the supplied one. func is invoked with arguments args
    and keyword arguments kwargs. If a different type of exception is thrown
    or a different errno is set, it will not be caught, and the test case
    will be deemed to have suffered an error, exactly as for an unexpected
    exception.

    """
    try:
        func(*args, **kwargs)
    except exc_cls, exc:
        assert_equals(errno, exc.errno)
    else:
        exc_name = getattr(exc_cls, "__name__", str(exc_cls))
        fail("%s not raised" % exc_name)


def assert_none(actual, msg=None):
    """Fail if actual is not None."""
    if actual is not None:
        fail(msg or '%r is not None' % (actual, ))


def assert_not_none(actual, msg=None):
    """Fail if actual is None."""
    if actual is None:
        fail(msg or '%r is None' % (actual, ))


def assert_contains(expected, actual, msg=None):
    """Fail if expected string is not contained in actual string."""
    try:
        actual.index(expected)
    except ValueError:
        fail(msg or '%r not contained in %r' % (expected, actual))
