[Twisted-Python] A pseudo-deferred class that can be canceled

Terry Jones terry at jon.es
Tue Jan 5 07:47:50 EST 2010


Hi again Glyph, Andrew

Below is a simpler and more flexible ControllableDeferred class.

The idea is simple: you want a deferred that you can call/errback yourself,
and which you can also deactivate so that it never fires.  This is done by
manipulating two normal deferreds (self, and a deferred received from
maybeDeferred). This ControllableDeferred class sits in the middle and will
(a) pass on the normal result (via chainDeferred) if it arrives first, or
(b) if called by the user, fire with the user-supplied value, or (c) if
deactivated by the user, never fire. In cases b and c it will ignore the
result (if any ever arrives) from the function originally called.

In summary, this provides two things you can't ordinarily do when you get a
deferred (d) back from calling a function:

  - Call d yourself, thereby firing it immediately.
  - Deactivate d, so that it never fires.

The code below could be a bit more sophisticated. E.g., it could tell you
if you try to call a deferred you've deactivated. It should probably use an
attribute name other than _called.  I've kept it sparse for now though so
the general idea is clearer.  I changed its name to reflect that the
deferred is more controllable.

Terry

---

from twisted.internet import defer


class ControllableDeferred(defer.Deferred):    
    def __init__(self, f, *args, **kw):
        defer.Deferred.__init__(self)
        self._called = False
        self._calld = defer.maybeDeferred(f, *args, **kw).addBoth(self._fire)

    def _fire(self, ign):
        if not self._called:
            self._called = True
            self._calld.chainDeferred(self)

    def callback(self, result):
        if not self._called:
            self._called = True
            defer.Deferred.callback(self, result)

    def errback(self, fail=None):
        if not self._called:
            self._called = True
            defer.Deferred.callback(self, fail)

    def deactivate(self):
        self._called = True



More information about the Twisted-Python mailing list