@param where:     what to log file and line number for;
                      -1 for one frame above log.py; -2 and down for higher up;
                      a function for a (future) code object
    @type  where:     int or callable
    @param filePath:  file to show the message as coming from, if caller
                      knows best
    @type  filePath:  str
    @param line:      line to show the message as coming from, if caller
                      knows best
    @type  line:      int

    @return: dict of calculated variables, if they needed calculating.
             currently contains file and line; this prevents us from
             doing this work in the caller when it isn't needed because
             of the debug level

def doLog(level, object, category, format, args, where=-1,
    filePath=None, line=None):
    """
    @param where:     what to log file and line number for;
                      -1 for one frame above log.py; -2 and down for higher up;
                      a function for a (future) code object
    @type  where:     int or callable
    @param filePath:  file to show the message as coming from, if caller
                      knows best
    @type  filePath:  str
    @param line:      line to show the message as coming from, if caller
                      knows best
    @type  line:      int

    @return: dict of calculated variables, if they needed calculating.
             currently contains file and line; this prevents us from
             doing this work in the caller when it isn't needed because
             of the debug level
    """
    ret = {}

    if category is None:
        category = 'feat'

    if args:
        message = format % args
    else:
        message = format

    # first all the unlimited ones
    if _log_handlers:
        if filePath is None and line is None:
            (filePath, line) = getFileLine(where=where)
        ret['filePath'] = filePath
        ret['line'] = line
        for handler in _log_handlers:
            try:
                handler(level, object, category, file, line, message)
            except TypeError, e:
                raise SystemError("handler %r raised a TypeError: %s" % (
                    handler, getExceptionMessage(e)))

    if level > getCategoryLevel(category):
        return ret

    if _log_handlers_limited:
        if filePath is None and line is None:
            (filePath, line) = getFileLine(where=where)
        ret['filePath'] = filePath
        ret['line'] = line
        for handler in _log_handlers_limited:
            # set this a second time, just in case there weren't unlimited
            # loggers there before
            try:
                handler(level, object, category, filePath, line, message)
            except TypeError, e:
                raise SystemError("handler %r raised a TypeError: %s" % (
                    handler, getExceptionMessage(e)))

        return ret