4
from zope.interface import implements
6
from twisted.persisted import styles
7
from twisted.internet.interfaces import IDelayedCall
8
from twisted.internet import error, base
9
from twisted.python import reflect
11
class DelayedCall(styles.Ephemeral):
13
implements(IDelayedCall)
14
# enable .debug to record creator call stack, and it will be logged if
15
# an exception occurs while the function is being run
19
def __init__(self, time, func, args, kw, cancel, reset, seconds=None):
20
self.time, self.func, self.args, self.kw = time, func, args, kw
22
self.canceller = cancel
23
self.seconds = seconds
24
self.cancelled = self.called = 0
27
self.creator = traceback.format_stack()[:-2]
30
"""Return the time at which this call will fire
33
@return: The number of seconds after the epoch at which this call is
36
return self.time + self.delayed_time
39
"""Unschedule this call
41
@raise AlreadyCancelled: Raised if this call has already been
44
@raise AlreadyCalled: Raised if this call has already been made.
47
raise error.AlreadyCancelled
49
raise error.AlreadyCalled
55
del self.func, self.args, self.kw
57
def reset(self, secondsFromNow):
58
"""Reschedule this call for a different time
60
@type secondsFromNow: C{float}
61
@param secondsFromNow: The number of seconds from the time of the
62
C{reset} call at which this call will be scheduled.
64
@raise AlreadyCancelled: Raised if this call has been cancelled.
65
@raise AlreadyCalled: Raised if this call has already been made.
68
raise error.AlreadyCancelled
70
raise error.AlreadyCalled
72
if self.seconds is None:
73
new_time = base.seconds() + secondsFromNow
75
new_time = self.seconds() + secondsFromNow
76
if new_time < self.time:
81
self.delayed_time = new_time - self.time
83
def delay(self, secondsLater):
84
"""Reschedule this call for a later time
86
@type secondsLater: C{float}
87
@param secondsLater: The number of seconds after the originally
88
scheduled time for which to reschedule this call.
90
@raise AlreadyCancelled: Raised if this call has been cancelled.
91
@raise AlreadyCalled: Raised if this call has already been made.
94
raise error.AlreadyCancelled
96
raise error.AlreadyCalled
98
self.delayed_time += secondsLater
99
if self.delayed_time < 0:
100
self.activate_delay()
103
def activate_delay(self):
104
self.time += self.delayed_time
105
self.delayed_time = 0
108
"""Determine whether this call is still pending
111
@return: True if this call has not yet been made or cancelled,
114
return not (self.cancelled or self.called)
116
def __le__(self, other):
117
return self.time <= other.time
120
if self._str is not None:
122
if hasattr(self, 'func'):
123
if hasattr(self.func, 'func_name'):
124
func = self.func.func_name
125
if hasattr(self.func, 'im_class'):
126
func = self.func.im_class.__name__ + '.' + func
128
func = reflect.safe_repr(self.func)
132
if self.seconds is None:
136
L = ["<DelayedCall %s [%ss] called=%s cancelled=%s" % (
137
id(self), self.time - now, self.called, self.cancelled)]
139
L.extend((" ", func, "("))
141
L.append(", ".join([reflect.safe_repr(e) for e in self.args]))
145
L.append(", ".join(['%s=%s' % (k, reflect.safe_repr(v)) for (k, v) in self.kw.iteritems()]))
149
L.append("\n\ntraceback at creation: \n\n%s" % (' '.join(self.creator)))
158
base.DelayedCall.__dict__ = DelayedCall.__dict__
159
base.DelayedCall.__dict__['__module__'] = 'twisted.internet.base'
160
DelayedCall = base.DelayedCall