issue #170: replace Timer.cancelled with Timer.active

It's more flexable: False can represent 'cancelled' or 'expired',
whereas setting cancelled=True for an expired timer didn't feel right.
This commit is contained in:
David Wilson 2019-08-06 04:34:25 +01:00
parent 9839e6781c
commit 9c0cb44ee9
2 changed files with 19 additions and 4 deletions

View File

@ -575,7 +575,9 @@ class Timer(object):
"""
Represents a future event.
"""
cancelled = False
#: Set to :data:`False` if :meth:`cancel` has been called, or immediately
#: prior to being executed by :meth:`TimerList.expire`.
active = True
def __init__(self, when, func):
self.when = when
@ -598,7 +600,7 @@ class Timer(object):
Cancel this event. If it has not yet executed, it will not execute
during any subsequent :meth:`TimerList.expire` call.
"""
self.cancelled = True
self.active = False
class TimerList(object):
@ -634,7 +636,7 @@ class TimerList(object):
Floating point delay, or 0.0, or :data:`None` if no events are
scheduled.
"""
while self._lst and self._lst[0].cancelled:
while self._lst and not self._lst[0].active:
heapq.heappop(self._lst)
if self._lst:
return max(0, self._lst[0].when - self._now())
@ -662,7 +664,8 @@ class TimerList(object):
now = self._now()
while self._lst and self._lst[0].when <= now:
timer = heapq.heappop(self._lst)
if not timer.cancelled:
if timer.active:
timer.active = False
timer.func()

View File

@ -98,23 +98,31 @@ class ScheduleTest(TimerListMixin, testlib.TestCase):
class ExpireTest(TimerListMixin, testlib.TestCase):
def test_in_past(self):
timer = self.list.schedule(29, mock.Mock())
self.assertTrue(timer.active)
self.list._now = lambda: 30
self.list.expire()
self.assertEquals(1, len(timer.func.mock_calls))
self.assertFalse(timer.active)
def test_in_future(self):
timer = self.list.schedule(29, mock.Mock())
self.assertTrue(timer.active)
self.list._now = lambda: 28
self.list.expire()
self.assertEquals(0, len(timer.func.mock_calls))
self.assertTrue(timer.active)
def test_same_moment(self):
timer = self.list.schedule(29, mock.Mock())
timer2 = self.list.schedule(29, mock.Mock())
self.assertTrue(timer.active)
self.assertTrue(timer2.active)
self.list._now = lambda: 29
self.list.expire()
self.assertEquals(1, len(timer.func.mock_calls))
self.assertEquals(1, len(timer2.func.mock_calls))
self.assertFalse(timer.active)
self.assertFalse(timer2.active)
def test_cancelled(self):
self.list._now = lambda: 29
@ -131,7 +139,9 @@ class CancelTest(TimerListMixin, testlib.TestCase):
def test_single_cancel(self):
self.list._now = lambda: 29
timer = self.list.schedule(29, mock.Mock())
self.assertTrue(timer.active)
timer.cancel()
self.assertFalse(timer.active)
self.list.expire()
self.assertEquals(0, len(timer.func.mock_calls))
@ -139,7 +149,9 @@ class CancelTest(TimerListMixin, testlib.TestCase):
self.list._now = lambda: 29
timer = self.list.schedule(29, mock.Mock())
timer.cancel()
self.assertFalse(timer.active)
timer.cancel()
self.assertFalse(timer.active)
self.list.expire()
self.assertEquals(0, len(timer.func.mock_calls))