Added spawn_after_local and tests, removed test__timers (the source of the new tests), deprecated call_after_*

This commit is contained in:
Ryan Williams
2010-02-13 19:38:01 -08:00
parent 64ad004e5d
commit 7fb4f59ac8
5 changed files with 65 additions and 42 deletions

View File

@@ -10,6 +10,7 @@ try:
spawn = greenthread.spawn
spawn_n = greenthread.spawn_n
spawn_after = greenthread.spawn_after
call_after_global = greenthread.call_after_global
TimeoutError = greenthread.TimeoutError
exc_after = greenthread.exc_after

View File

@@ -4,6 +4,7 @@ from eventlet import event
from eventlet import hubs
from eventlet.hubs import timer
from eventlet.support import greenlets as greenlet
import warnings
__all__ = ['getcurrent', 'sleep', 'spawn', 'spawn_n', 'call_after_global', 'call_after_local', 'GreenThread']
@@ -81,7 +82,30 @@ def spawn_after(seconds, func, *args, **kwargs):
g = GreenThread(hub.greenlet)
hub.schedule_call_global(seconds, g.switch, func, args, kwargs)
return g
def spawn_after_local(seconds, func, *args, **kwargs):
"""Spawns *func* after *seconds* have elapsed. The function will NOT be
called if the current greenthread has exited.
*seconds* may be specified as an integer, or a float if fractional seconds
are desired. The *func* will be called with the given *args* and
keyword arguments *kwargs*, and will be executed within its own greenthread.
The return value of :func:`spawn_after` is a :class:`GreenThread` object,
which can be used to retrieve the results of the call.
To cancel the spawn and prevent *func* from being called,
call :meth:`GreenThread.cancel` on the return value. This will not abort the
function if it's already started running. If terminating *func* regardless
of whether it's started or not is the desired behavior, call
:meth:`GreenThread.kill`.
"""
hub = hubs.get_hub()
g = GreenThread(hub.greenlet)
hub.schedule_call_local(seconds, g.switch, func, args, kwargs)
return g
def call_after_global(seconds, func, *args, **kwargs):
"""Schedule *function* to be called after *seconds* have elapsed.
@@ -92,6 +116,10 @@ def call_after_global(seconds, func, *args, **kwargs):
keyword arguments *kwargs*, and will be executed within its own greenthread.
Its return value is discarded."""
warnings.warn("call_after_global is renamed to spawn_after, which"
"has the same signature and semantics (plus a bit extra). Please do a"
" quick search-and-replace on your codebase, thanks!",
DeprecationWarning, stacklevel=2)
return _spawn_n(seconds, func, args, kwargs)[0]
@@ -105,6 +133,9 @@ def call_after_local(seconds, function, *args, **kwargs):
Its return value is discarded.
"""
warnings.warn("call_after_local is renamed to spawn_after_local, which"
"has the same signature and semantics (plus a bit extra).",
DeprecationWarning, stacklevel=2)
hub = hubs.get_hub()
g = greenlet.greenlet(_main_wrapper, parent=hub.greenlet)
t = hub.schedule_call_local(seconds, g.switch, function, args, kwargs)

View File

@@ -107,3 +107,35 @@ class SpawnAfter(LimitedTestCase, Asserts):
greenthread.sleep(0)
gt.kill()
self.assert_dead(gt)
class SpawnAfterLocal(LimitedTestCase, Asserts):
def setUp(self):
super(SpawnAfterLocal, self).setUp()
self.lst = [1]
def test_timer_fired(self):
def func():
greenthread.spawn_after_local(0.1, self.lst.pop)
greenthread.sleep(0.2)
greenthread.spawn(func)
assert self.lst == [1], self.lst
greenthread.sleep(0.3)
assert self.lst == [], self.lst
def test_timer_cancelled_upon_greenlet_exit(self):
def func():
greenthread.spawn_after_local(0.1, self.lst.pop)
greenthread.spawn(func)
assert self.lst == [1], self.lst
greenthread.sleep(0.2)
assert self.lst == [1], self.lst
def test_spawn_is_not_cancelled(self):
def func():
greenthread.spawn(self.lst.pop)
# exiting immediatelly, but self.lst.pop must be called
greenthread.spawn(func)
greenthread.sleep(0.1)
assert self.lst == [], self.lst

View File

@@ -1,42 +0,0 @@
import unittest
from eventlet.api import call_after, spawn, sleep
class test(unittest.TestCase):
def setUp(self):
self.lst = [1]
def test_timer_fired(self):
def func():
call_after(0.1, self.lst.pop)
sleep(0.2)
spawn(func)
assert self.lst == [1], self.lst
sleep(0.3)
assert self.lst == [], self.lst
def test_timer_cancelled_upon_greenlet_exit(self):
def func():
call_after(0.1, self.lst.pop)
spawn(func)
assert self.lst == [1], self.lst
sleep(0.2)
assert self.lst == [1], self.lst
def test_spawn_is_not_cancelled(self):
def func():
spawn(self.lst.pop)
# exiting immediatelly, but self.lst.pop must be called
spawn(func)
sleep(0.1)
assert self.lst == [], self.lst
if __name__=='__main__':
unittest.main()

View File

@@ -31,6 +31,7 @@ class TestTimer(TestCase):
hub.switch()
assert called
assert not hub.running
if __name__ == '__main__':
main()