def limit_error_rate(fails, timeout, exception=ErrorRateExceeded):
    """If function fails to complete fails times in a row,
       calls to it will be intercepted for timeout with exception raised instead."""
    if isinstance(timeout, int):
        timeout = timedelta(seconds=timeout)

    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if wrapper.blocked:
                if datetime.now() - wrapper.blocked < timeout:
                    raise exception
                else:
                    wrapper.blocked = None

            try:
                result = func(*args, **kwargs)
            except:  # noqa
                wrapper.fails += 1
                if wrapper.fails >= fails:
                    wrapper.blocked = datetime.now()
                raise
            else:
                wrapper.fails = 0
                return result

        wrapper.fails = 0
        wrapper.blocked = None
        return wrapper
    return decorator
If function fails to complete fails times in a row,
       calls to it will be intercepted for timeout with exception raised instead.
funcy/flow.py