""" 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...)