"""
Simple decorator that prevents a function from finishing faster than a given number of seconds.
Useful if you're fairly confident that your function should finish in a certain amount of time,
but you want to make the return time constant (eg. to prevent constant-time attacks).

For example, if I know that my password reset function always takes about 1 second to execute
if the given email address is valid but if the email address is invalid, it usually finishes much faster, 
I can ensure that it always takes 2 seconds to execute whenever it's called.

The usefulness here goes out the window if your function's normal execution time is subject
to a lot of jitter.
"""

def minimum_time(seconds):
    def decorator(fn):
        @wraps(fn)
        def decorated_function(*args, **kwargs):
            start = time.time()
            rv = fn(*args, **kwargs)
            end = time.time()

            runtime = end - start
            if runtime < seconds:
                time.sleep(seconds - runtime)

            return rv
        return decorated_function
    return decorator


# Usage:
@minimum_time(2)
def request_password_reset(email_address):
    user = get_user_by_email(email_address)
    if email_address:
        # Assume this reliably takes around 1 second to finish
        send_reset_token_to_user(user)
    return 'Finished!  User has been notified if they are indeed a real user.'


# This usually takes around 1 second to finish
request_password_reset('real.user@example.com')
# This usually finishes much faster because `send_reset_token_to_user` never gets called
request_password_reset('fake.user@example.com')
# But now they'll always take 2 seconds! (or more, in which case this is less useful...)