diff --git a/eventlet/api.py b/eventlet/api.py index 7dc98f4..8baa8f8 100644 --- a/eventlet/api.py +++ b/eventlet/api.py @@ -324,6 +324,65 @@ def call_after_local(seconds, function, *args, **kwds): # for compatibility with original eventlet API call_after = call_after_local +class _SilentException(BaseException): + pass + +class timeout: + """ + >>> from __future__ import with_statement + >>> from eventlet.api import sleep + >>> DELAY = 0.01 + + Nothing happens if with-block finishes before the timeout expires + >>> with timeout(DELAY*2): + ... sleep(DELAY) + >>> sleep(DELAY*2) # check if timer was actually cancelled + + An exception will be raised if it's not + >>> with timeout(DELAY): + ... sleep(DELAY*2) + Traceback (most recent call last): + ... + TimeoutError + + You can customize the exception raised: + >>> with timeout(DELAY, IOError("Operation takes way too long")): + ... sleep(DELAY*2) + Traceback (most recent call last): + ... + IOError: Operation takes way too long + + It's possible to cancel the timer inside the block: + >>> with timeout(DELAY) as timer: + ... timer.cancel() + ... sleep(DELAY*2) + + To silent the exception, pass None as second parameter. The with-block + will be interrupted with _SilentException, but it won't be propogated + outside. + >>> DELAY=0.1 + >>> import time + >>> start = time.time() + >>> with timeout(DELAY, None): + ... sleep(DELAY*2) + >>> (time.time()-start)