Moved a bunch of stuff from api to greenthread and imported into __init__. Broke circular import in timer.py.

This commit is contained in:
Ryan Williams
2010-01-04 21:46:53 -08:00
parent 19fa2c909f
commit a8f22fc895
4 changed files with 94 additions and 81 deletions

View File

@@ -11,6 +11,11 @@ sleep = greenthread.sleep
spawn = greenthread.spawn
spawn_n = greenthread.spawn_n
Event = greenthread.Event
call_after_global = greenthread.call_after_global
call_after_local = greenthread.call_after_local
TimeoutError = greenthread.TimeoutError
exc_after = greenthread.exc_after
with_timeout = greenthread.with_timeout
GreenPool = greenpool.GreenPool
GreenPile = greenpool.GreenPile
GreenPile = greenpool.GreenPile

View File

@@ -8,6 +8,7 @@ import warnings
from eventlet.support import greenlets as greenlet
from eventlet.hubs import get_hub as get_hub_, get_default_hub as get_default_hub_, use_hub as use_hub_
from eventlet import greenthread
__all__ = [
'call_after', 'exc_after', 'getcurrent', 'get_default_hub', 'get_hub',
@@ -37,10 +38,6 @@ def switch(coro, result=None, exc=None):
Greenlet = greenlet.greenlet
class TimeoutError(Exception):
"""Exception raised if an asynchronous operation times out"""
pass
def tcp_listener(address, backlog=50):
"""
@@ -80,6 +77,7 @@ def connect_tcp(address, localaddr=None):
desc.connect(address)
return desc
TimeoutError = greenthread.TimeoutError
def trampoline(fd, read=None, write=None, timeout=None, timeout_exc=TimeoutError):
"""Suspend the current coroutine until the given socket object or file
@@ -118,7 +116,6 @@ def trampoline(fd, read=None, write=None, timeout=None, timeout_exc=TimeoutError
t.cancel()
from eventlet import greenthread
spawn = greenthread.spawn
spawn_n = greenthread.spawn_n
@@ -186,80 +183,9 @@ class timeout(object):
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
value.
with_timeout = greenthread.with_timeout
:param seconds: seconds before timeout occurs
:type seconds: int or float
:param func: the callable to execute with a timeout; must be one of the
functions that implicitly or explicitly yields
:param \*args: positional arguments to pass to *func*
:param \*\*kwds: keyword arguments to pass to *func*
:param timeout_value: value to return if timeout occurs (default raise
:class:`~eventlet.api.TimeoutError`)
:rtype: Value returned by *func* if *func* returns before *seconds*, else
*timeout_value* if provided, else raise ``TimeoutError``
:exception TimeoutError: if *func* times out and no ``timeout_value`` has
been provided.
:exception *any*: Any exception raised by *func*
**Example**::
data = with_timeout(30, httpc.get, 'http://www.google.com/', timeout_value="")
Here *data* is either the result of the ``get()`` call, or the empty string if
it took too long to return. Any exception raised by the ``get()`` call is
passed through to the caller.
"""
# Recognize a specific keyword argument, while also allowing pass-through
# of any other keyword arguments accepted by func. Use pop() so we don't
# pass timeout_value through to func().
has_timeout_value = "timeout_value" in kwds
timeout_value = kwds.pop("timeout_value", None)
error = TimeoutError()
timeout = exc_after(seconds, error)
try:
try:
return func(*args, **kwds)
except TimeoutError, ex:
if ex is error and has_timeout_value:
return timeout_value
raise
finally:
timeout.cancel()
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
used to set timeouts after which a network operation or series of
operations will be canceled.
Returns a :class:`~eventlet.timer.Timer` object with a
:meth:`~eventlet.timer.Timer.cancel` method which should be used to
prevent the exception if the operation completes successfully.
See also :func:`~eventlet.api.with_timeout` that encapsulates the idiom below.
Example::
def read_with_timeout():
timer = api.exc_after(30, RuntimeError())
try:
httpc.get('http://www.google.com/')
except RuntimeError:
print "Timed out!"
else:
timer.cancel()
"""
return call_after(seconds, getcurrent().throw, *throw_args)
exc_after = greenthread.exc_after
sleep = greenthread.sleep

View File

@@ -1,6 +1,7 @@
import sys
from eventlet import hubs
from eventlet import timer
from eventlet.support import greenlets as greenlet
__all__ = ['getcurrent', 'sleep', 'spawn', 'spawn_n', 'call_after_global', 'call_after_local', 'GreenThread', 'Event']
@@ -80,6 +81,87 @@ def call_after_local(seconds, function, *args, **kwargs):
call_after = call_after_local
class TimeoutError(Exception):
"""Exception raised if an asynchronous operation times out"""
pass
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
used to set timeouts after which a network operation or series of
operations will be canceled.
Returns a :class:`~eventlet.timer.Timer` object with a
:meth:`~eventlet.timer.Timer.cancel` method which should be used to
prevent the exception if the operation completes successfully.
See also :func:`~eventlet.api.with_timeout` that encapsulates the idiom below.
Example::
def read_with_timeout():
timer = api.exc_after(30, RuntimeError())
try:
httpc.get('http://www.google.com/')
except RuntimeError:
print "Timed out!"
else:
timer.cancel()
"""
if seconds is None: # dummy argument, do nothing
return timer.Timer(seconds, lambda: None)
hub = hubs.get_hub()
return hub.schedule_call_local(seconds, getcurrent().throw, *throw_args)
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
value.
:param seconds: seconds before timeout occurs
:type seconds: int or float
:param func: the callable to execute with a timeout; must be one of the
functions that implicitly or explicitly yields
:param \*args: positional arguments to pass to *func*
:param \*\*kwds: keyword arguments to pass to *func*
:param timeout_value: value to return if timeout occurs (default raise
:class:`~eventlet.api.TimeoutError`)
:rtype: Value returned by *func* if *func* returns before *seconds*, else
*timeout_value* if provided, else raise ``TimeoutError``
:exception TimeoutError: if *func* times out and no ``timeout_value`` has
been provided.
:exception *any*: Any exception raised by *func*
**Example**::
data = with_timeout(30, httpc.get, 'http://www.google.com/', timeout_value="")
Here *data* is either the result of the ``get()`` call, or the empty string if
it took too long to return. Any exception raised by the ``get()`` call is
passed through to the caller.
"""
# Recognize a specific keyword argument, while also allowing pass-through
# of any other keyword arguments accepted by func. Use pop() so we don't
# pass timeout_value through to func().
has_timeout_value = "timeout_value" in kwds
timeout_value = kwds.pop("timeout_value", None)
error = TimeoutError()
timeout = exc_after(seconds, error)
try:
try:
return func(*args, **kwds)
except TimeoutError, ex:
if ex is error and has_timeout_value:
return timeout_value
raise
finally:
timeout.cancel()
def _spawn_n(seconds, func, args, kwargs):
hub = hubs.get_hub()

View File

@@ -1,4 +1,4 @@
from eventlet.api import getcurrent
from eventlet.support import greenlets as greenlet
from eventlet.hubs import get_hub
""" If true, captures a stack trace for each timer when constructed. This is
@@ -74,7 +74,7 @@ class Timer(object):
class LocalTimer(Timer):
def __init__(self, *args, **kwargs):
self.greenlet = getcurrent()
self.greenlet = greenlet.getcurrent()
Timer.__init__(self, *args, **kwargs)
@property