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 = greenthread.spawn
|
||||||
spawn_n = greenthread.spawn_n
|
spawn_n = greenthread.spawn_n
|
||||||
|
spawn_after = greenthread.spawn_after
|
||||||
call_after_global = greenthread.call_after_global
|
call_after_global = greenthread.call_after_global
|
||||||
TimeoutError = greenthread.TimeoutError
|
TimeoutError = greenthread.TimeoutError
|
||||||
exc_after = greenthread.exc_after
|
exc_after = greenthread.exc_after
|
||||||
|
@@ -4,6 +4,7 @@ from eventlet import event
|
|||||||
from eventlet import hubs
|
from eventlet import hubs
|
||||||
from eventlet.hubs import timer
|
from eventlet.hubs import timer
|
||||||
from eventlet.support import greenlets as greenlet
|
from eventlet.support import greenlets as greenlet
|
||||||
|
import warnings
|
||||||
|
|
||||||
__all__ = ['getcurrent', 'sleep', 'spawn', 'spawn_n', 'call_after_global', 'call_after_local', 'GreenThread']
|
__all__ = ['getcurrent', 'sleep', 'spawn', 'spawn_n', 'call_after_global', 'call_after_local', 'GreenThread']
|
||||||
|
|
||||||
@@ -83,6 +84,29 @@ def spawn_after(seconds, func, *args, **kwargs):
|
|||||||
return g
|
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):
|
def call_after_global(seconds, func, *args, **kwargs):
|
||||||
"""Schedule *function* to be called after *seconds* have elapsed.
|
"""Schedule *function* to be called after *seconds* have elapsed.
|
||||||
The function will be scheduled even if the current greenlet has exited.
|
The function will be scheduled even if the current greenlet has exited.
|
||||||
@@ -92,6 +116,10 @@ def call_after_global(seconds, func, *args, **kwargs):
|
|||||||
keyword arguments *kwargs*, and will be executed within its own greenthread.
|
keyword arguments *kwargs*, and will be executed within its own greenthread.
|
||||||
|
|
||||||
Its return value is discarded."""
|
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]
|
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.
|
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()
|
hub = hubs.get_hub()
|
||||||
g = greenlet.greenlet(_main_wrapper, parent=hub.greenlet)
|
g = greenlet.greenlet(_main_wrapper, parent=hub.greenlet)
|
||||||
t = hub.schedule_call_local(seconds, g.switch, function, args, kwargs)
|
t = hub.schedule_call_local(seconds, g.switch, function, args, kwargs)
|
||||||
|
@@ -107,3 +107,35 @@ class SpawnAfter(LimitedTestCase, Asserts):
|
|||||||
greenthread.sleep(0)
|
greenthread.sleep(0)
|
||||||
gt.kill()
|
gt.kill()
|
||||||
self.assert_dead(gt)
|
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()
|
|
||||||
|
|
@@ -32,5 +32,6 @@ class TestTimer(TestCase):
|
|||||||
assert called
|
assert called
|
||||||
assert not hub.running
|
assert not hub.running
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
Reference in New Issue
Block a user