Yet another cancelable Twisted deferred class
I’m posting this (completely untested!) to illustrate how one could write a class to provide a Twisted deferred-like class, identical to the twisted.internet.defer.Deferred class, but which lets you call callback, errback, or cancel on the instance yourself. Hopefully that will make some sense. If not, let me know in the comments and I’ll try to be clearer. There’s also discussion of this issue (again) in the Twisted mailing list right now. For context, the discussion thread from January 2010 where I first wrote a class like the below is here.
from twisted.internet.defer import CancelledError, Deferred
from twisted.python.failure import Failure
class ControllableDeferred2013(object):
"""A Deferred-like class that takes a regular Twisted Deferred and
provides a deferred that can be fired at will. If you have a regular
Twisted Deferred, you can produce a deferred you have more control over
by using your Deferred instance to make an instance of this class.
Any time you need to fire a ControllableDeferred2013 instance for any
reason, call its callback, errback or cancel method. It will fire
immediately with the value you provide and the original Deferred will
be cancelled."""
def __init__(self, originalDeferred):
self._fired = False
self._originalDeferred = originalDeferred
self._newDeferred = Deferred()
for method in ('addBoth', 'addCallback', 'addCallbacks', 'addErrback',
'chainDeferred'):
setattr(self, method, getattr(self._newDeferred, method))
originalDeferred.addBoth(self._originalFired)
def _originalFired(self, result):
if not self._fired:
self._fired = True
self._originalDeferred.chainDeferred(self._newDeferred)
def cancel(self, value=None):
if not self._fired:
self._fired = True
self._newDeferred.errback(Failure(CancelledError(value)))
self._originalDeferred.cancel()
def callback(self, result=None):
if not self._fired:
self._fired = True
self._newDeferred.callback(result)
self._originalDeferred.cancel()
def errback(self, fail=None):
if not self._fired:
self._fired = True
self._newDeferred.errback(fail)
self._originalDeferred.cancel()
def pause(self):
self._newDeferred.pause()
self._originalDeferred.pause()
def unpause(self):
self._newDeferred.unpause()
self._originalDeferred.unpause()
You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.