I just wrote the below for fun. It's untested :-) It's a class that you initialize with a callable (f), and which gives you back a deferred (d) that will fire when f fires. Alternately, you can fire d yourself by calling 'callback' or 'errback' on the class instance and passing a value. That value is returned via d.
The reason this is useful is that normally when you call a function that returns a deferred, you can't easily "cancel" the deferred because it is made and controlled by the function you called. The callback or errback on the deferred is (very likely) going to be called at some point. OTOH, in the class below you get to "cancel" the deferred by triggering it yourself. If you fire d in this way, then when the original deferred fires (if ever), its result is ignored. I don't know why defer.Deferred.setTimeout is deprecated, but I guess it's partly to do with this control issue. If a timeout function you add to a deferred calls its errback (the default behavior), the deferred is still nevertheless going to be called by the code that created it. That code doesn't know and shouldn't have to check if a timeout happened from the POV of its caller. The setTimeout approach also only allows one timeout. With the below, any code can call the callback/errback function at any time. If you do want to cancel the deferred based simply on a timeout, you can do this (with as many different timeouts as you like - only the earliest will have any effect, supposing the original deferred still hasn't fired): cd = CancellableDeferred(func) deferred = cd.call() reactor.callLater(5, cd.errback, None) I post this partly because it seems cute, but more because it seems like issue that's probably been solved by many people. Is there a general utility in Twisted for doing this? A better way? Terry ---- from twisted.internet import defer class CancellableDeferred(object): def __init__(self, f, *args, **kw): self._f = f self._args = args self._kw = kw self._calld = None self.called = False def _fire(self, result): if not self.called: self.called = True self._calld.chainDeferred(self._resultd) def call(self): if self._calld: raise Exception('Already called.') self._resultd = defer.Deferred() self._calld = defer.maybeDeferred(self.f, *self._args, **self._kw) self._calld.addBoth(self._fire) return self._resultd def callback(self, value=None): if not self.called: self.called = True self._resultd.callback(value) def errback(self, value=None): if not self.called: self.called = True self._resultd.errback(value) _______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python