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

# Source Code for Module Products.ZenUtils.Step

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