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

Glyph Lefkowitz glyph at twistedmatrix.com
Mon Jan 4 21:58:32 EST 2010

On Jan 4, 2010, at 9:22 PM, Terry Jones wrote:

> 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.

I already lost you at the first sentence.  The class below never appears to use 'self._f', and ... Deferreds are things that fire, I don't see how the callable (f) can fire.  Can you rephrase your intent?

> 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'm glad you're thinking about this, because it is an *extremely* thorny issue which I would really like to address one day.  Many of the issues you're talking about were brought up, and various solutions suggested, then found problematic, then modified ad nauseam on <http://twistedmatrix.com/trac/ticket/990>.  If you can read that discussion and make some sense of it, perhaps you can post a recommendation there, or at least a summary of the discussion so far so that I don't have to read the whole discussion again to remember what I think should happen next? :)

> I don't know why defer.Deferred.setTimeout is deprecated, but I guess it's
> partly to do with this control issue.

This is one of the reasons, but another major reason is that 'setTimeout' does not belong as a method of Deferred.  If we did support cancellation somehow, the way to set a timeout would be to do 'reactor.callLater(5.0, myDeferred.cancel)'.  Deferred was originally in twisted.python and it really should have remained there, decoupled from twisted.internet.

More information about the Twisted-Python mailing list