1
2
3
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
43 self.message = message
44 self.stack = traceback.extract_stack()
45 Exception.__init__(self, self.message)
48
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
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
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
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
112 self.allkeys = []
113 UserDict.__init__(self, dict)
114
116 self.allkeys.remove(key)
117 UserDict.__delitem__(self, key)
118
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":
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
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
151 if sys.hexversion<0x20400f0:
152 raise ImportError,"Waf requires Python >= 2.3 but the raw source requires Python 2.4"
153
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
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
196
197
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
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():
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
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
235 if not path: return ['']
236 return path.split('/')
237
238 if sys.platform == 'win32':
243
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
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
269
271 return (path.strip().find(' ') > 0 and '"%s"' % path or path).replace('""', '"')
272
274 if not s: return ''
275 s = s.rstrip()
276 if s[0] == "'" and s[-1] == "'": return s[1:-1]
277 return s
278
280 m = md5()
281 m.update(str(lst))
282 return m.digest()
283
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
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:
326 pass
327
328
329 return hash( (prevhash, inspect.getsource(func)) )
330
331 -def pprint(col, str, label=''):
334
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