From 90ac9e854b88df50379233c4b31cb986738d28e4 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 10 Dec 2008 15:56:28 +0600 Subject: [PATCH] made api.exc_after, api.timeout and Hub.exc_greenlet support greenlet.throw() parameters; old exception_object scheme still works, but it's now possible to do stuff like exc_after(1, *sys.exc_info()) --- eventlet/api.py | 25 +++++++++++++------------ eventlet/hubs/hub.py | 4 ++-- eventlet/hubs/twistedr.py | 4 ++-- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/eventlet/api.py b/eventlet/api.py index e99cacf..a45ecf5 100644 --- a/eventlet/api.py +++ b/eventlet/api.py @@ -146,7 +146,7 @@ def trampoline(fd, read=None, write=None, timeout=None, timeout_exc=TimeoutError current.throw(timeout_exc()) def cb(d): current.switch() - # with TwistedHub, descriptor actually an object (socket_rwdescriptor) which stores + # with TwistedHub, descriptor is actually an object (socket_rwdescriptor) which stores # this callback. If this callback stores a reference to the socket instance (fd) # then descriptor has a reference to that instance. This makes socket not collected # after greenlet exit. Since nobody actually uses the results of this switch, I removed @@ -339,24 +339,24 @@ class timeout: If exc is None, code block will be interrupted silently. """ - def __init__(self, seconds, exc=TimeoutError): + def __init__(self, seconds, *throw_args): self.seconds = seconds - if exc is None: - self.exc = _SilentException() + if not throw_args: + self.throw_args = (TimeoutError(), ) + elif throw_args == (None, ): + self.throw_args = (_SilentException(), ) else: - self.exc = exc + self.throw_args = throw_args def __enter__(self): - self.timeout = exc_after(self.seconds, self.exc) + self.timeout = exc_after(self.seconds, *self.throw_args) return self.timeout def __exit__(self, typ, value, tb): self.timeout.cancel() - del self.timeout - if value is self.exc: + if typ is _SilentException and value in self.throw_args: return True - def with_timeout(seconds, func, *args, **kwds): """Wrap a call to some (yielding) function with a timeout; if the called function fails to return before the timeout, cancel it and return a flag @@ -407,8 +407,9 @@ def with_timeout(seconds, func, *args, **kwds): finally: timeout.cancel() -def exc_after(seconds, exception_object): - """Schedule *exception_object* to be raised into the current coroutine + +def exc_after(seconds, *throw_args): + """Schedule an exception to be raised into the current coroutine after *seconds* have elapsed. This only works if the current coroutine is yielding, and is generally @@ -432,7 +433,7 @@ def exc_after(seconds, exception_object): timer.cancel() """ hub = get_hub() - return call_after(seconds, hub.exc_greenlet, getcurrent(), exception_object) + return call_after(seconds, hub.exc_greenlet, getcurrent(), *throw_args) def get_default_hub(): diff --git a/eventlet/hubs/hub.py b/eventlet/hubs/hub.py index 9109ecb..d287554 100644 --- a/eventlet/hubs/hub.py +++ b/eventlet/hubs/hub.py @@ -100,11 +100,11 @@ class BaseHub(object): self.excs.pop(fileno, None) self.waiters_by_greenlet.pop(greenlet.getcurrent(), None) - def exc_greenlet(self, gr, exception_object): + def exc_greenlet(self, gr, *throw_args): fileno = self.waiters_by_greenlet.pop(gr, None) if fileno is not None: self.remove_descriptor(fileno) - gr.throw(exception_object) + gr.throw(*throw_args) def exc_descriptor(self, fileno): exc = self.excs.get(fileno) diff --git a/eventlet/hubs/twistedr.py b/eventlet/hubs/twistedr.py index 22ad203..62dfe05 100644 --- a/eventlet/hubs/twistedr.py +++ b/eventlet/hubs/twistedr.py @@ -100,11 +100,11 @@ class BaseTwistedHub(object): reactor.removeWriter(descriptor) self.waiters_by_greenlet.pop(greenlet.getcurrent(), None) - def exc_greenlet(self, gr, exception_object): + def exc_greenlet(self, gr, *throw_args): fileno = self.waiters_by_greenlet.pop(gr, None) if fileno is not None: self.remove_descriptor(fileno) - gr.throw(exception_object) + gr.throw(*throw_args) # required by GreenSocket def exc_descriptor(self, _fileno):