Package Products :: Package ZenUtils :: Module Step
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenUtils.Step

 1  ############################################################################## 
 2  #  
 3  # Copyright (C) Zenoss, Inc. 2007, all rights reserved. 
 4  #  
 5  # This content is made available according to terms specified in 
 6  # License.zenoss under the directory where your Zenoss product is installed. 
 7  #  
 8  ############################################################################## 
 9   
10   
11  __doc__ = """Step 
12   
13  Utility for chaining defered actions. 
14   
15  """ 
16   
17  from twisted.internet import reactor, defer 
18   
19 -def Step(iterable):
20 ''' Step through iterable looking for deferreds. Whenever a deferred is 21 encountered wait until it is called before continuing through iterable. 22 23 Iterable is usually a generator function that yields a defered 24 anytime it wants to wait for that deferred to trigger before 25 continuing execution. 26 ''' 27 def doSteps(result): 28 # Depending on closure for value of iterable and finalD. 29 # If this causes problems we can pass them as arguments 30 # to doSteps and pass them in the addCallback(doSteps..) call. 31 # 32 # We don't actually use result anywhere here unless we are done 33 # iterating through iterable, in which case result becomes the 34 # result for the finalD deferred. 35 # Code within the iterable that needs the result of the previously 36 # yielded defered can get it directly from that deferred's result 37 # attribute. 38 for result in iterable: 39 # Keep getting items from iterable (the generator) until 40 # one returns a deferred. Then add this function as a 41 # callback to that deferred and return from the function. 42 if isinstance(result, defer.Deferred): 43 result.addCallback(doSteps) 44 return result 45 finalD.callback(result) 46 return result
47 48 # Make sure we have an iterable 49 if not hasattr(iterable, 'next'): 50 if hasattr(iterable, '__iter__'): 51 iterable = iter(iterable) 52 else: 53 raise RuntimeError( 'Must pass an iterable object to step' ) 54 55 # finalD is the deferred that will trigger when iterable is exhausted 56 finalD = defer.Deferred() 57 58 # start consuming the iterable 59 doSteps(None) 60 61 return finalD 62 63
64 -class Test:
65
66 - def foo(self, n):
67 d = defer.Deferred() 68 reactor.callLater(2, d.callback, n) 69 return d
70 71
72 - def sequence(self):
73 d1 = self.foo(1) 74 print 'yielding d1 from sequence' 75 yield d1 76 r1 = d1.result 77 d2 = self.foo(r1 + 1) 78 print 'yielding d2 from sequence' 79 yield d2 80 r2 = d2.result 81 print 'yielding final result from sequence' 82 yield r2
83 84
85 - def myCallback(self, r):
86 print 'final deferred returned %s' % `r`
87 88
89 - def go(self):
90 myD = Step(self.sequence()) 91 myD.addCallback(self.myCallback) 92 reactor.callLater(10, reactor.stop) 93 reactor.run()
94