Added spawn_after_local and tests, removed test__timers (the source of the new tests), deprecated call_after_*
This commit is contained in:
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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()
|
||||
|
@@ -31,6 +31,7 @@ class TestTimer(TestCase):
|
||||
hub.switch()
|
||||
assert called
|
||||
assert not hub.running
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
Reference in New Issue
Block a user