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