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())
This commit is contained in:
@@ -146,7 +146,7 @@ def trampoline(fd, read=None, write=None, timeout=None, timeout_exc=TimeoutError
|
|||||||
current.throw(timeout_exc())
|
current.throw(timeout_exc())
|
||||||
def cb(d):
|
def cb(d):
|
||||||
current.switch()
|
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)
|
# 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
|
# 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
|
# 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.
|
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
|
self.seconds = seconds
|
||||||
if exc is None:
|
if not throw_args:
|
||||||
self.exc = _SilentException()
|
self.throw_args = (TimeoutError(), )
|
||||||
|
elif throw_args == (None, ):
|
||||||
|
self.throw_args = (_SilentException(), )
|
||||||
else:
|
else:
|
||||||
self.exc = exc
|
self.throw_args = throw_args
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self.timeout = exc_after(self.seconds, self.exc)
|
self.timeout = exc_after(self.seconds, *self.throw_args)
|
||||||
return self.timeout
|
return self.timeout
|
||||||
|
|
||||||
def __exit__(self, typ, value, tb):
|
def __exit__(self, typ, value, tb):
|
||||||
self.timeout.cancel()
|
self.timeout.cancel()
|
||||||
del self.timeout
|
if typ is _SilentException and value in self.throw_args:
|
||||||
if value is self.exc:
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def with_timeout(seconds, func, *args, **kwds):
|
def with_timeout(seconds, func, *args, **kwds):
|
||||||
"""Wrap a call to some (yielding) function with a timeout; if the called
|
"""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
|
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:
|
finally:
|
||||||
timeout.cancel()
|
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.
|
after *seconds* have elapsed.
|
||||||
|
|
||||||
This only works if the current coroutine is yielding, and is generally
|
This only works if the current coroutine is yielding, and is generally
|
||||||
@@ -432,7 +433,7 @@ def exc_after(seconds, exception_object):
|
|||||||
timer.cancel()
|
timer.cancel()
|
||||||
"""
|
"""
|
||||||
hub = get_hub()
|
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():
|
def get_default_hub():
|
||||||
|
@@ -100,11 +100,11 @@ class BaseHub(object):
|
|||||||
self.excs.pop(fileno, None)
|
self.excs.pop(fileno, None)
|
||||||
self.waiters_by_greenlet.pop(greenlet.getcurrent(), 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)
|
fileno = self.waiters_by_greenlet.pop(gr, None)
|
||||||
if fileno is not None:
|
if fileno is not None:
|
||||||
self.remove_descriptor(fileno)
|
self.remove_descriptor(fileno)
|
||||||
gr.throw(exception_object)
|
gr.throw(*throw_args)
|
||||||
|
|
||||||
def exc_descriptor(self, fileno):
|
def exc_descriptor(self, fileno):
|
||||||
exc = self.excs.get(fileno)
|
exc = self.excs.get(fileno)
|
||||||
|
@@ -100,11 +100,11 @@ class BaseTwistedHub(object):
|
|||||||
reactor.removeWriter(descriptor)
|
reactor.removeWriter(descriptor)
|
||||||
self.waiters_by_greenlet.pop(greenlet.getcurrent(), 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)
|
fileno = self.waiters_by_greenlet.pop(gr, None)
|
||||||
if fileno is not None:
|
if fileno is not None:
|
||||||
self.remove_descriptor(fileno)
|
self.remove_descriptor(fileno)
|
||||||
gr.throw(exception_object)
|
gr.throw(*throw_args)
|
||||||
|
|
||||||
# required by GreenSocket
|
# required by GreenSocket
|
||||||
def exc_descriptor(self, _fileno):
|
def exc_descriptor(self, _fileno):
|
||||||
|
Reference in New Issue
Block a user