Package buildbot :: Package util :: Module eventual
[frames] | no frames]

Source Code for Module buildbot.util.eventual

  1  # This file is part of Buildbot.  Buildbot is free software: you can 
  2  # redistribute it and/or modify it under the terms of the GNU General Public 
  3  # License as published by the Free Software Foundation, version 2. 
  4  # 
  5  # This program is distributed in the hope that it will be useful, but WITHOUT 
  6  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  8  # details. 
  9  # 
 10  # You should have received a copy of the GNU General Public License along with 
 11  # this program; if not, write to the Free Software Foundation, Inc., 51 
 12  # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
 13  # 
 14  # Copyright Buildbot Team Members 
 15   
 16   
 17  # copied from foolscap 
 18   
 19  from twisted.internet import reactor, defer 
 20  from twisted.python import log 
 21   
22 -class _SimpleCallQueue(object):
23 24 _reactor = reactor 25
26 - def __init__(self):
27 self._events = [] 28 self._flushObservers = [] 29 self._timer = None 30 self._in_turn = False
31
32 - def append(self, cb, args, kwargs):
33 self._events.append((cb, args, kwargs)) 34 if not self._timer: 35 self._timer = self._reactor.callLater(0, self._turn)
36
37 - def _turn(self):
38 self._timer = None 39 self._in_turn = True 40 # flush all the messages that are currently in the queue. If anything 41 # gets added to the queue while we're doing this, those events will 42 # be put off until the next turn. 43 events, self._events = self._events, [] 44 for cb, args, kwargs in events: 45 try: 46 cb(*args, **kwargs) 47 except: 48 log.err() 49 self._in_turn = False 50 if self._events and not self._timer: 51 self._timer = self._reactor.callLater(0, self._turn) 52 if not self._events: 53 observers, self._flushObservers = self._flushObservers, [] 54 for o in observers: 55 o.callback(None)
56
57 - def flush(self):
58 """Return a Deferred that will fire (with None) when the call queue 59 is completely empty.""" 60 if not self._events and not self._in_turn: 61 return defer.succeed(None) 62 d = defer.Deferred() 63 self._flushObservers.append(d) 64 return d
65 66 67 _theSimpleQueue = _SimpleCallQueue() 68
69 -def eventually(cb, *args, **kwargs):
70 """This is the eventual-send operation, used as a plan-coordination 71 primitive. The callable will be invoked (with args and kwargs) in a later 72 reactor turn. Doing 'eventually(a); eventually(b)' guarantees that a will 73 be called before b. 74 75 Any exceptions that occur in the callable will be logged with log.err(). 76 If you really want to ignore them, be sure to provide a callable that 77 catches those exceptions. 78 79 This function returns None. If you care to know when the callable was 80 run, be sure to provide a callable that notifies somebody. 81 """ 82 _theSimpleQueue.append(cb, args, kwargs)
83 84
85 -def fireEventually(value=None):
86 """This returns a Deferred which will fire in a later reactor turn, after 87 the current call stack has been completed, and after all other deferreds 88 previously scheduled with callEventually(). 89 """ 90 d = defer.Deferred() 91 eventually(d.callback, value) 92 return d
93
94 -def flushEventualQueue(_ignored=None):
95 """This returns a Deferred which fires when the eventual-send queue is 96 finally empty. This is useful to wait upon as the last step of a Trial 97 test method. 98 """ 99 return _theSimpleQueue.flush()
100
101 -def _setReactor(r=None):
102 """This sets the reactor used to schedule future events to r. If r is None 103 (the default), the reactor is reset to its default value. 104 105 This should only be used for unit tests. 106 """ 107 if r is None: 108 r = reactor 109 _theSimpleQueue._reactor = r
110