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

Source Code for Package buildbot.util

  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  import time, re, string 
 18  import datetime 
 19  import calendar 
 20  from buildbot.util.misc import deferredLocked, SerializedInvocation 
 21   
22 -def naturalSort(l):
23 l = l[:] 24 def try_int(s): 25 try: 26 return int(s) 27 except ValueError: 28 return s
29 def key_func(item): 30 return [try_int(s) for s in re.split('(\d+)', item)] 31 # prepend integer keys to each element, sort them, then strip the keys 32 keyed_l = [ (key_func(i), i) for i in l ] 33 keyed_l.sort() 34 l = [ i[1] for i in keyed_l ] 35 return l 36
37 -def flatten(l):
38 if l and type(l[0]) == list: 39 rv = [] 40 for e in l: 41 if type(e) == list: 42 rv.extend(flatten(e)) 43 else: 44 rv.append(e) 45 return rv 46 else: 47 return l
48
49 -def now(_reactor=None):
50 if _reactor and hasattr(_reactor, "seconds"): 51 return _reactor.seconds() 52 else: 53 return time.time()
54
55 -def formatInterval(eta):
56 eta_parts = [] 57 if eta > 3600: 58 eta_parts.append("%d hrs" % (eta / 3600)) 59 eta %= 3600 60 if eta > 60: 61 eta_parts.append("%d mins" % (eta / 60)) 62 eta %= 60 63 eta_parts.append("%d secs" % eta) 64 return ", ".join(eta_parts)
65
66 -class ComparableMixin:
67 68 compare_attrs = [] 69
70 - class _None:
71 pass
72
73 - def __hash__(self):
74 alist = [self.__class__] + \ 75 [getattr(self, name, self._None) for name in self.compare_attrs] 76 return hash(tuple(map(str, alist)))
77
78 - def __cmp__(self, them):
79 result = cmp(type(self), type(them)) 80 if result: 81 return result 82 83 result = cmp(self.__class__.__name__, them.__class__.__name__) 84 if result: 85 return result 86 87 result = cmp(self.compare_attrs, them.compare_attrs) 88 if result: 89 return result 90 91 self_list = [getattr(self, name, self._None) 92 for name in self.compare_attrs] 93 them_list = [getattr(them, name, self._None) 94 for name in self.compare_attrs] 95 return cmp(self_list, them_list)
96
97 -def diffSets(old, new):
98 if not isinstance(old, set): 99 old = set(old) 100 if not isinstance(new, set): 101 new = set(new) 102 return old - new, new - old
103 104 # Remove potentially harmful characters from builder name if it is to be 105 # used as the build dir. 106 badchars_map = string.maketrans("\t !#$%&'()*+,./:;<=>?@[\\]^{|}~", 107 "______________________________")
108 -def safeTranslate(str):
109 if isinstance(str, unicode): 110 str = str.encode('utf8') 111 return str.translate(badchars_map)
112
113 -def none_or_str(x):
114 if x is not None and not isinstance(x, str): 115 return str(x) 116 return x
117 118 # place a working json module at 'buildbot.util.json'. Code is adapted from 119 # Paul Wise <pabs@debian.org>: 120 # http://lists.debian.org/debian-python/2010/02/msg00016.html 121 # json doesn't exist as a standard module until python2.6 122 # However python2.6's json module is much slower than simplejson, so we prefer 123 # to use simplejson if available. 124 try: 125 import simplejson as json 126 assert json 127 except ImportError: 128 import json # python 2.6 or 2.7 129 try: 130 _tmp = json.loads 131 except AttributeError: 132 import warnings 133 import sys 134 warnings.warn("Use simplejson, not the old json module.") 135 sys.modules.pop('json') # get rid of the bad json module 136 import simplejson as json 137 138 # changes and schedulers consider None to be a legitimate name for a branch, 139 # which makes default function keyword arguments hard to handle. This value 140 # is always false.
141 -class NotABranch:
142 - def __nonzero__(self):
143 return False
144 NotABranch = NotABranch() 145 146 # time-handling methods 147
148 -class UTC(datetime.tzinfo):
149 """Simple definition of UTC timezone"""
150 - def utcoffset(self, dt):
151 return datetime.timedelta(0)
152
153 - def dst(self, dt):
154 return datetime.timedelta(0)
155
156 - def tzname(self):
157 return "UTC"
158 UTC = UTC() 159
160 -def epoch2datetime(epoch):
161 """Convert a UNIX epoch time to a datetime object, in the UTC timezone""" 162 if epoch is not None: 163 return datetime.datetime.fromtimestamp(epoch, tz=UTC)
164
165 -def datetime2epoch(dt):
166 """Convert a non-naive datetime object to a UNIX epoch timestamp""" 167 if dt is not None: 168 return calendar.timegm(dt.utctimetuple())
169
170 -def makeList(input):
171 if isinstance(input, basestring): 172 return [ input ] 173 elif input is None: 174 return [ ] 175 else: 176 return list(input)
177
178 -def in_reactor(f):
179 """decorate a function by running it with maybeDeferred in a reactor""" 180 def wrap(*args, **kwargs): 181 from twisted.internet import reactor, defer 182 result = [ ] 183 def async(): 184 d = defer.maybeDeferred(f, *args, **kwargs) 185 def eb(f): 186 f.printTraceback()
187 d.addErrback(eb) 188 def do_stop(r): 189 result.append(r) 190 reactor.stop() 191 d.addBoth(do_stop) 192 reactor.callWhenRunning(async) 193 reactor.run() 194 return result[0] 195 wrap.__doc__ = f.__doc__ 196 wrap.__name__ = f.__name__ 197 wrap._orig = f # for tests 198 return wrap 199 200 __all__ = [ 201 'naturalSort', 'now', 'formatInterval', 'ComparableMixin', 'json', 202 'safeTranslate', 'LRUCache', 'none_or_str', 203 'NotABranch', 'deferredLocked', 'SerializedInvocation', 'UTC', 204 'diffLists', 'makeList', 'in_reactor' ] 205