Package wafadmin :: Module Utils
[hide private]
[frames] | no frames]

Source Code for Module wafadmin.Utils

  1  #!/usr/bin/env python 
  2  # encoding: utf-8 
  3  # Thomas Nagy, 2005 (ita) 
  4   
  5  """ 
  6  Utilities, the stable ones are the following: 
  7   
  8  * h_file: compute a unique value for a file (hash), it uses 
  9    the module fnv if it is installed (see waf/utils/fnv & http://code.google.com/p/waf/wiki/FAQ) 
 10    else, md5 (see the python docs) 
 11   
 12    For large projects (projects with more than 15000 files) it is possible to use 
 13    a hashing based on the path and the size (may give broken cache results) 
 14   
 15          import stat 
 16          def h_file(filename): 
 17                  st = os.stat(filename) 
 18                  if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError, 'not a file' 
 19                  m = md5() 
 20                  m.update(str(st.st_mtime)) 
 21                  m.update(str(st.st_size)) 
 22                  m.update(filename) 
 23                  return m.digest() 
 24   
 25      To replace the function in your project, use something like this: 
 26          import Utils 
 27          Utils.h_file = h_file 
 28   
 29  * h_list 
 30  * h_fun 
 31  * get_term_cols 
 32  * ordered_dict 
 33   
 34  """ 
 35   
 36  import os, sys, imp, types, string, errno, traceback, inspect, re 
 37  from UserDict import UserDict 
 38  import Logs, pproc 
 39  from Constants import * 
 40   
41 -class WafError(Exception):
42 - def __init__(self, message):
43 self.message = message 44 self.stack = traceback.extract_stack() 45 Exception.__init__(self, self.message)
46 - def __str__(self):
47 return self.message
48
49 -class WscriptError(WafError):
50 - def __init__(self, message, wscript_file=None):
51 self.message = '' 52 53 if wscript_file: 54 self.wscript_file = wscript_file 55 self.wscript_line = None 56 else: 57 (self.wscript_file, self.wscript_line) = self.locate_error() 58 59 if self.wscript_file: 60 self.message += "%s:" % self.wscript_file 61 if self.wscript_line: 62 self.message += "%s:" % self.wscript_line 63 self.message += " error: %s" % message 64 WafError.__init__(self, self.message)
65
66 - def locate_error(self):
67 stack = traceback.extract_stack() 68 stack.reverse() 69 for frame in stack: 70 file_name = os.path.basename(frame[0]) 71 is_wscript = (file_name == WSCRIPT_FILE or file_name == WSCRIPT_BUILD_FILE) 72 if is_wscript: 73 return (frame[0], frame[1]) 74 return (None, None)
75 76 indicator = sys.platform=='win32' and '\x1b[A\x1b[K%s%s%s\r' or '\x1b[K%s%s%s\r' 77 78 try: 79 from fnv import new as md5 80 import Constants 81 Constants.SIG_NIL = 'signofnv' 82
83 - def h_file(filename):
84 m = md5() 85 try: 86 m.hfile(filename) 87 x = m.digest() 88 if x is None: raise OSError, "not a file" 89 return x 90 except SystemError: 91 raise OSError, "not a file"+filename
92 93 except ImportError: 94 try: 95 from hashlib import md5 96 except ImportError: 97 from md5 import md5 98
99 - def h_file(filename):
100 f = file(filename,'rb') 101 m = md5() 102 readBytes = 100000 103 while (readBytes): 104 readString = f.read(readBytes) 105 m.update(readString) 106 readBytes = len(readString) 107 f.close() 108 return m.digest()
109
110 -class ordered_dict(UserDict):
111 - def __init__(self, dict = None):
112 self.allkeys = [] 113 UserDict.__init__(self, dict)
114
115 - def __delitem__(self, key):
116 self.allkeys.remove(key) 117 UserDict.__delitem__(self, key)
118
119 - def __setitem__(self, key, item):
120 if key not in self.allkeys: self.allkeys.append(key) 121 UserDict.__setitem__(self, key, item)
122 123 listdir = os.listdir 124 if sys.platform == "win32":
125 - def listdir_win32(s):
126 if not os.path.isdir(s): 127 e = OSError() 128 e.errno = errno.ENOENT 129 raise e 130 return os.listdir(s)
131 listdir = listdir_win32 132
133 -def waf_version(mini = 0x010000, maxi = 0x100000):
134 "Halts if the waf version is wrong" 135 ver = HEXVERSION 136 try: min_val = mini + 0 137 except TypeError: min_val = int(mini.replace('.', '0'), 16) 138 139 if min_val > ver: 140 Logs.error("waf version should be at least %s (%s found)" % (mini, ver)) 141 sys.exit(0) 142 143 try: max_val = maxi + 0 144 except TypeError: max_val = int(maxi.replace('.', '0'), 16) 145 146 if max_val < ver: 147 Logs.error("waf version should be at most %s (%s found)" % (maxi, ver)) 148 sys.exit(0)
149
150 -def python_24_guard():
151 if sys.hexversion<0x20400f0: 152 raise ImportError,"Waf requires Python >= 2.3 but the raw source requires Python 2.4"
153
154 -def to_list(sth):
155 if type(sth) is types.ListType: 156 return sth 157 else: 158 return sth.split()
159 160 g_loaded_modules = {} 161 "index modules by absolute path" 162 163 g_module=None 164 "the main module is special" 165
166 -def load_module(file_path, name=WSCRIPT_FILE):
167 "this function requires an absolute path" 168 try: 169 return g_loaded_modules[file_path] 170 except KeyError: 171 pass 172 173 module = imp.new_module(name) 174 175 try: 176 file = open(file_path, 'r') 177 except (IOError, OSError): 178 raise WscriptError('The file %s could not be opened!' % file_path) 179 180 module_dir = os.path.dirname(file_path) 181 sys.path.insert(0, module_dir) 182 exec file in module.__dict__ 183 sys.path.remove(module_dir) 184 if file: file.close() 185 186 g_loaded_modules[file_path] = module 187 188 return module
189
190 -def set_main_module(file_path):
191 "Load custom options, if defined" 192 global g_module 193 g_module = load_module(file_path, 'wscript_main')
194 195 # remark: to register the module globally, use the following: 196 # sys.modules['wscript_main'] = g_module 197
198 -def to_hashtable(s):
199 "used for importing env files" 200 tbl = {} 201 lst = s.split('\n') 202 for line in lst: 203 if not line: continue 204 mems = line.split('=') 205 tbl[mems[0]] = mems[1] 206 return tbl
207
208 -def get_term_cols():
209 "console width" 210 return 80
211 try: 212 import struct, fcntl, termios 213 except ImportError: 214 pass 215 else: 216 if sys.stdout.isatty():
217 - def myfun():
218 dummy_lines, cols = struct.unpack("HHHH", \ 219 fcntl.ioctl(sys.stdout.fileno(),termios.TIOCGWINSZ , \ 220 struct.pack("HHHH", 0, 0, 0, 0)))[:2] 221 return cols
222 # we actually try the function once to see if it is suitable 223 try: 224 myfun() 225 except IOError: 226 pass 227 else: 228 get_term_cols = myfun 229 230 rot_idx = 0 231 rot_chr = ['\\', '|', '/', '-'] 232 "the rotation thing" 233
234 -def split_path(path):
235 if not path: return [''] 236 return path.split('/')
237 238 if sys.platform == 'win32':
239 - def split_path(path):
240 h,t = os.path.splitunc(path) 241 if not h: return __split_dirs(t) 242 return [h] + __split_dirs(t)[1:]
243
244 - def __split_dirs(path):
245 h,t = os.path.split(path) 246 if not h: return [t] 247 if h == path: return [h.replace('\\', '')] 248 if not t: return __split_dirs(h) 249 else: return __split_dirs(h) + [t]
250
251 -def copy_attrs(orig, dest, names, only_if_set=False):
252 for a in to_list(names): 253 u = getattr(orig, a, ()) 254 if u or not only_if_set: 255 setattr(dest, a, u)
256 257 _quote_define_name_translation = None 258 "lazily construct a translation table for mapping invalid characters to valid ones" 259
260 -def quote_define_name(path):
261 "Converts a string to a constant name, foo/zbr-xpto.h -> FOO_ZBR_XPTO_H" 262 global _quote_define_name_translation 263 if _quote_define_name_translation is None: 264 invalid_chars = [chr(x) for x in xrange(256)] 265 for valid in string.digits + string.uppercase: invalid_chars.remove(valid) 266 _quote_define_name_translation = string.maketrans(''.join(invalid_chars), '_'*len(invalid_chars)) 267 268 return string.translate(string.upper(path), _quote_define_name_translation)
269
270 -def quote_whitespace(path):
271 return (path.strip().find(' ') > 0 and '"%s"' % path or path).replace('""', '"')
272
273 -def trimquotes(s):
274 if not s: return '' 275 s = s.rstrip() 276 if s[0] == "'" and s[-1] == "'": return s[1:-1] 277 return s
278
279 -def h_list(lst):
280 m = md5() 281 m.update(str(lst)) 282 return m.digest()
283
284 -def h_fun(fun):
285 try: 286 return fun.code 287 except AttributeError: 288 try: 289 hh = inspect.getsource(fun) 290 except IOError: 291 hh = "nocode" 292 try: 293 fun.code = hh 294 except AttributeError: 295 pass 296 return hh
297 298 _hash_blacklist_types = ( 299 types.BuiltinFunctionType, 300 types.ModuleType, 301 types.FunctionType, 302 types.ClassType, 303 types.TypeType, 304 types.NoneType, 305 ) 306
307 -def hash_function_with_globals(prevhash, func):
308 """ 309 hash a function (object) and the global vars needed from outside 310 ignore unhashable global variables (lists) 311 312 prevhash: previous hash value to be combined with this one; 313 if there is no previous value, zero should be used here 314 315 func: a Python function object. 316 """ 317 assert type(func) is types.FunctionType 318 for name, value in func.func_globals.iteritems(): 319 if type(value) in _hash_blacklist_types: 320 continue 321 if isinstance(value, type): 322 continue 323 try: 324 prevhash = hash( (prevhash, name, value) ) 325 except TypeError: # raised for unhashable elements 326 pass 327 #else: 328 # print "hashed: ", name, " => ", value, " => ", hash(value) 329 return hash( (prevhash, inspect.getsource(func)) )
330
331 -def pprint(col, str, label=''):
332 "print messages in color" 333 print "%s%s%s %s" % (Logs.colors(col), str, Logs.colors.NORMAL, label)
334
335 -def check_dir(dir):
336 """If a folder doesn't exists, create it.""" 337 try: 338 os.stat(dir) 339 except OSError: 340 try: 341 os.makedirs(dir) 342 except OSError, e: 343 raise WafError("Cannot create folder '%s' (original error: %s)" % (dir, e))
344
345 -def cmd_output(cmd, e=None):
346 p = pproc.Popen(cmd, stdout=pproc.PIPE, shell=True, env=e) 347 output = p.communicate()[0] 348 if p.returncode: 349