<div dir="ltr">Hi Tom<div><br></div><div>I'm not sure we should continue this discussion on the list seeing as the original issue seems to be settled. Anyway, here's an answer and maybe we could/should take it offline if there's more to say?<br>
<div class="gmail_extra"><br><div class="gmail_quote">On Sat, Jun 22, 2013 at 11:14 PM, Tom Prince <span dir="ltr"><<a href="mailto:tom.prince@ualberta.net" target="_blank">tom.prince@ualberta.net</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="im">Terry Jones <<a href="mailto:terry@jon.es">terry@jon.es</a>> writes:<br>
> The problem that I was originally trying to address by getting 'cancel'<br></div><div class="im">
> into deferreds is that the control flow you mention gets totally stuck if a<br>
> deferred never fires for some reason (this was happening to me in talking<br>
> to the Twitter API).<br>
<br>
</div>.cancel as currently implemented addresses this, as calling cancel<br>
causes the deferred to fire.</blockquote><div><br></div><div style>Right. When I say "originally" I mean in Jan 2010, before cancel was implemented. See the thread URL I posted a couple of times in this thread to see how it wen t down.</div>
<div style> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="im">
> This goes against the thinking that only the code that creates a deferred<br>
> can fire it.<br>
<br>
</div>To allow anything else would be to break the abstraction<br>
<br>
    d = Deferred()<br>
    return d<br>
    ...<br>
    d.callback(5)<br>
<br>
vs.<br>
    d = Deferred()<br>
    d.addCallback(lambda x: x+1)<br>
    return d<br>
    ...<br>
    d.callback(4)<br>
<br>
There is currently no way of distinguishing these to code<br>
snippets. Allowing other code to callback/errback the deferred<br>
would cause different results in the two cases.</blockquote><div><br></div><div style>That depends how you do it. If you actually have 2 deferreds, the original (which you can't err/callback yourself cause things will break) and one that you create yourself (as a "controllable" deferred), then you can allow the latter to be call/errbacked and hook the former up to the latter if the former fires first. That's what the code samples I posted do, including the one from Jan 2010. </div>
<div style> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="im">
> As API writers, we're used to being in control: we don't think it's a<br>
> good idea if we create and return a deferred in a method and the code<br>
> we return the deferred to then fires it itself.<br>
<br>
</div>It isn't so much a matter of control, as of abstraction. It isn't<br>
uncommon for a single deferred to be pass through several systems, with<br>
each stage adding more callbacks, changing the value that the next stage<br>
will see in the callbacks they add.<br></blockquote><div><br></div><div style>Right.</div><div style> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

If the "final" consumer could fire the deferred with any value, it would<br>
need to know about all the stagse (or at least the first one) to know<br>
what kind of value to put in.</blockquote><div><br></div><div style>In the ControlableDeferred2013 class I posted the other night, this isn't the case. If the deferred using code fires it, the only callbacks and errbacks that are run are ones that that code added (not ones added to the original deferred by the code that made it or any intermediates).</div>
<div style> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="im">
> But as app writers consuming deferreds from these APIs, we<br>
> want more control (I do, anyway).<br>
<br>
</div>Well, the consumer can't control the deferreds that it gets but, as your<br>
code demonstrates, it is easy enough to create a new deferred that<br>
behaves however the consumer wants. The fact that this isn't the same<br>
object isn't signifiant, since the identity of deferreds isn't an<br>
interesting thing.</blockquote><div><br></div><div style>Yes.</div><div style><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div class="im">
> The ControllableDeferred2013 class I posted last night shows one<br>
> way.<br>
<br>
</div>One comment about the code you posted: There doesn't really seem to be a<br>
need to create a sepearte class, that forwards<br>
.addCallback/.addErrback. You can just create a regular deferred that is<br>
hooked hooked up in the appropriate way. (It may make sense for the<br>
stage that sets this up to have an object, but it shouldn't pass it<br>
along, it should just pass a regular deferred on). There are a few<br>
places that accept deferreds that depend on the object being an instance<br>
of deferred, which your object isn't.</blockquote><div><br></div><div style>Yes, you can do that too (and there are other approaches). Here's a subclassing version that's similar to what you just described:</div>
<div><a href="http://twistedmatrix.com/pipermail/twisted-python/2010-January/021311.html">http://twistedmatrix.com/pipermail/twisted-python/2010-January/021311.html</a></div><div style>They're all basically the same idea (at least the way I do it), just based on setting up another deferred and hooking the original up to it when/if needed.</div>
</div><br></div></div><div class="gmail_extra" style>Terry</div><div class="gmail_extra" style><br></div></div>