~justin-fathomdb/nova/justinsb-openstack-api-volumes

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/doc/core/howto/deferredindepth.html

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html  PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml">
 
2
  <head>
 
3
<title>Twisted Documentation: Deferreds are beautiful! (A Tutorial)</title>
 
4
<link href="stylesheet.css" rel="stylesheet" type="text/css"/>
 
5
  </head>
 
6
 
 
7
  <body bgcolor="white">
 
8
    <h1 class="title">Deferreds are beautiful! (A Tutorial)</h1>
 
9
    <div class="toc"><ol><li><a href="#auto0">Introduction</a></li><li><a href="#auto1">A simple example</a></li><li><a href="#auto2">Errbacks</a></li><ul><li><a href="#auto3">Failure in requested operation</a></li><li><a href="#auto4">Exceptions raised in callbacks</a></li><li><a href="#auto5">Exceptions will only be handled by errbacks</a></li><li><a href="#auto6">Handling an exception and continuing on</a></li></ul><li><a href="#auto7">addBoth: the deferred version of finally</a></li><li><a href="#auto8">addCallbacks: decision making based on previous success or failure</a></li><li><a href="#auto9">Hints, tips, common mistakes, and miscellaney</a></li><ul><li><a href="#auto10">The deferred callback chain is stateful</a></li><li><a href="#auto11">Don't call .callback() on deferreds you didn't create!</a></li><li><a href="#auto12">Callbacks can return deferreds</a></li></ul><li><a href="#auto13">Conclusion</a></li></ol></div>
 
10
    <div class="content">
 
11
<span/>
 
12
 
 
13
<h2>Introduction<a name="auto0"/></h2>
 
14
 
 
15
<p>Deferreds are quite possibly the single most confusing topic that a
 
16
newcomer to Twisted has to deal with. I am going to forgo the normal talk
 
17
about what deferreds are, what they aren't, and why they're used in Twisted.
 
18
Instead, I'm going show you the logic behind what they
 
19
<strong>do</strong>.</p>
 
20
 
 
21
 
 
22
<p>A deferred allows you to encapsulate the logic that you'd normally use to
 
23
make a series of function calls after receiving a result into a single object.
 
24
In the examples that follow, I'll first show you what's going to go on behind 
 
25
the scenes in the deferred chain, then show you the deferred API calls that set
 
26
up that chain. All of these examples are runnable code, so feel free to play 
 
27
around with them.</p>
 
28
 
 
29
 
 
30
<h2>A simple example<a name="auto1"/></h2>
 
31
 
 
32
First, a simple example so that we have something to talk about:
 
33
 
 
34
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
35
 2
 
36
 3
 
37
 4
 
38
 5
 
39
 6
 
40
 7
 
41
 8
 
42
 9
 
43
10
 
44
11
 
45
12
 
46
13
 
47
14
 
48
15
 
49
16
 
50
17
 
51
18
 
52
19
 
53
20
 
54
21
 
55
22
 
56
23
 
57
24
 
58
25
 
59
26
 
60
27
 
61
28
 
62
29
 
63
30
 
64
31
 
65
32
 
66
33
 
67
34
 
68
35
 
69
36
 
70
37
 
71
38
 
72
39
 
73
40
 
74
41
 
75
42
 
76
43
 
77
44
 
78
45
 
79
46
 
80
47
 
81
48
 
82
49
 
83
50
 
84
51
 
85
52
 
86
53
 
87
54
 
88
55
 
89
56
 
90
57
 
91
58
 
92
59
 
93
60
 
94
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
95
 
 
96
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
97
<span class="py-src-comment"># See LICENSE for details.</span>
 
98
 
 
99
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
 
100
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">failure</span>, <span class="py-src-variable">util</span>
 
101
 
 
102
<span class="py-src-string">&quot;&quot;&quot;
 
103
Here we have the simplest case, a single callback and a single errback.
 
104
&quot;&quot;&quot;</span>
 
105
 
 
106
<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
107
 
 
108
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleFailure</span>(<span class="py-src-parameter">f</span>):
 
109
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;errback&quot;</span>
 
110
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;we got an exception: %s&quot;</span> % (<span class="py-src-variable">f</span>.<span class="py-src-variable">getTraceback</span>(),)
 
111
    <span class="py-src-variable">f</span>.<span class="py-src-variable">trap</span>(<span class="py-src-variable">RuntimeError</span>)
 
112
 
 
113
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleResult</span>(<span class="py-src-parameter">result</span>):
 
114
    <span class="py-src-keyword">global</span> <span class="py-src-variable">num</span>; <span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
115
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">num</span>,)
 
116
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
117
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;yay! handleResult was successful!&quot;</span>
 
118
 
 
119
 
 
120
<span class="py-src-keyword">def</span> <span class="py-src-identifier">behindTheScenes</span>(<span class="py-src-parameter">result</span>):
 
121
    <span class="py-src-comment"># equivalent to d.callback(result)</span>
 
122
 
 
123
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
124
        <span class="py-src-keyword">try</span>:
 
125
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleResult</span>(<span class="py-src-variable">result</span>)
 
126
        <span class="py-src-keyword">except</span>:
 
127
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
128
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
129
        <span class="py-src-keyword">pass</span>
 
130
 
 
131
 
 
132
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
133
        <span class="py-src-keyword">pass</span>
 
134
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
135
        <span class="py-src-keyword">try</span>:
 
136
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleFailure</span>(<span class="py-src-variable">result</span>)
 
137
        <span class="py-src-keyword">except</span>:
 
138
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
139
 
 
140
 
 
141
<span class="py-src-keyword">def</span> <span class="py-src-identifier">deferredExample</span>():
 
142
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
 
143
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>)
 
144
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">handleFailure</span>)
 
145
 
 
146
    <span class="py-src-variable">d</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
147
 
 
148
 
 
149
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
 
150
    <span class="py-src-variable">behindTheScenes</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
151
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
 
152
    <span class="py-src-keyword">global</span> <span class="py-src-variable">num</span>; <span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
153
    <span class="py-src-variable">deferredExample</span>()
 
154
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex.py"><span class="filename">listings/deferred/deferred_ex.py</span></a></div></div>
 
155
 
 
156
<p>And the output: (since both methods in the example produce the same output,
 
157
it will only be shown once.) </p>
 
158
 
 
159
<pre xml:space="preserve">
 
160
callback 1
 
161
        got result: success
 
162
</pre>
 
163
 
 
164
<p>Here we have the simplest case. A deferred with a single callback and a
 
165
single errback. Normally, a function would create a deferred and hand it back
 
166
to you when you request an operation that needs to wait for an event for
 
167
completion.  The object you called then does <code>d.callback(result)</code>
 
168
when the results are in.  
 
169
</p>
 
170
 
 
171
<p>The thing to notice is that there is only one result that is passed from
 
172
method to method, and that the result returned from a method is the argument
 
173
to the next method in the chain. In case of an exception, result is set to an
 
174
instance of <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.python.failure.Failure.html" title="twisted.python.failure.Failure">Failure</a></code>
 
175
that describes the exception.</p>
 
176
 
 
177
<h2>Errbacks<a name="auto2"/></h2>
 
178
<h3>Failure in requested operation<a name="auto3"/></h3>
 
179
<p>Things don't always go as planned, and sometimes the function that
 
180
returned the deferred needs to alert the callback chain that an error
 
181
has occurred.</p>
 
182
 
 
183
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
184
 2
 
185
 3
 
186
 4
 
187
 5
 
188
 6
 
189
 7
 
190
 8
 
191
 9
 
192
10
 
193
11
 
194
12
 
195
13
 
196
14
 
197
15
 
198
16
 
199
17
 
200
18
 
201
19
 
202
20
 
203
21
 
204
22
 
205
23
 
206
24
 
207
25
 
208
26
 
209
27
 
210
28
 
211
29
 
212
30
 
213
31
 
214
32
 
215
33
 
216
34
 
217
35
 
218
36
 
219
37
 
220
38
 
221
39
 
222
40
 
223
41
 
224
42
 
225
43
 
226
44
 
227
45
 
228
46
 
229
47
 
230
48
 
231
49
 
232
50
 
233
51
 
234
52
 
235
53
 
236
54
 
237
55
 
238
56
 
239
57
 
240
58
 
241
59
 
242
60
 
243
61
 
244
62
 
245
63
 
246
64
 
247
65
 
248
66
 
249
67
 
250
68
 
251
69
 
252
70
 
253
71
 
254
72
 
255
73
 
256
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
257
 
 
258
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
259
<span class="py-src-comment"># See LICENSE for details.</span>
 
260
 
 
261
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
 
262
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">failure</span>, <span class="py-src-variable">util</span>
 
263
 
 
264
<span class="py-src-string">&quot;&quot;&quot;
 
265
This example is analogous to a function calling .errback(failure)
 
266
&quot;&quot;&quot;</span>
 
267
 
 
268
 
 
269
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
 
270
    <span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
271
 
 
272
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleFailure</span>(<span class="py-src-parameter">f</span>):
 
273
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;errback&quot;</span>
 
274
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;we got an exception: %s&quot;</span> % (<span class="py-src-variable">f</span>.<span class="py-src-variable">getTraceback</span>(),)
 
275
    <span class="py-src-variable">f</span>.<span class="py-src-variable">trap</span>(<span class="py-src-variable">RuntimeError</span>)
 
276
 
 
277
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleResult</span>(<span class="py-src-parameter">result</span>):
 
278
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
279
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
280
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
281
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;yay! handleResult was successful!&quot;</span>
 
282
 
 
283
<span class="py-src-keyword">def</span> <span class="py-src-identifier">failAtHandlingResult</span>(<span class="py-src-parameter">result</span>):
 
284
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
285
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
286
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
287
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tabout to raise exception&quot;</span>
 
288
    <span class="py-src-keyword">raise</span> <span class="py-src-variable">RuntimeError</span>, <span class="py-src-string">&quot;whoops! we encountered an error&quot;</span>
 
289
 
 
290
 
 
291
<span class="py-src-keyword">def</span> <span class="py-src-identifier">behindTheScenes</span>(<span class="py-src-parameter">result</span>):
 
292
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
293
        <span class="py-src-keyword">try</span>:
 
294
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleResult</span>(<span class="py-src-variable">result</span>)
 
295
        <span class="py-src-keyword">except</span>:
 
296
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
297
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
298
        <span class="py-src-keyword">pass</span>
 
299
 
 
300
 
 
301
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
302
        <span class="py-src-keyword">pass</span>
 
303
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
304
        <span class="py-src-keyword">try</span>:
 
305
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleFailure</span>(<span class="py-src-variable">result</span>)
 
306
        <span class="py-src-keyword">except</span>:
 
307
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
308
 
 
309
 
 
310
<span class="py-src-keyword">def</span> <span class="py-src-identifier">deferredExample</span>(<span class="py-src-parameter">result</span>):
 
311
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
 
312
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>)
 
313
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">failAtHandlingResult</span>)
 
314
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">handleFailure</span>)
 
315
 
 
316
    <span class="py-src-variable">d</span>.<span class="py-src-variable">errback</span>(<span class="py-src-variable">result</span>)
 
317
 
 
318
 
 
319
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
 
320
    <span class="py-src-variable">result</span> = <span class="py-src-variable">None</span>
 
321
    <span class="py-src-keyword">try</span>:
 
322
        <span class="py-src-keyword">raise</span> <span class="py-src-variable">RuntimeError</span>, <span class="py-src-string">&quot;*doh*! failure!&quot;</span>
 
323
    <span class="py-src-keyword">except</span>:
 
324
        <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
325
    <span class="py-src-variable">behindTheScenes</span>(<span class="py-src-variable">result</span>)
 
326
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
 
327
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
328
    <span class="py-src-variable">deferredExample</span>(<span class="py-src-variable">result</span>)
 
329
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex1a.py"><span class="filename">listings/deferred/deferred_ex1a.py</span></a></div></div>
 
330
 
 
331
<pre xml:space="preserve">
 
332
errback
 
333
we got an exception: Traceback (most recent call last):
 
334
--- exception caught here ---
 
335
  File &quot;deferred_ex1a.py&quot;, line 73, in ?
 
336
    raise RuntimeError, &quot;*doh*! failure!&quot;
 
337
exceptions.RuntimeError: *doh*! failure!
 
338
</pre>
 
339
 
 
340
<p> The important thing to note (as it will come up again in later examples)
 
341
is that the callback isn't touched, the failure goes right to the errback.
 
342
Also note that the errback trap()s the expected exception type. If you don't
 
343
trap the exception, an error will be logged when the deferred is
 
344
garbage-collected. 
 
345
</p>
 
346
 
 
347
 
 
348
<h3>Exceptions raised in callbacks<a name="auto4"/></h3>
 
349
 
 
350
<p>Now let's see what happens when <em>our callback</em> raises an
 
351
exception</p>
 
352
 
 
353
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
354
 2
 
355
 3
 
356
 4
 
357
 5
 
358
 6
 
359
 7
 
360
 8
 
361
 9
 
362
10
 
363
11
 
364
12
 
365
13
 
366
14
 
367
15
 
368
16
 
369
17
 
370
18
 
371
19
 
372
20
 
373
21
 
374
22
 
375
23
 
376
24
 
377
25
 
378
26
 
379
27
 
380
28
 
381
29
 
382
30
 
383
31
 
384
32
 
385
33
 
386
34
 
387
35
 
388
36
 
389
37
 
390
38
 
391
39
 
392
40
 
393
41
 
394
42
 
395
43
 
396
44
 
397
45
 
398
46
 
399
47
 
400
48
 
401
49
 
402
50
 
403
51
 
404
52
 
405
53
 
406
54
 
407
55
 
408
56
 
409
57
 
410
58
 
411
59
 
412
60
 
413
61
 
414
62
 
415
63
 
416
64
 
417
65
 
418
66
 
419
67
 
420
68
 
421
69
 
422
70
 
423
71
 
424
72
 
425
73
 
426
74
 
427
75
 
428
76
 
429
77
 
430
78
 
431
79
 
432
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
433
 
 
434
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
435
<span class="py-src-comment"># See LICENSE for details.</span>
 
436
 
 
437
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
 
438
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">failure</span>, <span class="py-src-variable">util</span>
 
439
 
 
440
<span class="py-src-string">&quot;&quot;&quot;
 
441
Here we have a slightly more involved case. The deferred is called back with a
 
442
result. the first callback returns a value, the second callback, however
 
443
raises an exception, which is handled by the errback.
 
444
&quot;&quot;&quot;</span>
 
445
 
 
446
 
 
447
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
 
448
    <span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
449
 
 
450
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleFailure</span>(<span class="py-src-parameter">f</span>):
 
451
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;errback&quot;</span>
 
452
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;we got an exception: %s&quot;</span> % (<span class="py-src-variable">f</span>.<span class="py-src-variable">getTraceback</span>(),)
 
453
    <span class="py-src-variable">f</span>.<span class="py-src-variable">trap</span>(<span class="py-src-variable">RuntimeError</span>)
 
454
 
 
455
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleResult</span>(<span class="py-src-parameter">result</span>):
 
456
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
457
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
458
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
459
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;yay! handleResult was successful!&quot;</span>
 
460
 
 
461
<span class="py-src-keyword">def</span> <span class="py-src-identifier">failAtHandlingResult</span>(<span class="py-src-parameter">result</span>):
 
462
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
463
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
464
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
465
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tabout to raise exception&quot;</span>
 
466
    <span class="py-src-keyword">raise</span> <span class="py-src-variable">RuntimeError</span>, <span class="py-src-string">&quot;whoops! we encountered an error&quot;</span>
 
467
 
 
468
 
 
469
<span class="py-src-keyword">def</span> <span class="py-src-identifier">behindTheScenes</span>(<span class="py-src-parameter">result</span>):
 
470
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
471
        <span class="py-src-keyword">try</span>:
 
472
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleResult</span>(<span class="py-src-variable">result</span>)
 
473
        <span class="py-src-keyword">except</span>:
 
474
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
475
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
476
        <span class="py-src-keyword">pass</span>
 
477
 
 
478
 
 
479
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
480
        <span class="py-src-keyword">try</span>:
 
481
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failAtHandlingResult</span>(<span class="py-src-variable">result</span>)
 
482
        <span class="py-src-keyword">except</span>:
 
483
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
484
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
485
        <span class="py-src-keyword">pass</span>
 
486
 
 
487
 
 
488
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
489
        <span class="py-src-keyword">pass</span>
 
490
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
491
        <span class="py-src-keyword">try</span>:
 
492
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleFailure</span>(<span class="py-src-variable">result</span>)
 
493
        <span class="py-src-keyword">except</span>:
 
494
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
495
 
 
496
 
 
497
<span class="py-src-keyword">def</span> <span class="py-src-identifier">deferredExample</span>():
 
498
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
 
499
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>)
 
500
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">failAtHandlingResult</span>)
 
501
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">handleFailure</span>)
 
502
 
 
503
    <span class="py-src-variable">d</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
504
 
 
505
 
 
506
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
 
507
    <span class="py-src-variable">behindTheScenes</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
508
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
 
509
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
510
    <span class="py-src-variable">deferredExample</span>()
 
511
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex1b.py"><span class="filename">listings/deferred/deferred_ex1b.py</span></a></div></div>
 
512
 
 
513
<p>And the output: (note, tracebacks will be edited slightly to conserve
 
514
space)</p>
 
515
 
 
516
<pre xml:space="preserve">
 
517
callback 1
 
518
        got result: success
 
519
callback 2
 
520
        got result: yay! handleResult was successful!
 
521
        about to raise exception
 
522
errback
 
523
we got an exception: Traceback (most recent call last):
 
524
--- &lt;exception caught here&gt; ---
 
525
  File &quot;/home/slyphon/Projects/Twisted/trunk/twisted/internet/defer.py&quot;, line
 
526
326, in _runCallbacks
 
527
    self.result = callback(self.result, *args, **kw)
 
528
  File &quot;./deferred_ex1.py&quot;, line 32, in failAtHandlingResult
 
529
    raise RuntimeError, &quot;whoops! we encountered an error&quot;
 
530
exceptions.RuntimeError: whoops! we encountered an error
 
531
</pre>
 
532
 
 
533
<p>If your callback raises an exception, the next method to be called will be 
 
534
the next errback in your chain.</p>
 
535
 
 
536
 
 
537
<h3>Exceptions will only be handled by errbacks<a name="auto5"/></h3>
 
538
 
 
539
<p>If a callback raises an exception the next method to be called will be next
 
540
errback in the chain. If the chain is started off with a failure, the first
 
541
method to be called will be the first errback.</p>
 
542
 
 
543
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
544
 2
 
545
 3
 
546
 4
 
547
 5
 
548
 6
 
549
 7
 
550
 8
 
551
 9
 
552
10
 
553
11
 
554
12
 
555
13
 
556
14
 
557
15
 
558
16
 
559
17
 
560
18
 
561
19
 
562
20
 
563
21
 
564
22
 
565
23
 
566
24
 
567
25
 
568
26
 
569
27
 
570
28
 
571
29
 
572
30
 
573
31
 
574
32
 
575
33
 
576
34
 
577
35
 
578
36
 
579
37
 
580
38
 
581
39
 
582
40
 
583
41
 
584
42
 
585
43
 
586
44
 
587
45
 
588
46
 
589
47
 
590
48
 
591
49
 
592
50
 
593
51
 
594
52
 
595
53
 
596
54
 
597
55
 
598
56
 
599
57
 
600
58
 
601
59
 
602
60
 
603
61
 
604
62
 
605
63
 
606
64
 
607
65
 
608
66
 
609
67
 
610
68
 
611
69
 
612
70
 
613
71
 
614
72
 
615
73
 
616
74
 
617
75
 
618
76
 
619
77
 
620
78
 
621
79
 
622
80
 
623
81
 
624
82
 
625
83
 
626
84
 
627
85
 
628
86
 
629
87
 
630
88
 
631
89
 
632
90
 
633
91
 
634
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
635
 
 
636
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
637
<span class="py-src-comment"># See LICENSE for details.</span>
 
638
 
 
639
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
 
640
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">failure</span>, <span class="py-src-variable">util</span>
 
641
 
 
642
<span class="py-src-string">&quot;&quot;&quot;
 
643
This example shows an important concept that many deferred newbies
 
644
(myself included) have trouble understanding.
 
645
 
 
646
when an error occurs in a callback, the first errback after the error
 
647
occurs will be the next method called. (in the next example we'll
 
648
see what happens in the 'chain' after an errback).
 
649
&quot;&quot;&quot;</span>
 
650
 
 
651
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
 
652
    <span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
653
 
 
654
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleFailure</span>(<span class="py-src-parameter">f</span>):
 
655
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;errback&quot;</span>
 
656
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;we got an exception: %s&quot;</span> % (<span class="py-src-variable">f</span>.<span class="py-src-variable">getTraceback</span>(),)
 
657
    <span class="py-src-variable">f</span>.<span class="py-src-variable">trap</span>(<span class="py-src-variable">RuntimeError</span>)
 
658
 
 
659
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleResult</span>(<span class="py-src-parameter">result</span>):
 
660
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
661
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
662
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
663
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;yay! handleResult was successful!&quot;</span>
 
664
 
 
665
<span class="py-src-keyword">def</span> <span class="py-src-identifier">failAtHandlingResult</span>(<span class="py-src-parameter">result</span>):
 
666
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
667
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
668
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
669
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tabout to raise exception&quot;</span>
 
670
    <span class="py-src-keyword">raise</span> <span class="py-src-variable">RuntimeError</span>, <span class="py-src-string">&quot;whoops! we encountered an error&quot;</span>
 
671
 
 
672
 
 
673
 
 
674
<span class="py-src-keyword">def</span> <span class="py-src-identifier">behindTheScenes</span>(<span class="py-src-parameter">result</span>):
 
675
    <span class="py-src-comment"># equivalent to d.callback(result)</span>
 
676
 
 
677
    <span class="py-src-comment"># now, let's make the error happen in the first callback</span>
 
678
 
 
679
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
680
        <span class="py-src-keyword">try</span>:
 
681
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failAtHandlingResult</span>(<span class="py-src-variable">result</span>)
 
682
        <span class="py-src-keyword">except</span>:
 
683
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
684
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
685
        <span class="py-src-keyword">pass</span>
 
686
 
 
687
 
 
688
    <span class="py-src-comment"># note: this callback will be skipped because</span>
 
689
    <span class="py-src-comment"># result is a failure</span>
 
690
 
 
691
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
692
        <span class="py-src-keyword">try</span>:
 
693
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleResult</span>(<span class="py-src-variable">result</span>)
 
694
        <span class="py-src-keyword">except</span>:
 
695
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
696
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
697
        <span class="py-src-keyword">pass</span>
 
698
 
 
699
 
 
700
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
701
        <span class="py-src-keyword">pass</span>
 
702
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
703
        <span class="py-src-keyword">try</span>:
 
704
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleFailure</span>(<span class="py-src-variable">result</span>)
 
705
        <span class="py-src-keyword">except</span>:
 
706
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
707
 
 
708
 
 
709
 
 
710
<span class="py-src-keyword">def</span> <span class="py-src-identifier">deferredExample</span>():
 
711
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
 
712
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">failAtHandlingResult</span>)
 
713
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>)
 
714
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">handleFailure</span>)
 
715
 
 
716
    <span class="py-src-variable">d</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
717
 
 
718
 
 
719
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
 
720
    <span class="py-src-variable">behindTheScenes</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
721
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
 
722
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
723
    <span class="py-src-variable">deferredExample</span>()
 
724
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex2.py"><span class="filename">listings/deferred/deferred_ex2.py</span></a></div></div>
 
725
 
 
726
<pre xml:space="preserve">
 
727
callback 1
 
728
        got result: success
 
729
        about to raise exception
 
730
errback
 
731
we got an exception: Traceback (most recent call last):
 
732
  File &quot;./deferred_ex2.py&quot;, line 85, in ?
 
733
    nonDeferredExample(&quot;success&quot;)
 
734
--- &lt;exception caught here&gt; ---
 
735
  File &quot;./deferred_ex2.py&quot;, line 46, in nonDeferredExample
 
736
    result = failAtHandlingResult(result)
 
737
  File &quot;./deferred_ex2.py&quot;, line 35, in failAtHandlingResult
 
738
    raise RuntimeError, &quot;whoops! we encountered an error&quot;
 
739
exceptions.RuntimeError: whoops! we encountered an error
 
740
</pre>
 
741
 
 
742
<p>You can see that our second callback, handleResult was not called because
 
743
failAtHandlingResult raised an exception</p>
 
744
 
 
745
<h3>Handling an exception and continuing on<a name="auto6"/></h3>
 
746
 
 
747
<p>In this example, we see an errback handle an exception raised in the
 
748
preceeding callback.  Take note that it could just as easily been an exception
 
749
from <strong>any other</strong> preceeding method. You'll see that after the
 
750
exception is handled in the errback (i.e.  the errback does not return a
 
751
failure or raise an exception) the chain continues on with the next
 
752
callback.</p>
 
753
 
 
754
<div class="py-listing"><pre><p class="py-linenumber">  1
 
755
  2
 
756
  3
 
757
  4
 
758
  5
 
759
  6
 
760
  7
 
761
  8
 
762
  9
 
763
 10
 
764
 11
 
765
 12
 
766
 13
 
767
 14
 
768
 15
 
769
 16
 
770
 17
 
771
 18
 
772
 19
 
773
 20
 
774
 21
 
775
 22
 
776
 23
 
777
 24
 
778
 25
 
779
 26
 
780
 27
 
781
 28
 
782
 29
 
783
 30
 
784
 31
 
785
 32
 
786
 33
 
787
 34
 
788
 35
 
789
 36
 
790
 37
 
791
 38
 
792
 39
 
793
 40
 
794
 41
 
795
 42
 
796
 43
 
797
 44
 
798
 45
 
799
 46
 
800
 47
 
801
 48
 
802
 49
 
803
 50
 
804
 51
 
805
 52
 
806
 53
 
807
 54
 
808
 55
 
809
 56
 
810
 57
 
811
 58
 
812
 59
 
813
 60
 
814
 61
 
815
 62
 
816
 63
 
817
 64
 
818
 65
 
819
 66
 
820
 67
 
821
 68
 
822
 69
 
823
 70
 
824
 71
 
825
 72
 
826
 73
 
827
 74
 
828
 75
 
829
 76
 
830
 77
 
831
 78
 
832
 79
 
833
 80
 
834
 81
 
835
 82
 
836
 83
 
837
 84
 
838
 85
 
839
 86
 
840
 87
 
841
 88
 
842
 89
 
843
 90
 
844
 91
 
845
 92
 
846
 93
 
847
 94
 
848
 95
 
849
 96
 
850
 97
 
851
 98
 
852
 99
 
853
100
 
854
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
855
 
 
856
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
857
<span class="py-src-comment"># See LICENSE for details.</span>
 
858
 
 
859
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
 
860
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">failure</span>, <span class="py-src-variable">util</span>
 
861
 
 
862
<span class="py-src-string">&quot;&quot;&quot;
 
863
Now we see how an errback can handle errors. if an errback
 
864
does not raise an exception, the next callback in the chain
 
865
will be called.
 
866
&quot;&quot;&quot;</span>
 
867
 
 
868
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
 
869
    <span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
870
 
 
871
 
 
872
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleFailure</span>(<span class="py-src-parameter">f</span>):
 
873
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;errback&quot;</span>
 
874
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;we got an exception: %s&quot;</span> % (<span class="py-src-variable">f</span>.<span class="py-src-variable">getTraceback</span>(),)
 
875
    <span class="py-src-variable">f</span>.<span class="py-src-variable">trap</span>(<span class="py-src-variable">RuntimeError</span>)
 
876
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;okay, continue on&quot;</span>
 
877
 
 
878
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleResult</span>(<span class="py-src-parameter">result</span>):
 
879
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
880
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
881
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
882
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;yay! handleResult was successful!&quot;</span>
 
883
 
 
884
<span class="py-src-keyword">def</span> <span class="py-src-identifier">failAtHandlingResult</span>(<span class="py-src-parameter">result</span>):
 
885
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
886
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
887
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
888
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tabout to raise exception&quot;</span>
 
889
    <span class="py-src-keyword">raise</span> <span class="py-src-variable">RuntimeError</span>, <span class="py-src-string">&quot;whoops! we encountered an error&quot;</span>
 
890
 
 
891
<span class="py-src-keyword">def</span> <span class="py-src-identifier">callbackAfterErrback</span>(<span class="py-src-parameter">result</span>):
 
892
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
893
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
894
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
895
 
 
896
 
 
897
 
 
898
<span class="py-src-keyword">def</span> <span class="py-src-identifier">behindTheScenes</span>(<span class="py-src-parameter">result</span>):
 
899
    <span class="py-src-comment"># equivalent to d.callback(result)</span>
 
900
 
 
901
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
902
        <span class="py-src-keyword">try</span>:
 
903
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleResult</span>(<span class="py-src-variable">result</span>)
 
904
        <span class="py-src-keyword">except</span>:
 
905
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
906
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
907
        <span class="py-src-keyword">pass</span>
 
908
 
 
909
 
 
910
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
911
        <span class="py-src-keyword">try</span>:
 
912
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failAtHandlingResult</span>(<span class="py-src-variable">result</span>)
 
913
        <span class="py-src-keyword">except</span>:
 
914
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
915
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
916
        <span class="py-src-keyword">pass</span>
 
917
 
 
918
 
 
919
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
920
        <span class="py-src-keyword">pass</span>
 
921
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
922
        <span class="py-src-keyword">try</span>:
 
923
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleFailure</span>(<span class="py-src-variable">result</span>)
 
924
        <span class="py-src-keyword">except</span>:
 
925
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
926
 
 
927
 
 
928
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
929
        <span class="py-src-keyword">try</span>:
 
930
            <span class="py-src-variable">result</span> = <span class="py-src-variable">callbackAfterErrback</span>(<span class="py-src-variable">result</span>)
 
931
        <span class="py-src-keyword">except</span>:
 
932
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
933
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
934
        <span class="py-src-keyword">pass</span>
 
935
 
 
936
 
 
937
 
 
938
<span class="py-src-keyword">def</span> <span class="py-src-identifier">deferredExample</span>():
 
939
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
 
940
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>)
 
941
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">failAtHandlingResult</span>)
 
942
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">handleFailure</span>)
 
943
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">callbackAfterErrback</span>)
 
944
 
 
945
    <span class="py-src-variable">d</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
946
 
 
947
 
 
948
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
 
949
    <span class="py-src-variable">behindTheScenes</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
950
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
 
951
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
952
    <span class="py-src-variable">deferredExample</span>()
 
953
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex3.py"><span class="filename">listings/deferred/deferred_ex3.py</span></a></div></div>
 
954
 
 
955
<pre xml:space="preserve">
 
956
callback 1
 
957
        got result: success
 
958
callback 2
 
959
        got result: yay! handleResult was successful!
 
960
        about to raise exception
 
961
errback
 
962
we got an exception: Traceback (most recent call last):
 
963
  File &quot;./deferred_ex3.py&quot;, line 97, in &lt;module&gt;
 
964
    deferredExample()
 
965
  File &quot;./deferred_ex3.py&quot;, line 90, in deferredExample
 
966
    d.callback(&quot;success&quot;)
 
967
  File &quot;/home/slyphon/Projects/Twisted/trunk/twisted/internet/defer.py&quot;, line 243, in callback
 
968
    self._startRunCallbacks(result)
 
969
  File &quot;/home/slyphon/Projects/Twisted/trunk/twisted/internet/defer.py&quot;, line 312, in _startRunCallbacks
 
970
    self._runCallbacks()
 
971
--- &lt;exception caught here&gt; ---
 
972
  File &quot;/home/slyphon/Projects/Twisted/trunk/twisted/internet/defer.py&quot;, line 328, in _runCallbacks
 
973
    self.result = callback(self.result, *args, **kw)
 
974
  File &quot;./deferred_ex3.py&quot;, line 34, in failAtHandlingResult
 
975
    raise RuntimeError, &quot;whoops! we encountered an error&quot;
 
976
exceptions.RuntimeError: whoops! we encountered an error
 
977
 
 
978
callback 3
 
979
        got result: okay, continue on
 
980
</pre>
 
981
 
 
982
<h2>addBoth: the deferred version of <em>finally</em><a name="auto7"/></h2>
 
983
 
 
984
<p>Now we see how deferreds do <strong>finally</strong>, with .addBoth. The
 
985
callback that gets added as addBoth will be called if the result is a failure
 
986
or non-failure. We'll also see in this example, that our doThisNoMatterWhat()
 
987
method follows a common idiom in deferred callbacks by acting as a passthru,
 
988
returning the value that it received to allow processing the chain to
 
989
continue, but appearing transparent in terms of the result.</p>
 
990
 
 
991
<div class="py-listing"><pre><p class="py-linenumber">  1
 
992
  2
 
993
  3
 
994
  4
 
995
  5
 
996
  6
 
997
  7
 
998
  8
 
999
  9
 
1000
 10
 
1001
 11
 
1002
 12
 
1003
 13
 
1004
 14
 
1005
 15
 
1006
 16
 
1007
 17
 
1008
 18
 
1009
 19
 
1010
 20
 
1011
 21
 
1012
 22
 
1013
 23
 
1014
 24
 
1015
 25
 
1016
 26
 
1017
 27
 
1018
 28
 
1019
 29
 
1020
 30
 
1021
 31
 
1022
 32
 
1023
 33
 
1024
 34
 
1025
 35
 
1026
 36
 
1027
 37
 
1028
 38
 
1029
 39
 
1030
 40
 
1031
 41
 
1032
 42
 
1033
 43
 
1034
 44
 
1035
 45
 
1036
 46
 
1037
 47
 
1038
 48
 
1039
 49
 
1040
 50
 
1041
 51
 
1042
 52
 
1043
 53
 
1044
 54
 
1045
 55
 
1046
 56
 
1047
 57
 
1048
 58
 
1049
 59
 
1050
 60
 
1051
 61
 
1052
 62
 
1053
 63
 
1054
 64
 
1055
 65
 
1056
 66
 
1057
 67
 
1058
 68
 
1059
 69
 
1060
 70
 
1061
 71
 
1062
 72
 
1063
 73
 
1064
 74
 
1065
 75
 
1066
 76
 
1067
 77
 
1068
 78
 
1069
 79
 
1070
 80
 
1071
 81
 
1072
 82
 
1073
 83
 
1074
 84
 
1075
 85
 
1076
 86
 
1077
 87
 
1078
 88
 
1079
 89
 
1080
 90
 
1081
 91
 
1082
 92
 
1083
 93
 
1084
 94
 
1085
 95
 
1086
 96
 
1087
 97
 
1088
 98
 
1089
 99
 
1090
100
 
1091
101
 
1092
102
 
1093
103
 
1094
104
 
1095
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
1096
 
 
1097
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
1098
<span class="py-src-comment"># See LICENSE for details.</span>
 
1099
 
 
1100
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
 
1101
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">failure</span>, <span class="py-src-variable">util</span>
 
1102
 
 
1103
<span class="py-src-string">&quot;&quot;&quot;
 
1104
Now we'll see what happens when you use 'addBoth'.
 
1105
&quot;&quot;&quot;</span>
 
1106
 
 
1107
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
 
1108
    <span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
1109
 
 
1110
 
 
1111
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleFailure</span>(<span class="py-src-parameter">f</span>):
 
1112
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;errback&quot;</span>
 
1113
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;we got an exception: %s&quot;</span> % (<span class="py-src-variable">f</span>.<span class="py-src-variable">getTraceback</span>(),)
 
1114
    <span class="py-src-variable">f</span>.<span class="py-src-variable">trap</span>(<span class="py-src-variable">RuntimeError</span>)
 
1115
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;okay, continue on&quot;</span>
 
1116
 
 
1117
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleResult</span>(<span class="py-src-parameter">result</span>):
 
1118
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
1119
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
1120
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
1121
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;yay! handleResult was successful!&quot;</span>
 
1122
 
 
1123
<span class="py-src-keyword">def</span> <span class="py-src-identifier">failAtHandlingResult</span>(<span class="py-src-parameter">result</span>):
 
1124
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
1125
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
1126
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
1127
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tabout to raise exception&quot;</span>
 
1128
    <span class="py-src-keyword">raise</span> <span class="py-src-variable">RuntimeError</span>, <span class="py-src-string">&quot;whoops! we encountered an error&quot;</span>
 
1129
 
 
1130
<span class="py-src-keyword">def</span> <span class="py-src-identifier">doThisNoMatterWhat</span>(<span class="py-src-parameter">arg</span>):
 
1131
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
1132
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;both %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
1133
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot argument %r&quot;</span> % (<span class="py-src-variable">arg</span>,)
 
1134
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tdoing something very important&quot;</span>
 
1135
    <span class="py-src-comment"># we pass the argument we received to the next phase here</span>
 
1136
    <span class="py-src-keyword">return</span> <span class="py-src-variable">arg</span>
 
1137
 
 
1138
 
 
1139
 
 
1140
<span class="py-src-keyword">def</span> <span class="py-src-identifier">behindTheScenes</span>(<span class="py-src-parameter">result</span>):
 
1141
    <span class="py-src-comment"># equivalent to d.callback(result)</span>
 
1142
 
 
1143
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1144
        <span class="py-src-keyword">try</span>:
 
1145
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleResult</span>(<span class="py-src-variable">result</span>)
 
1146
        <span class="py-src-keyword">except</span>:
 
1147
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1148
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1149
        <span class="py-src-keyword">pass</span>
 
1150
 
 
1151
 
 
1152
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1153
        <span class="py-src-keyword">try</span>:
 
1154
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failAtHandlingResult</span>(<span class="py-src-variable">result</span>)
 
1155
        <span class="py-src-keyword">except</span>:
 
1156
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1157
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1158
        <span class="py-src-keyword">pass</span>
 
1159
 
 
1160
 
 
1161
    <span class="py-src-comment"># ---- this is equivalent to addBoth(doThisNoMatterWhat)</span>
 
1162
 
 
1163
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>):
 
1164
        <span class="py-src-keyword">try</span>:
 
1165
            <span class="py-src-variable">result</span> = <span class="py-src-variable">doThisNoMatterWhat</span>(<span class="py-src-variable">result</span>)
 
1166
        <span class="py-src-keyword">except</span>:
 
1167
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1168
    <span class="py-src-keyword">else</span>:
 
1169
        <span class="py-src-keyword">try</span>:
 
1170
            <span class="py-src-variable">result</span> = <span class="py-src-variable">doThisNoMatterWhat</span>(<span class="py-src-variable">result</span>)
 
1171
        <span class="py-src-keyword">except</span>:
 
1172
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1173
 
 
1174
 
 
1175
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1176
        <span class="py-src-keyword">pass</span>
 
1177
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1178
        <span class="py-src-keyword">try</span>:
 
1179
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleFailure</span>(<span class="py-src-variable">result</span>)
 
1180
        <span class="py-src-keyword">except</span>:
 
1181
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1182
 
 
1183
 
 
1184
<span class="py-src-keyword">def</span> <span class="py-src-identifier">deferredExample</span>():
 
1185
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
 
1186
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>)
 
1187
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">failAtHandlingResult</span>)
 
1188
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addBoth</span>(<span class="py-src-variable">doThisNoMatterWhat</span>)
 
1189
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">handleFailure</span>)
 
1190
 
 
1191
    <span class="py-src-variable">d</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
1192
 
 
1193
 
 
1194
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
 
1195
    <span class="py-src-variable">behindTheScenes</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
1196
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
 
1197
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
1198
    <span class="py-src-variable">deferredExample</span>()
 
1199
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex4.py"><span class="filename">listings/deferred/deferred_ex4.py</span></a></div></div>
 
1200
 
 
1201
<pre xml:space="preserve">
 
1202
callback 1
 
1203
        got result: success
 
1204
callback 2
 
1205
        got result: yay! handleResult was successful!
 
1206
        about to raise exception
 
1207
both 3
 
1208
        got argument &lt;twisted.python.failure.Failure exceptions.RuntimeError&gt;
 
1209
        doing something very important
 
1210
errback
 
1211
we got an exception: Traceback (most recent call last):
 
1212
--- &lt;exception caught here&gt; ---
 
1213
  File &quot;/home/slyphon/Projects/Twisted/trunk/twisted/internet/defer.py&quot;, line
 
1214
326, in _runCallbacks
 
1215
    self.result = callback(self.result, *args, **kw)
 
1216
  File &quot;./deferred_ex4.py&quot;, line 32, in failAtHandlingResult
 
1217
    raise RuntimeError, &quot;whoops! we encountered an error&quot;
 
1218
exceptions.RuntimeError: whoops! we encountered an error
 
1219
</pre>
 
1220
 
 
1221
<p>You can see that the errback is called, (and consequently, the failure is
 
1222
trapped).  This is because doThisNoMatterWhat method returned the value it
 
1223
received, a failure.</p>
 
1224
 
 
1225
<h2>addCallbacks: decision making based on previous success or failure<a name="auto8"/></h2>
 
1226
 
 
1227
<p>As we've been seeing in the examples, the callback is a pair of
 
1228
callback/errback.  Using addCallback or addErrback is actually a special case
 
1229
where one of the pair is a pass statement. If you want to make a decision
 
1230
based on whether or not the previous result in the chain was a failure or not
 
1231
(which is very rare, but included here for completeness), you use
 
1232
addCallbacks. Note that this is <strong>not</strong> the same thing as an
 
1233
addCallback followed by an addErrback.</p>
 
1234
 
 
1235
 
 
1236
<div class="py-listing"><pre><p class="py-linenumber">  1
 
1237
  2
 
1238
  3
 
1239
  4
 
1240
  5
 
1241
  6
 
1242
  7
 
1243
  8
 
1244
  9
 
1245
 10
 
1246
 11
 
1247
 12
 
1248
 13
 
1249
 14
 
1250
 15
 
1251
 16
 
1252
 17
 
1253
 18
 
1254
 19
 
1255
 20
 
1256
 21
 
1257
 22
 
1258
 23
 
1259
 24
 
1260
 25
 
1261
 26
 
1262
 27
 
1263
 28
 
1264
 29
 
1265
 30
 
1266
 31
 
1267
 32
 
1268
 33
 
1269
 34
 
1270
 35
 
1271
 36
 
1272
 37
 
1273
 38
 
1274
 39
 
1275
 40
 
1276
 41
 
1277
 42
 
1278
 43
 
1279
 44
 
1280
 45
 
1281
 46
 
1282
 47
 
1283
 48
 
1284
 49
 
1285
 50
 
1286
 51
 
1287
 52
 
1288
 53
 
1289
 54
 
1290
 55
 
1291
 56
 
1292
 57
 
1293
 58
 
1294
 59
 
1295
 60
 
1296
 61
 
1297
 62
 
1298
 63
 
1299
 64
 
1300
 65
 
1301
 66
 
1302
 67
 
1303
 68
 
1304
 69
 
1305
 70
 
1306
 71
 
1307
 72
 
1308
 73
 
1309
 74
 
1310
 75
 
1311
 76
 
1312
 77
 
1313
 78
 
1314
 79
 
1315
 80
 
1316
 81
 
1317
 82
 
1318
 83
 
1319
 84
 
1320
 85
 
1321
 86
 
1322
 87
 
1323
 88
 
1324
 89
 
1325
 90
 
1326
 91
 
1327
 92
 
1328
 93
 
1329
 94
 
1330
 95
 
1331
 96
 
1332
 97
 
1333
 98
 
1334
 99
 
1335
100
 
1336
101
 
1337
102
 
1338
103
 
1339
104
 
1340
105
 
1341
106
 
1342
107
 
1343
108
 
1344
109
 
1345
110
 
1346
111
 
1347
112
 
1348
113
 
1349
114
 
1350
115
 
1351
116
 
1352
117
 
1353
118
 
1354
119
 
1355
120
 
1356
121
 
1357
122
 
1358
123
 
1359
124
 
1360
125
 
1361
126
 
1362
127
 
1363
128
 
1364
129
 
1365
130
 
1366
131
 
1367
132
 
1368
133
 
1369
134
 
1370
135
 
1371
136
 
1372
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
1373
 
 
1374
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
1375
<span class="py-src-comment"># See LICENSE for details.</span>
 
1376
 
 
1377
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
 
1378
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">failure</span>, <span class="py-src-variable">util</span>
 
1379
 
 
1380
<span class="py-src-string">&quot;&quot;&quot;
 
1381
Now comes the more nuanced addCallbacks, which allows us to make a
 
1382
yes/no (branching) decision based on whether the result at a given point is
 
1383
a failure or not.
 
1384
&quot;&quot;&quot;</span>
 
1385
 
 
1386
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
 
1387
    <span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
1388
 
 
1389
 
 
1390
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleFailure</span>(<span class="py-src-parameter">f</span>):
 
1391
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;errback&quot;</span>
 
1392
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;we got an exception: %s&quot;</span> % (<span class="py-src-variable">f</span>.<span class="py-src-variable">getTraceback</span>(),)
 
1393
    <span class="py-src-variable">f</span>.<span class="py-src-variable">trap</span>(<span class="py-src-variable">RuntimeError</span>)
 
1394
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;okay, continue on&quot;</span>
 
1395
 
 
1396
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleResult</span>(<span class="py-src-parameter">result</span>):
 
1397
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
1398
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
1399
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
1400
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;yay! handleResult was successful!&quot;</span>
 
1401
 
 
1402
<span class="py-src-keyword">def</span> <span class="py-src-identifier">failAtHandlingResult</span>(<span class="py-src-parameter">result</span>):
 
1403
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
1404
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
1405
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
1406
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tabout to raise exception&quot;</span>
 
1407
    <span class="py-src-keyword">raise</span> <span class="py-src-variable">RuntimeError</span>, <span class="py-src-string">&quot;whoops! we encountered an error&quot;</span>
 
1408
 
 
1409
<span class="py-src-keyword">def</span> <span class="py-src-identifier">yesDecision</span>(<span class="py-src-parameter">result</span>):
 
1410
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
1411
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;yes decision %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
1412
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\twasn't a failure, so we can plow ahead&quot;</span>
 
1413
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;go ahead!&quot;</span>
 
1414
 
 
1415
<span class="py-src-keyword">def</span> <span class="py-src-identifier">noDecision</span>(<span class="py-src-parameter">result</span>):
 
1416
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
1417
    <span class="py-src-variable">result</span>.<span class="py-src-variable">trap</span>(<span class="py-src-variable">RuntimeError</span>)
 
1418
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;no decision %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
1419
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\t*doh*! a failure! quick! damage control!&quot;</span>
 
1420
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;damage control successful!&quot;</span>
 
1421
 
 
1422
 
 
1423
 
 
1424
<span class="py-src-keyword">def</span> <span class="py-src-identifier">behindTheScenes</span>(<span class="py-src-parameter">result</span>):
 
1425
 
 
1426
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1427
        <span class="py-src-keyword">try</span>:
 
1428
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failAtHandlingResult</span>(<span class="py-src-variable">result</span>)
 
1429
        <span class="py-src-keyword">except</span>:
 
1430
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1431
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1432
        <span class="py-src-keyword">pass</span>
 
1433
 
 
1434
 
 
1435
    <span class="py-src-comment"># this is equivalent to addCallbacks(yesDecision, noDecision)</span>
 
1436
 
 
1437
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1438
        <span class="py-src-keyword">try</span>:
 
1439
            <span class="py-src-variable">result</span> = <span class="py-src-variable">yesDecision</span>(<span class="py-src-variable">result</span>)
 
1440
        <span class="py-src-keyword">except</span>:
 
1441
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1442
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1443
        <span class="py-src-keyword">try</span>:
 
1444
            <span class="py-src-variable">result</span> = <span class="py-src-variable">noDecision</span>(<span class="py-src-variable">result</span>)
 
1445
        <span class="py-src-keyword">except</span>:
 
1446
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1447
 
 
1448
 
 
1449
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1450
        <span class="py-src-keyword">try</span>:
 
1451
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleResult</span>(<span class="py-src-variable">result</span>)
 
1452
        <span class="py-src-keyword">except</span>:
 
1453
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1454
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1455
        <span class="py-src-keyword">pass</span>
 
1456
 
 
1457
 
 
1458
    <span class="py-src-comment"># this is equivalent to addCallbacks(yesDecision, noDecision)</span>
 
1459
 
 
1460
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1461
        <span class="py-src-keyword">try</span>:
 
1462
            <span class="py-src-variable">result</span> = <span class="py-src-variable">yesDecision</span>(<span class="py-src-variable">result</span>)
 
1463
        <span class="py-src-keyword">except</span>:
 
1464
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1465
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1466
        <span class="py-src-keyword">try</span>:
 
1467
            <span class="py-src-variable">result</span> = <span class="py-src-variable">noDecision</span>(<span class="py-src-variable">result</span>)
 
1468
        <span class="py-src-keyword">except</span>:
 
1469
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1470
 
 
1471
 
 
1472
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1473
        <span class="py-src-keyword">try</span>:
 
1474
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleResult</span>(<span class="py-src-variable">result</span>)
 
1475
        <span class="py-src-keyword">except</span>:
 
1476
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1477
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1478
        <span class="py-src-keyword">pass</span>
 
1479
 
 
1480
 
 
1481
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1482
        <span class="py-src-keyword">pass</span>
 
1483
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1484
        <span class="py-src-keyword">try</span>:
 
1485
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleFailure</span>(<span class="py-src-variable">result</span>)
 
1486
        <span class="py-src-keyword">except</span>:
 
1487
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1488
 
 
1489
 
 
1490
<span class="py-src-keyword">def</span> <span class="py-src-identifier">deferredExample</span>():
 
1491
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
 
1492
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">failAtHandlingResult</span>)
 
1493
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallbacks</span>(<span class="py-src-variable">yesDecision</span>, <span class="py-src-variable">noDecision</span>) <span class="py-src-comment"># noDecision will be called</span>
 
1494
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>) <span class="py-src-comment"># - A -</span>
 
1495
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallbacks</span>(<span class="py-src-variable">yesDecision</span>, <span class="py-src-variable">noDecision</span>) <span class="py-src-comment"># yesDecision will be called</span>
 
1496
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>)
 
1497
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">handleFailure</span>)
 
1498
 
 
1499
    <span class="py-src-variable">d</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
1500
 
 
1501
 
 
1502
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
 
1503
    <span class="py-src-variable">behindTheScenes</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
1504
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
 
1505
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
1506
    <span class="py-src-variable">deferredExample</span>()
 
1507
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex5.py"><span class="filename">listings/deferred/deferred_ex5.py</span></a></div></div>
 
1508
 
 
1509
<pre xml:space="preserve">
 
1510
callback 1
 
1511
        got result: success
 
1512
        about to raise exception
 
1513
no decision 2
 
1514
        *doh*! a failure! quick! damage control!
 
1515
callback 3
 
1516
        got result: damage control successful!
 
1517
yes decision 4
 
1518
        wasn't a failure, so we can plow ahead
 
1519
callback 5
 
1520
        got result: go ahead!
 
1521
</pre>
 
1522
 
 
1523
<p>Notice that our errback is never called. The noDecision method returns a
 
1524
non-failure so processing continues with the next callback. If we wanted to
 
1525
skip the callback at &quot;- A -&quot; because of the error, but do some kind of
 
1526
processing in response to the error, we would have used a passthru, and
 
1527
returned the failure we received, as we see in this next example: </p>
 
1528
 
 
1529
<div class="py-listing"><pre><p class="py-linenumber">  1
 
1530
  2
 
1531
  3
 
1532
  4
 
1533
  5
 
1534
  6
 
1535
  7
 
1536
  8
 
1537
  9
 
1538
 10
 
1539
 11
 
1540
 12
 
1541
 13
 
1542
 14
 
1543
 15
 
1544
 16
 
1545
 17
 
1546
 18
 
1547
 19
 
1548
 20
 
1549
 21
 
1550
 22
 
1551
 23
 
1552
 24
 
1553
 25
 
1554
 26
 
1555
 27
 
1556
 28
 
1557
 29
 
1558
 30
 
1559
 31
 
1560
 32
 
1561
 33
 
1562
 34
 
1563
 35
 
1564
 36
 
1565
 37
 
1566
 38
 
1567
 39
 
1568
 40
 
1569
 41
 
1570
 42
 
1571
 43
 
1572
 44
 
1573
 45
 
1574
 46
 
1575
 47
 
1576
 48
 
1577
 49
 
1578
 50
 
1579
 51
 
1580
 52
 
1581
 53
 
1582
 54
 
1583
 55
 
1584
 56
 
1585
 57
 
1586
 58
 
1587
 59
 
1588
 60
 
1589
 61
 
1590
 62
 
1591
 63
 
1592
 64
 
1593
 65
 
1594
 66
 
1595
 67
 
1596
 68
 
1597
 69
 
1598
 70
 
1599
 71
 
1600
 72
 
1601
 73
 
1602
 74
 
1603
 75
 
1604
 76
 
1605
 77
 
1606
 78
 
1607
 79
 
1608
 80
 
1609
 81
 
1610
 82
 
1611
 83
 
1612
 84
 
1613
 85
 
1614
 86
 
1615
 87
 
1616
 88
 
1617
 89
 
1618
 90
 
1619
 91
 
1620
 92
 
1621
 93
 
1622
 94
 
1623
 95
 
1624
 96
 
1625
 97
 
1626
 98
 
1627
 99
 
1628
100
 
1629
101
 
1630
102
 
1631
103
 
1632
104
 
1633
105
 
1634
106
 
1635
107
 
1636
108
 
1637
109
 
1638
110
 
1639
111
 
1640
112
 
1641
113
 
1642
114
 
1643
115
 
1644
116
 
1645
117
 
1646
118
 
1647
119
 
1648
120
 
1649
121
 
1650
122
 
1651
123
 
1652
124
 
1653
125
 
1654
126
 
1655
127
 
1656
128
 
1657
129
 
1658
130
 
1659
131
 
1660
132
 
1661
133
 
1662
134
 
1663
135
 
1664
136
 
1665
137
 
1666
138
 
1667
139
 
1668
140
 
1669
141
 
1670
142
 
1671
143
 
1672
144
 
1673
145
 
1674
146
 
1675
147
 
1676
148
 
1677
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
1678
 
 
1679
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
1680
<span class="py-src-comment"># See LICENSE for details.</span>
 
1681
 
 
1682
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
 
1683
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">failure</span>, <span class="py-src-variable">util</span>
 
1684
 
 
1685
<span class="py-src-string">&quot;&quot;&quot;
 
1686
Now comes the more nuanced addCallbacks, which allows us to make a
 
1687
yes/no (branching) decision based on whether the result at a given point is
 
1688
a failure or not.
 
1689
 
 
1690
here, we return the failure from noDecisionPassthru, the errback argument to
 
1691
the first addCallbacks method invocation, and see what happens.
 
1692
&quot;&quot;&quot;</span>
 
1693
 
 
1694
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
 
1695
    <span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
1696
 
 
1697
 
 
1698
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleFailure</span>(<span class="py-src-parameter">f</span>):
 
1699
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;errback&quot;</span>
 
1700
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;we got an exception: %s&quot;</span> % (<span class="py-src-variable">f</span>.<span class="py-src-variable">getTraceback</span>(),)
 
1701
    <span class="py-src-variable">f</span>.<span class="py-src-variable">trap</span>(<span class="py-src-variable">RuntimeError</span>)
 
1702
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;okay, continue on&quot;</span>
 
1703
 
 
1704
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleResult</span>(<span class="py-src-parameter">result</span>):
 
1705
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
1706
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
1707
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
1708
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;yay! handleResult was successful!&quot;</span>
 
1709
 
 
1710
<span class="py-src-keyword">def</span> <span class="py-src-identifier">failAtHandlingResult</span>(<span class="py-src-parameter">result</span>):
 
1711
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
1712
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
1713
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
1714
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tabout to raise exception&quot;</span>
 
1715
    <span class="py-src-keyword">raise</span> <span class="py-src-variable">RuntimeError</span>, <span class="py-src-string">&quot;whoops! we encountered an error&quot;</span>
 
1716
 
 
1717
<span class="py-src-keyword">def</span> <span class="py-src-identifier">yesDecision</span>(<span class="py-src-parameter">result</span>):
 
1718
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
1719
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;yes decision %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
1720
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\twasn't a failure, so we can plow ahead&quot;</span>
 
1721
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;go ahead!&quot;</span>
 
1722
 
 
1723
<span class="py-src-keyword">def</span> <span class="py-src-identifier">noDecision</span>(<span class="py-src-parameter">result</span>):
 
1724
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
1725
    <span class="py-src-variable">result</span>.<span class="py-src-variable">trap</span>(<span class="py-src-variable">RuntimeError</span>)
 
1726
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;no decision %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
1727
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\t*doh*! a failure! quick! damage control!&quot;</span>
 
1728
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;damage control successful!&quot;</span>
 
1729
 
 
1730
<span class="py-src-keyword">def</span> <span class="py-src-identifier">noDecisionPassthru</span>(<span class="py-src-parameter">result</span>):
 
1731
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
1732
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;no decision %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
1733
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\t*doh*! a failure! don't know what to do, returning failure!&quot;</span>
 
1734
    <span class="py-src-keyword">return</span> <span class="py-src-variable">result</span>
 
1735
 
 
1736
 
 
1737
<span class="py-src-keyword">def</span> <span class="py-src-identifier">behindTheScenes</span>(<span class="py-src-parameter">result</span>):
 
1738
 
 
1739
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1740
        <span class="py-src-keyword">try</span>:
 
1741
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failAtHandlingResult</span>(<span class="py-src-variable">result</span>)
 
1742
        <span class="py-src-keyword">except</span>:
 
1743
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1744
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1745
        <span class="py-src-keyword">pass</span>
 
1746
 
 
1747
 
 
1748
    <span class="py-src-comment"># this is equivalent to addCallbacks(yesDecision, noDecision)</span>
 
1749
 
 
1750
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1751
        <span class="py-src-keyword">try</span>:
 
1752
            <span class="py-src-variable">result</span> = <span class="py-src-variable">yesDecision</span>(<span class="py-src-variable">result</span>)
 
1753
        <span class="py-src-keyword">except</span>:
 
1754
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1755
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1756
        <span class="py-src-keyword">try</span>:
 
1757
            <span class="py-src-variable">result</span> = <span class="py-src-variable">noDecisionPassthru</span>(<span class="py-src-variable">result</span>)
 
1758
        <span class="py-src-keyword">except</span>:
 
1759
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1760
 
 
1761
 
 
1762
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1763
        <span class="py-src-keyword">try</span>:
 
1764
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleResult</span>(<span class="py-src-variable">result</span>)
 
1765
        <span class="py-src-keyword">except</span>:
 
1766
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1767
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1768
        <span class="py-src-keyword">pass</span>
 
1769
 
 
1770
 
 
1771
    <span class="py-src-comment"># this is equivalent to addCallbacks(yesDecision, noDecision)</span>
 
1772
 
 
1773
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1774
        <span class="py-src-keyword">try</span>:
 
1775
            <span class="py-src-variable">result</span> = <span class="py-src-variable">yesDecision</span>(<span class="py-src-variable">result</span>)
 
1776
        <span class="py-src-keyword">except</span>:
 
1777
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1778
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1779
        <span class="py-src-keyword">try</span>:
 
1780
            <span class="py-src-variable">result</span> = <span class="py-src-variable">noDecision</span>(<span class="py-src-variable">result</span>)
 
1781
        <span class="py-src-keyword">except</span>:
 
1782
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1783
 
 
1784
 
 
1785
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1786
        <span class="py-src-keyword">try</span>:
 
1787
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleResult</span>(<span class="py-src-variable">result</span>)
 
1788
        <span class="py-src-keyword">except</span>:
 
1789
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1790
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1791
        <span class="py-src-keyword">pass</span>
 
1792
 
 
1793
 
 
1794
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
 
1795
        <span class="py-src-keyword">pass</span>
 
1796
    <span class="py-src-keyword">else</span>:                                       <span class="py-src-comment"># ---- errback</span>
 
1797
        <span class="py-src-keyword">try</span>:
 
1798
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleFailure</span>(<span class="py-src-variable">result</span>)
 
1799
        <span class="py-src-keyword">except</span>:
 
1800
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>()
 
1801
 
 
1802
 
 
1803
<span class="py-src-keyword">def</span> <span class="py-src-identifier">deferredExample</span>():
 
1804
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
 
1805
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">failAtHandlingResult</span>)
 
1806
 
 
1807
    <span class="py-src-comment"># noDecisionPassthru will be called</span>
 
1808
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallbacks</span>(<span class="py-src-variable">yesDecision</span>, <span class="py-src-variable">noDecisionPassthru</span>)
 
1809
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>) <span class="py-src-comment"># - A -</span>
 
1810
 
 
1811
    <span class="py-src-comment"># noDecision will be called</span>
 
1812
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallbacks</span>(<span class="py-src-variable">yesDecision</span>, <span class="py-src-variable">noDecision</span>)
 
1813
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>) <span class="py-src-comment"># - B -</span>
 
1814
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">handleFailure</span>)
 
1815
 
 
1816
    <span class="py-src-variable">d</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
1817
 
 
1818
 
 
1819
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
 
1820
    <span class="py-src-variable">behindTheScenes</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
1821
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
 
1822
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
1823
    <span class="py-src-variable">deferredExample</span>()
 
1824
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex6.py"><span class="filename">listings/deferred/deferred_ex6.py</span></a></div></div>
 
1825
 
 
1826
<pre xml:space="preserve">
 
1827
callback 1
 
1828
        got result: success
 
1829
        about to raise exception
 
1830
no decision 2
 
1831
        *doh*! a failure! don't know what to do, returning failure!
 
1832
no decision 3
 
1833
        *doh*! a failure! quick! damage control!
 
1834
callback 4
 
1835
        got result: damage control successful!
 
1836
</pre>
 
1837
 
 
1838
<p>Two things to note here. First, &quot;- A -&quot; was skipped, like we wanted it to,
 
1839
and the second thing is that after &quot;- A -&quot;, noDecision is called, because
 
1840
<strong>it is the next errback that exists in the chain</strong>. It returns a
 
1841
non-failure, so processing continues with the next callback at &quot;- B -&quot;, and
 
1842
the errback at the end of the chain is never called </p>
 
1843
 
 
1844
<h2>Hints, tips, common mistakes, and miscellaney<a name="auto9"/></h2>
 
1845
 
 
1846
<h3>The deferred callback chain is stateful<a name="auto10"/></h3>
 
1847
 
 
1848
<p>A deferred that has been called back will call its addCallback and
 
1849
addErrback methods as appropriate in the order they are added, when they are
 
1850
added. So we see in the following example, deferredExample1 and
 
1851
deferredExample2 are equivalent. The first sets up the processing chain
 
1852
beforehand and then executes it, the other executes the chain as it is being
 
1853
constructed.  This is because deferreds are <em>stateful</em>.  </p>
 
1854
 
 
1855
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
1856
 2
 
1857
 3
 
1858
 4
 
1859
 5
 
1860
 6
 
1861
 7
 
1862
 8
 
1863
 9
 
1864
10
 
1865
11
 
1866
12
 
1867
13
 
1868
14
 
1869
15
 
1870
16
 
1871
17
 
1872
18
 
1873
19
 
1874
20
 
1875
21
 
1876
22
 
1877
23
 
1878
24
 
1879
25
 
1880
26
 
1881
27
 
1882
28
 
1883
29
 
1884
30
 
1885
31
 
1886
32
 
1887
33
 
1888
34
 
1889
35
 
1890
36
 
1891
37
 
1892
38
 
1893
39
 
1894
40
 
1895
41
 
1896
42
 
1897
43
 
1898
44
 
1899
45
 
1900
46
 
1901
47
 
1902
48
 
1903
49
 
1904
50
 
1905
51
 
1906
52
 
1907
53
 
1908
54
 
1909
55
 
1910
56
 
1911
57
 
1912
58
 
1913
59
 
1914
60
 
1915
61
 
1916
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
1917
 
 
1918
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
1919
<span class="py-src-comment"># See LICENSE for details.</span>
 
1920
 
 
1921
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
 
1922
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">failure</span>, <span class="py-src-variable">util</span>
 
1923
 
 
1924
<span class="py-src-string">&quot;&quot;&quot;
 
1925
The deferred callback chain is stateful, and can be executed before
 
1926
or after all callbacks have been added to the chain
 
1927
&quot;&quot;&quot;</span>
 
1928
 
 
1929
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
 
1930
    <span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
1931
 
 
1932
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleFailure</span>(<span class="py-src-parameter">f</span>):
 
1933
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;errback&quot;</span>
 
1934
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;we got an exception: %s&quot;</span> % (<span class="py-src-variable">f</span>.<span class="py-src-variable">getTraceback</span>(),)
 
1935
    <span class="py-src-variable">f</span>.<span class="py-src-variable">trap</span>(<span class="py-src-variable">RuntimeError</span>)
 
1936
 
 
1937
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleResult</span>(<span class="py-src-parameter">result</span>):
 
1938
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
1939
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
1940
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
1941
    <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;yay! handleResult was successful!&quot;</span>
 
1942
 
 
1943
<span class="py-src-keyword">def</span> <span class="py-src-identifier">failAtHandlingResult</span>(<span class="py-src-parameter">result</span>):
 
1944
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
1945
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
1946
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
1947
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tabout to raise exception&quot;</span>
 
1948
    <span class="py-src-keyword">raise</span> <span class="py-src-variable">RuntimeError</span>, <span class="py-src-string">&quot;whoops! we encountered an error&quot;</span>
 
1949
 
 
1950
<span class="py-src-keyword">def</span> <span class="py-src-identifier">deferredExample1</span>():
 
1951
    <span class="py-src-comment"># this is another common idiom, since all add* methods</span>
 
1952
    <span class="py-src-comment"># return the deferred instance, you can just chain your</span>
 
1953
    <span class="py-src-comment"># calls to addCallback and addErrback</span>
 
1954
 
 
1955
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>().<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">failAtHandlingResult</span>
 
1956
                       ).<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>
 
1957
                       ).<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">handleFailure</span>)
 
1958
 
 
1959
    <span class="py-src-variable">d</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
1960
 
 
1961
<span class="py-src-keyword">def</span> <span class="py-src-identifier">deferredExample2</span>():
 
1962
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
 
1963
 
 
1964
    <span class="py-src-variable">d</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">&quot;success&quot;</span>)
 
1965
 
 
1966
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">failAtHandlingResult</span>)
 
1967
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>)
 
1968
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">handleFailure</span>)
 
1969
 
 
1970
 
 
1971
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
 
1972
    <span class="py-src-variable">deferredExample1</span>()
 
1973
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
 
1974
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
1975
    <span class="py-src-variable">deferredExample2</span>()
 
1976
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex7.py"><span class="filename">listings/deferred/deferred_ex7.py</span></a></div></div>
 
1977
 
 
1978
<pre xml:space="preserve">
 
1979
callback 1
 
1980
        got result: success
 
1981
        about to raise exception
 
1982
errback
 
1983
we got an exception: Traceback (most recent call last):
 
1984
--- &lt;exception caught here&gt; ---
 
1985
  File &quot;/home/slyphon/Projects/Twisted/trunk/twisted/internet/defer.py&quot;, line
 
1986
326, in _runCallbacks
 
1987
    self.result = callback(self.result, *args, **kw)
 
1988
  File &quot;./deferred_ex7.py&quot;, line 35, in failAtHandlingResult
 
1989
    raise RuntimeError, &quot;whoops! we encountered an error&quot;
 
1990
exceptions.RuntimeError: whoops! we encountered an error
 
1991
 
 
1992
 
 
1993
-------------------------------------------------
 
1994
 
 
1995
callback 1
 
1996
        got result: success
 
1997
        about to raise exception
 
1998
errback
 
1999
we got an exception: Traceback (most recent call last):
 
2000
--- &lt;exception caught here&gt; ---
 
2001
  File &quot;/home/slyphon/Projects/Twisted/trunk/twisted/internet/defer.py&quot;, line
 
2002
326, in _runCallbacks
 
2003
    self.result = callback(self.result, *args, **kw)
 
2004
  File &quot;./deferred_ex7.py&quot;, line 35, in failAtHandlingResult
 
2005
    raise RuntimeError, &quot;whoops! we encountered an error&quot;
 
2006
exceptions.RuntimeError: whoops! we encountered an error
 
2007
</pre>
 
2008
 
 
2009
<p>This example also shows you the common idiom of chaining calls to
 
2010
addCallback and addErrback.
 
2011
</p>
 
2012
 
 
2013
<h3>Don't call .callback() on deferreds you didn't create!<a name="auto11"/></h3>
 
2014
 
 
2015
<p>It is an error to reinvoke deferreds callback or errback method, therefore
 
2016
if you didn't create a deferred, <strong>do not under any
 
2017
circumstances</strong> call its callback or errback.  doing so will raise
 
2018
an exception </p>
 
2019
 
 
2020
<h3>Callbacks can return deferreds<a name="auto12"/></h3>
 
2021
 
 
2022
<p>If you need to call a method that returns a deferred within your callback
 
2023
chain, just return that deferred, and the result of the secondary deferred's
 
2024
processing chain will become the result that gets passed to the next callback
 
2025
of the primary deferreds processing chain </p>
 
2026
 
 
2027
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
2028
 2
 
2029
 3
 
2030
 4
 
2031
 5
 
2032
 6
 
2033
 7
 
2034
 8
 
2035
 9
 
2036
10
 
2037
11
 
2038
12
 
2039
13
 
2040
14
 
2041
15
 
2042
16
 
2043
17
 
2044
18
 
2045
19
 
2046
20
 
2047
21
 
2048
22
 
2049
23
 
2050
24
 
2051
25
 
2052
26
 
2053
27
 
2054
28
 
2055
29
 
2056
30
 
2057
31
 
2058
32
 
2059
33
 
2060
34
 
2061
35
 
2062
36
 
2063
37
 
2064
38
 
2065
39
 
2066
40
 
2067
41
 
2068
42
 
2069
43
 
2070
44
 
2071
45
 
2072
46
 
2073
47
 
2074
48
 
2075
49
 
2076
50
 
2077
51
 
2078
52
 
2079
53
 
2080
54
 
2081
55
 
2082
56
 
2083
57
 
2084
58
 
2085
59
 
2086
60
 
2087
61
 
2088
62
 
2089
63
 
2090
64
 
2091
65
 
2092
66
 
2093
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
2094
 
 
2095
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
2096
<span class="py-src-comment"># See LICENSE for details.</span>
 
2097
 
 
2098
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
 
2099
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">failure</span>, <span class="py-src-variable">util</span>
 
2100
 
 
2101
 
 
2102
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
 
2103
    <span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
 
2104
    <span class="py-src-variable">let</span> = <span class="py-src-string">'a'</span>
 
2105
 
 
2106
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">incrLet</span>(<span class="py-src-parameter">cls</span>):
 
2107
        <span class="py-src-variable">cls</span>.<span class="py-src-variable">let</span> = <span class="py-src-variable">chr</span>(<span class="py-src-variable">ord</span>(<span class="py-src-variable">cls</span>.<span class="py-src-variable">let</span>) + <span class="py-src-number">1</span>)
 
2108
    <span class="py-src-variable">incrLet</span> = <span class="py-src-variable">classmethod</span>(<span class="py-src-variable">incrLet</span>)
 
2109
 
 
2110
 
 
2111
<span class="py-src-keyword">def</span> <span class="py-src-identifier">handleFailure</span>(<span class="py-src-parameter">f</span>):
 
2112
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;errback&quot;</span>
 
2113
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;we got an exception: %s&quot;</span> % (<span class="py-src-variable">f</span>.<span class="py-src-variable">getTraceback</span>(),)
 
2114
    <span class="py-src-keyword">return</span> <span class="py-src-variable">f</span>
 
2115
 
 
2116
<span class="py-src-keyword">def</span> <span class="py-src-identifier">subCb_B</span>(<span class="py-src-parameter">result</span>):
 
2117
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;sub-callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">let</span>,)
 
2118
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">incrLet</span>()
 
2119
    <span class="py-src-variable">s</span> = <span class="py-src-string">&quot; beautiful!&quot;</span>
 
2120
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tadding %r to result&quot;</span> % (<span class="py-src-variable">s</span>,)
 
2121
    <span class="py-src-variable">result</span> += <span class="py-src-variable">s</span>
 
2122
    <span class="py-src-keyword">return</span> <span class="py-src-variable">result</span>
 
2123
 
 
2124
<span class="py-src-keyword">def</span> <span class="py-src-identifier">subCb_A</span>(<span class="py-src-parameter">result</span>):
 
2125
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;sub-callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">let</span>,)
 
2126
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">incrLet</span>()
 
2127
    <span class="py-src-variable">s</span> = <span class="py-src-string">&quot; are &quot;</span>
 
2128
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tadding %r to result&quot;</span> % (<span class="py-src-variable">s</span>,)
 
2129
    <span class="py-src-variable">result</span> += <span class="py-src-variable">s</span>
 
2130
    <span class="py-src-keyword">return</span> <span class="py-src-variable">result</span>
 
2131
 
 
2132
<span class="py-src-keyword">def</span> <span class="py-src-identifier">mainCb_1</span>(<span class="py-src-parameter">result</span>):
 
2133
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
2134
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
2135
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
2136
    <span class="py-src-variable">result</span> += <span class="py-src-string">&quot; Deferreds &quot;</span>
 
2137
 
 
2138
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>().<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">subCb_A</span>
 
2139
                       ).<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">subCb_B</span>)
 
2140
    <span class="py-src-variable">d</span>.<span class="py-src-variable">callback</span>(<span class="py-src-variable">result</span>)
 
2141
    <span class="py-src-keyword">return</span> <span class="py-src-variable">d</span>
 
2142
 
 
2143
<span class="py-src-keyword">def</span> <span class="py-src-identifier">mainCb_2</span>(<span class="py-src-parameter">result</span>):
 
2144
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> += <span class="py-src-number">1</span>
 
2145
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;callback %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
 
2146
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot result: %s&quot;</span> % (<span class="py-src-variable">result</span>,)
 
2147
 
 
2148
 
 
2149
<span class="py-src-keyword">def</span> <span class="py-src-identifier">deferredExample</span>():
 
2150
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>().<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">mainCb_1</span>
 
2151
                       ).<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">mainCb_2</span>)
 
2152
 
 
2153
    <span class="py-src-variable">d</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">&quot;I hope you'll agree: &quot;</span>)
 
2154
 
 
2155
 
 
2156
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
 
2157
    <span class="py-src-variable">deferredExample</span>()
 
2158
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex8.py"><span class="filename">listings/deferred/deferred_ex8.py</span></a></div></div>
 
2159
 
 
2160
<pre xml:space="preserve">
 
2161
callback 1
 
2162
        got result: I hope you'll agree: 
 
2163
sub-callback a
 
2164
        adding ' are ' to result
 
2165
sub-callback b
 
2166
        adding ' beautiful!' to result
 
2167
callback 2
 
2168
        got result: I hope you'll agree:  Deferreds  are  beautiful!
 
2169
</pre>
 
2170
 
 
2171
<h2>Conclusion<a name="auto13"/></h2>
 
2172
 
 
2173
<p>Deferreds can be confusing, but only because they're so elegant and simple.
 
2174
There is a lot of logical power that can expressed with a deferred's
 
2175
processing chain, and once you see what's going on behind the curtain, it's a
 
2176
lot easier to understand how to make use of what deferreds have to offer.</p>
 
2177
 
 
2178
</div>
 
2179
 
 
2180
    <p><a href="index.html">Index</a></p>
 
2181
    <span class="version">Version: 10.0.0</span>
 
2182
  </body>
 
2183
</html>
 
 
b'\\ No newline at end of file'