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

Source Code for Module buildbot.util.misc

 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  Miscellaneous utilities; these should be imported from C{buildbot.util}, not 
18  directly from this module. 
19  """ 
20   
21  from twisted.python import log 
22  from twisted.internet import defer 
23   
24 -def deferredLocked(lock_or_attr):
25 """ 26 Wrap a function which returns a Deferred with a DeferredLock. The 27 DeferredLock is given by the argument to the decorator; if this argument is 28 a string, then the function is assumed to be a method, and the named 29 attribute of SELF is used as the lock object. 30 """ 31 def decorator(fn): 32 def wrapper(*args, **kwargs): 33 lock = lock_or_attr 34 if isinstance(lock, basestring): 35 lock = getattr(args[0], lock) 36 d = lock.acquire() 37 d.addCallback(lambda _ : fn(*args, **kwargs)) 38 def release(val): 39 lock.release() 40 return val
41 d.addBoth(release) 42 return d 43 return wrapper 44 return decorator 45
46 -class SerializedInvocation(object):
47 """ 48 A method wrapper to serialize calls to a deferred method. If a second call 49 occurs while the first call is still executing, it will not begin until the 50 first call has finished. If multiple calls queue up, they will be 51 collapsed into a single call. 52 53 The effect is that the underlying method is guaranteed to be called at 54 least once after every call to the wrapper. 55 56 Note that this cannot be used as a decorator on a method, as it will 57 serialize invocations across all class instances. Tests can monkey-patch 58 the C{_quiet} method to be notified when all planned invocations are 59 complete. 60 """
61 - def __init__(self, method):
62 self.method = method 63 self.running = False 64 self.pending_deferreds = []
65
66 - def __call__(self):
67 d = defer.Deferred() 68 self.pending_deferreds.append(d) 69 if not self.running: 70 self.start() 71 return d
72
73 - def start(self):
74 self.running = True 75 invocation_deferreds = self.pending_deferreds 76 self.pending_deferreds = [] 77 d = self.method() 78 d.addErrback(log.err, 'in invocation of %r' % (self.method,)) 79 80 def notify_callers(_): 81 for d in invocation_deferreds: 82 d.callback(None)
83 d.addCallback(notify_callers) 84 85 def next(_): 86 self.running = False 87 if self.pending_deferreds: 88 self.start() 89 else: 90 self._quiet()
91 d.addBoth(next) 92
93 - def _quiet(self): # hook for tests
94 pass 95