Fix 13245:

sched.scheduler class constructor's timefunc and delayfunct parameters are now optional.
scheduler.enter and scheduler.enterabs methods gained a new kwargs parameter.

Patch contributed by Matt Mulsow.
This commit is contained in:
Giampaolo Rodola' 2011-11-22 13:33:34 +01:00
parent ca4f20782e
commit be55d99b3d
6 changed files with 64 additions and 14 deletions

View File

@ -14,7 +14,7 @@
The :mod:`sched` module defines a class which implements a general purpose event The :mod:`sched` module defines a class which implements a general purpose event
scheduler: scheduler:
.. class:: scheduler(timefunc, delayfunc) .. class:: scheduler(timefunc=time.time, delayfunc=time.sleep)
The :class:`scheduler` class defines a generic interface to scheduling events. The :class:`scheduler` class defines a generic interface to scheduling events.
It needs two functions to actually deal with the "outside world" --- *timefunc* It needs two functions to actually deal with the "outside world" --- *timefunc*
@ -25,6 +25,9 @@ scheduler:
event is run to allow other threads an opportunity to run in multi-threaded event is run to allow other threads an opportunity to run in multi-threaded
applications. applications.
.. versionchanged:: 3.3
*timefunc* and *delayfunc* parameters are optional.
Example:: Example::
>>> import sched, time >>> import sched, time
@ -79,26 +82,38 @@ Scheduler Objects
:class:`scheduler` instances have the following methods and attributes: :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 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. 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 Events scheduled for the same *time* will be executed in the order of their
*priority*. *priority*.
Executing the event means executing ``action(*argument)``. *argument* must be a Executing the event means executing ``action(*argument, **kwargs)``.
sequence holding the parameters for *action*. *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 Return value is an event which may be used for later cancellation of the event
(see :meth:`cancel`). (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 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 other arguments, the effect and the return value are the same as those for
:meth:`enterabs`. :meth:`enterabs`.
.. versionchanged:: 3.3
*argument* parameter is optional.
.. versionadded:: 3.3
*kwargs* parameter was added.
.. method:: scheduler.cancel(event) .. method:: scheduler.cancel(event)

View File

@ -572,6 +572,22 @@ should be used. For example, this will send a ``'HEAD'`` request::
(:issue:`1673007`) (:issue:`1673007`)
sched
-----
* *timefunc* and *delayfunct* parameters of :class:`~sched.scheduler` class
constructor are now optional and defaults to :func:`time.time` and
:func:`time.sleep` respectively. (Contributed by Matt Mulsow in
:issue:`8809`)
* :meth:`~sched.scheduler.enter` and :meth:`~sched.scheduler.enterabs`
*argument* parameter is now optional. (Contributed by Matt Mulsow in
:issue:`8809`)
* :meth:`~sched.scheduler.enter` and :meth:`~sched.scheduler.enterabs`
now accept a *kwargs* parameter. (Contributed by Matt Mulsow in
:issue:`8809`)
Optimizations Optimizations
============= =============
@ -744,4 +760,3 @@ Other issues
.. Issue #10998: the -Q command-line flag and related artifacts have been .. Issue #10998: the -Q command-line flag and related artifacts have been
removed. Code checking sys.flags.division_warning will need updating. removed. Code checking sys.flags.division_warning will need updating.
Contributed by Éric Araujo. Contributed by Éric Araujo.

View File

@ -28,12 +28,13 @@ has another way to reference private data (besides global variables).
# XXX instead of having to define a module or class just to hold # XXX instead of having to define a module or class just to hold
# XXX the global state of your particular time and delay functions. # XXX the global state of your particular time and delay functions.
import time
import heapq import heapq
from collections import namedtuple from collections import namedtuple
__all__ = ["scheduler"] __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 __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 __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) def __lt__(s, o): return (s.time, s.priority) < (o.time, o.priority)
@ -42,32 +43,33 @@ class Event(namedtuple('Event', 'time, priority, action, argument')):
def __ge__(s, o): return (s.time, s.priority) >= (o.time, o.priority) def __ge__(s, o): return (s.time, s.priority) >= (o.time, o.priority)
class scheduler: 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 """Initialize a new instance, passing the time and delay
functions""" functions"""
self._queue = [] self._queue = []
self.timefunc = timefunc self.timefunc = timefunc
self.delayfunc = delayfunc 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. """Enter a new event in the queue at an absolute time.
Returns an ID for the event which can be used to remove it, Returns an ID for the event which can be used to remove it,
if necessary. if necessary.
""" """
event = Event(time, priority, action, argument) event = Event(time, priority, action, argument, kwargs)
heapq.heappush(self._queue, event) heapq.heappush(self._queue, event)
return event # The ID 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. """A variant that specifies the time as a relative time.
This is actually the more commonly used interface. This is actually the more commonly used interface.
""" """
time = self.timefunc() + delay time = self.timefunc() + delay
return self.enterabs(time, priority, action, argument) return self.enterabs(time, priority, action, argument, kwargs)
def cancel(self, event): def cancel(self, event):
"""Remove an event from the queue. """Remove an event from the queue.
@ -111,7 +113,7 @@ class scheduler:
timefunc = self.timefunc timefunc = self.timefunc
pop = heapq.heappop pop = heapq.heappop
while q: while q:
time, priority, action, argument = checked_event = q[0] time, priority, action, argument, kwargs = checked_event = q[0]
now = timefunc() now = timefunc()
if now < time: if now < time:
delayfunc(time - now) delayfunc(time - now)
@ -120,7 +122,7 @@ class scheduler:
# Verify that the event was not removed or altered # Verify that the event was not removed or altered
# by another thread after we last looked at q[0]. # by another thread after we last looked at q[0].
if event is checked_event: if event is checked_event:
action(*argument) action(*argument, **kwargs)
delayfunc(0) # Let other threads run delayfunc(0) # Let other threads run
else: else:
heapq.heappush(q, event) heapq.heappush(q, event)

View File

@ -72,6 +72,18 @@ class TestCase(unittest.TestCase):
scheduler.run() scheduler.run()
self.assertEqual(scheduler._queue, []) 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(): def test_main():
support.run_unittest(TestCase) support.run_unittest(TestCase)

View File

@ -11,6 +11,7 @@ Without you, I would've stopped working on Python long ago!
PS: In the standard Python distribution, this file is encoded in UTF-8 PS: In the standard Python distribution, this file is encoded in UTF-8
and the list is in rough alphabetical order by last names. and the list is in rough alphabetical order by last names.
Matt Mulsow
Rajiv Abraham Rajiv Abraham
David Abrahams David Abrahams
Ron Adam Ron Adam

View File

@ -387,6 +387,11 @@ Core and Builtins
Library Library
------- -------
- Issue #13245: sched.scheduler class constructor's timefunc and
delayfunct parameters are now optional.
scheduler.enter and scheduler.enterabs methods gained a new kwargs parameter.
Patch contributed by Matt Mulsow.
- Issue #12328: Under Windows, refactor handling of Ctrl-C events and - Issue #12328: Under Windows, refactor handling of Ctrl-C events and
make _multiprocessing.win32.WaitForMultipleObjects interruptible when make _multiprocessing.win32.WaitForMultipleObjects interruptible when
the wait_flag parameter is false. Patch by sbt. the wait_flag parameter is false. Patch by sbt.