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 twisted.CancelledError, Deferredtwisted.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()

