diff --git a/Doc/library/sched.rst b/Doc/library/sched.rst --- a/Doc/library/sched.rst +++ b/Doc/library/sched.rst @@ -14,7 +14,7 @@ The :mod:`sched` module defines a class which implements a general purpose event scheduler: -.. class:: scheduler(timefunc, delayfunc) +.. class:: scheduler(timefunc=time.time, delayfunc=time.sleep) The :class:`scheduler` class defines a generic interface to scheduling events. It needs two functions to actually deal with the "outside world" --- *timefunc* @@ -25,6 +25,9 @@ event is run to allow other threads an opportunity to run in multi-threaded applications. + .. versionchanged:: 3.3 + *timefunc* and *delayfunc* parameters are optional. + Example:: >>> import sched, time @@ -79,26 +82,38 @@ :class:`scheduler` instances have the following methods and attributes: -.. method:: scheduler.enterabs(time, priority, action, argument) +.. method:: scheduler.enterabs(time, priority, action, argument=[], kwargs={}) Schedule a new event. The *time* argument should be a numeric type compatible with the return value of the *timefunc* function passed to the constructor. Events scheduled for the same *time* will be executed in the order of their *priority*. - Executing the event means executing ``action(*argument)``. *argument* must be a - sequence holding the parameters for *action*. + Executing the event means executing ``action(*argument, **kwargs)``. + *argument* must be a sequence holding the parameters for *action*. + *kwargs* must be a dictionary holding the keyword parameters for *action*. Return value is an event which may be used for later cancellation of the event (see :meth:`cancel`). + .. versionchanged:: 3.3 + *argument* parameter is optional. -.. method:: scheduler.enter(delay, priority, action, argument) + .. versionadded:: 3.3 + *kwargs* parameter was added. + + +.. method:: scheduler.enter(delay, priority, action, argument=[], kwargs={}) Schedule an event for *delay* more time units. Other than the relative time, the other arguments, the effect and the return value are the same as those for :meth:`enterabs`. + .. versionchanged:: 3.3 + *argument* parameter is optional. + + .. versionadded:: 3.3 + *kwargs* parameter was added. .. method:: scheduler.cancel(event) diff --git a/Lib/sched.py b/Lib/sched.py --- a/Lib/sched.py +++ b/Lib/sched.py @@ -28,12 +28,13 @@ # XXX instead of having to define a module or class just to hold # XXX the global state of your particular time and delay functions. +import time import heapq from collections import namedtuple __all__ = ["scheduler"] -class Event(namedtuple('Event', 'time, priority, action, argument')): +class Event(namedtuple('Event', 'time, priority, action, argument, kwargs')): def __eq__(s, o): return (s.time, s.priority) == (o.time, o.priority) def __ne__(s, o): return (s.time, s.priority) != (o.time, o.priority) def __lt__(s, o): return (s.time, s.priority) < (o.time, o.priority) @@ -42,32 +43,33 @@ def __ge__(s, o): return (s.time, s.priority) >= (o.time, o.priority) class scheduler: - def __init__(self, timefunc, delayfunc): + + def __init__(self, timefunc=time.time, delayfunc=time.sleep): """Initialize a new instance, passing the time and delay functions""" self._queue = [] self.timefunc = timefunc self.delayfunc = delayfunc - def enterabs(self, time, priority, action, argument): + def enterabs(self, time, priority, action, argument=[], kwargs={}): """Enter a new event in the queue at an absolute time. Returns an ID for the event which can be used to remove it, if necessary. """ - event = Event(time, priority, action, argument) + event = Event(time, priority, action, argument, kwargs) heapq.heappush(self._queue, event) return event # The ID - def enter(self, delay, priority, action, argument): + def enter(self, delay, priority, action, argument=[], kwargs={}): """A variant that specifies the time as a relative time. This is actually the more commonly used interface. """ time = self.timefunc() + delay - return self.enterabs(time, priority, action, argument) + return self.enterabs(time, priority, action, argument, kwargs) def cancel(self, event): """Remove an event from the queue. @@ -111,7 +113,7 @@ timefunc = self.timefunc pop = heapq.heappop while q: - time, priority, action, argument = checked_event = q[0] + time, priority, action, argument, kwargs = checked_event = q[0] now = timefunc() if now < time: delayfunc(time - now) @@ -120,7 +122,7 @@ # Verify that the event was not removed or altered # by another thread after we last looked at q[0]. if event is checked_event: - action(*argument) + action(*argument, **kwargs) delayfunc(0) # Let other threads run else: heapq.heappush(q, event) diff --git a/Lib/test/test_sched.py b/Lib/test/test_sched.py --- a/Lib/test/test_sched.py +++ b/Lib/test/test_sched.py @@ -72,6 +72,18 @@ scheduler.run() self.assertEqual(scheduler._queue, []) + def test_args_kwargs(self): + flag = [] + + def fun(*a, **b): + flag.append(None) + self.assertEqual(a, (1,2,3)) + self.assertEqual(b, {"foo":1}) + + scheduler = sched.scheduler(time.time, time.sleep) + z = scheduler.enterabs(0.01, 1, fun, argument=(1,2,3), kwargs={"foo":1}) + scheduler.run() + self.assertEqual(flag, [None]) def test_main(): support.run_unittest(TestCase)