[Twisted-Python] If the errbacks of a canceled Deferred are called with error other than CancelledError, is this acceptable?
Terry Jones
terry at jon.es
Thu Jun 20 16:26:37 MDT 2013
By the way, I don't need any of this to make its way into Twisted. I can
still write my own class that does what I want (well, wanted). Below is a
2013 version of the CancelableDeferred. It's untested. The basic idea is
that if you get a regular deferred from somewhere, you can use the class
below to make a new deferred that you can callback, errback, or cancel at
will. You can give a value to 'cancel' and it will be in args[0] of the
CancelledError that your errback will receive.
I still find this approach attractive because it maintains the
power/elegance of coding with Twisted deferreds but also gives the caller
of deferred-producing code more flexibility. That's got to be a good thing,
right?
I hope the code makes the intention more clear, not less.
Terry
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()
# BTW, I posted the above code to
http://blogs.fluidinfo.com/terry/2013/06/20/yet-another-cancelable-twisted-deferred-class/as
well.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/twisted-python/attachments/20130620/2e62c911/attachment-0002.html>
More information about the Twisted-Python
mailing list