def failUnlessWarns(self, category, message, filename, f,
                   *args, **kwargs):
    """
    Fail if the given function doesn't generate the specified warning when
    called. It calls the function, checks the warning, and forwards the
    result of the function if everything is fine.

    @param category: the category of the warning to check.
    @param message: the output message of the warning to check.
    @param filename: the filename where the warning should come from.
    @param f: the function which is supposed to generate the warning.
    @type f: any callable.
    @param args: the arguments to C{f}.
    @param kwargs: the keywords arguments to C{f}.

    @return: the result of the original function C{f}.
    """
    warningsShown = []
    def warnExplicit(*args):
        warningsShown.append(args)

    origExplicit = warnings.warn_explicit
    try:
        warnings.warn_explicit = warnExplicit
        result = f(*args, **kwargs)
    finally:
        warnings.warn_explicit = origExplicit

    if not warningsShown:
        self.fail("No warnings emitted")
    first = warningsShown[0]
    for other in warningsShown[1:]:
        if other[:2] != first[:2]:
            self.fail("Can't handle different warnings")
    gotMessage, gotCategory, gotFilename, lineno = first[:4]
    self.assertEqual(gotMessage, message)
    self.assertIdentical(gotCategory, category)

    # Use starts with because of .pyc/.pyo issues.
    self.failUnless(
        filename.startswith(gotFilename),
        'Warning in %r, expected %r' % (gotFilename, filename))

    # It would be nice to be able to check the line number as well, but
    # different configurations actually end up reporting different line
    # numbers (generally the variation is only 1 line, but that's enough
    # to fail the test erroneously...).
    # self.assertEqual(lineno, xxx)

    return result
Fail if the given function doesn't generate the specified warning when
    called. It calls the function, checks the warning, and forwards the
    result of the function if everything is fine.

    @param category: the category of the warning to check.
    @param message: the output message of the warning to check.
    @param filename: the filename where the warning should come from.
    @param f: the function which is supposed to generate the warning.
    @type f: any callable.
    @param args: the arguments to C{f}.
    @param kwargs: the keywords arguments to C{f}.

    @return: the result of the original function C{f}.