1
2
3
4
5
6
7
8
9
10
11
12
13
14 __doc__='''Driver.py
15
16 Run generators that produce Deferreds.
17
18 twisted.flow has something like this, except I cannot understand it.
19
20 $Id$
21 '''
22
23 __version__ = "$Revision$"[11:-2]
24
25
26 from twisted.internet import defer, reactor
27 from twisted.python import failure
28
32
34 "Walk an iterable that returns a deferred."
35
39
40 - def drive(self, iterable):
41 "Call the iterable and set up callbacks to finish"
42 self.iter = iterable
43 self._next()
44 return self.defer
45
57
59 "Provide the result of the iterable as a value or exception"
60 ex = self.result
61 if isinstance(self.result, failure.Failure):
62 ex = self.result.value
63 if isinstance(ex, Exception):
64 raise ex
65 return self.result
66 next = result
67
70
76
78 '''Typical use of Driver class:
79
80 def walk(driver):
81 yield thing1()
82 a = driver.next()
83 print "Thing 1 is",
84 yield thing2()
85 b = driver.next()
86 print "Thing 2 is",
87 driver.finish(a + b)
88
89 drive(walk)
90
91 '''
92 d = Driver()
93 return d.drive(callable(d))
94
95
97 "Drive the callable at a later time"
98 d = defer.Deferred()
99 def driveAgain():
100 drive(callable).chainDeferred(d)
101 reactor.callLater(secs, driveAgain)
102 return d
103
104
106 lst = []
107 def loop(d):
108 for i in range(10):
109 yield defer.succeed(i)
110 lst.append(d.next())
111 def final(v):
112 assert lst[-1] == v
113 assert lst == range(10)
114 def unloop(d):
115 yield defer.fail(ZeroDivisionError('hahaha'))
116 d.next()
117 def checkError(err):
118 assert isinstance(err.value, ZeroDivisionError)
119 reactor.stop()
120 drive(unloop).addErrback(checkError)
121 drive(loop).addCallback(final)
122
123
124 if __name__ == '__main__':
125 test()
126 reactor.run()
127