Package sabayon :: Module util
[hide private]
[frames] | no frames]

Source Code for Module sabayon.util

  1  # 
  2  # Copyright (C) 2005 Red Hat, Inc. 
  3  # 
  4  # This program is free software; you can redistribute it and/or modify 
  5  # it under the terms of the GNU General Public License as published by 
  6  # the Free Software Foundation; either version 2 of the License, or 
  7  # (at your option) any later version. 
  8  # 
  9  # This program is distributed in the hope that it will be useful, 
 10  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 12  # GNU General Public License for more details. 
 13  # 
 14  # You should have received a copy of the GNU General Public License 
 15  # along with this program; if not, write to the Free Software 
 16  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 17  # 
 18   
 19  import os 
 20  import os.path 
 21  import sys 
 22  import fnmatch 
 23  import pwd 
 24  import grp 
 25  import gettext 
 26  import locale 
 27  import errno 
 28  import random 
 29  from config import * 
 30   
 31  # Standard exit codes for helper programs (sabayon-apply, sabayon-session) 
 32  EXIT_CODE_NORMAL = 0 
 33  EXIT_CODE_FATAL = 1 
 34  EXIT_CODE_RECOVERABLE = 2 
 35  EXIT_CODE_NO_USER_PROFILE = 3 # only for sabayon-apply 
 36   
 37  _util_admin_log_config_filename = None 
 38  _util_readable_log_config_filename = None 
 39   
40 -def get_admin_log_config_filename ():
41 """Returns the human-readable filename used for log configuration, 42 as stored with set_log_config_filename(). This is the file that the 43 system administrator actually modifies to set up the log configuration.""" 44 global _util_admin_log_config_filename 45 return _util_admin_log_config_filename
46
47 -def set_admin_log_config_filename (str):
48 """Stores the filename of the human-readable configuration file which the 49 system administrator used to set up the log configuration. This can be 50 queried back with get_admin_log_config_filename().""" 51 global _util_admin_log_config_filename 52 _util_admin_log_config_filename = str
53
54 -def get_readable_log_config_filename ():
55 """Returns the filename that the program actually used to read the log configuration, 56 as stored with set_readable_log_config_filename(). This may be different from the 57 filename from get_admin_log_config_filename(), since the helper processes in Sabayon 58 may need to be given a temporary file to read their log configuration (as root's 59 human-readable file may not be readable by the helper processes).""" 60 global _util_readable_log_config_filename 61 return _util_readable_log_config_filename
62
63 -def set_readable_log_config_filename (str):
64 """Stores the filename that the program actually used to read the log configuration. 65 This can be queried back with get_readable_log_config_filename(). This may be different from the 66 filename from get_admin_log_config_filename(), since the helper processes in Sabayon 67 may need to be given a temporary file to read their log configuration (as root's 68 human-readable file may not be readable by the helper processes).""" 69 global _util_readable_log_config_filename 70 _util_readable_log_config_filename = str
71
72 -class GeneralError (Exception):
73 - def __init__ (self, msg):
74 Exception.__init__ (self, msg)
75 76 unit_tests_homedir = None
77 -def set_home_dir_for_unit_tests (homedir):
78 global unit_tests_homedir 79 unit_tests_homedir = homedir
80
81 -def get_home_dir ():
82 if unit_tests_homedir: 83 return unit_tests_homedir 84 try: 85 pw = pwd.getpwuid (os.getuid ()) 86 if pw.pw_dir != "": 87 return pw.pw_dir 88 except KeyError: 89 pass 90 91 if os.environ.has_key ("HOME"): 92 return os.environ["HOME"] 93 else: 94 raise GeneralError (_("Cannot find home directory: not set in /etc/passwd and no value for $HOME in environment"))
95
96 -def get_group_membership ():
97 """Returns a list of non-primary, non-system groups that the user belongs 98 to. Raises a GeneralError if this fails. May return an empty list. 99 """ 100 101 groups = grp.getgrall() 102 103 try: 104 pw = pwd.getpwuid (os.getuid ()) 105 user = pw[0] 106 except KeyError: 107 if os.environ.has_key("USER"): 108 user = os.environ["USER"] 109 else: 110 raise GeneralError (_("Cannot find username: not set in /etc/passwd and no value for $USER in environment")) 111 112 members = [] 113 114 for group in groups: 115 if group[0] in members: 116 continue 117 if group[2] < 500: 118 continue 119 if group[0] == user: 120 continue 121 if user in group[3]: 122 members.append(group[0]) 123 124 return members
125
126 -def get_user_name ():
127 try: 128 pw = pwd.getpwuid (os.getuid ()) 129 if pw.pw_name != "": 130 return pw.pw_name 131 except KeyError: 132 pass 133 134 if os.environ.has_key ("USER"): 135 return os.environ["USER"] 136 else: 137 raise GeneralError (_("Cannot find username: not set in /etc/passwd and no value for $USER in environment"))
138 143
144 -def init_gettext ():
145 """Binds _() to gettext.gettext() in the global namespace. Run 146 util.init_gettext() at the entry point to any script and you'll be 147 able to use _(), gettext(), and ngettext() to mark strings for 148 translation.""" 149 try: 150 locale.setlocale (locale.LC_ALL, "") 151 except locale.Error: 152 pass 153 gettext.install (PACKAGE, LOCALEDIR) 154 # Python 2.4 compatibility 155 import __builtin__ 156 __builtin__.__dict__['gettext'] = __builtin__.__dict__['_'] 157 __builtin__.__dict__['ngettext'] = gettext.ngettext
158
159 -def random_string (len):
160 """Returns a string with random binary data of the specified length""" 161 bin = "" 162 while len > 0: 163 len = len - 1 164 bin = bin + chr(random.getrandbits(8)) 165 return bin
166 167
168 -def split_path(path, head=None, tail=None):
169 '''Given a path split it into a head and tail. If head is passed then 170 it is assumed to comprise the first part of the full path. If tail is 171 passed it is assumed to comprise the second part of the full path. 172 The path, head, and tail are made canonical via os.path.normpath prior 173 to the operations. ValueErrors are raised if head is not present at the 174 start of the path or if the path does not end with tail. The split must 175 occur on a directory separator boundary. 176 177 The return value is the tuple (head, tail) in canonical form.''' 178 path = os.path.normpath(path) 179 180 if tail is not None: 181 tail = os.path.normpath(tail) 182 if tail[0] == '/': 183 tail = tail[1:] 184 if not path.endswith(tail): 185 raise ValueError 186 path_len = len (path) 187 tail_len = len (tail) 188 dir_split = path_len - tail_len - 1 189 if path[dir_split] != '/': 190 raise ValueError 191 return (path[:dir_split], path[dir_split+1:]) 192 193 if head is not None: 194 head = os.path.normpath(head) 195 if head[-1] == '/': 196 head = head[:-1] 197 if not path.startswith(head): 198 raise ValueError 199 head_len = len (head) 200 dir_split = head_len 201 if path[dir_split] != '/': 202 raise ValueError 203 return (path[:dir_split], path[dir_split+1:]) 204 205 raise ValueError
206
207 -def run_unit_tests ():
208 home_dir = get_home_dir () 209 assert home_dir != "" 210 assert get_user_name () != "" 211 set_home_dir_for_unit_tests ("foo") 212 assert get_home_dir () == "foo" 213 set_home_dir_for_unit_tests (None) 214 assert get_home_dir () == home_dir
215 216 # ------ Class DictCompare ------ 217
218 -class DictCompare:
219 - def __init__(self, a, b):
220 self.a = a 221 self.b = b
222
223 - def compare(self):
224 ''' Given two dictionaries a,b analyze them for their 225 differences and similarities. 226 227 intersection - keys shared between a and b 228 only_a - keys only present in a 229 only_b - keys only present in b 230 equal - keys present in both a and b whole values are equal 231 not_equal - keys present in both a and b whole values are not equal''' 232 233 self.keys_a = self.a.keys() 234 self.keys_b = self.b.keys() 235 236 self.intersection = [] 237 self.only_a = [] 238 self.only_b = [] 239 self.equal = [] 240 self.not_equal = [] 241 self._add = {} 242 self._del = {} 243 self._mod = {} 244 245 for k in self.keys_a: 246 if self.b.has_key(k): 247 self.intersection.append(k) 248 else: 249 self.only_a.append(k) 250 251 for k in self.keys_b: 252 if not self.a.has_key(k): 253 self.only_b.append(k) 254 255 for k in self.intersection: 256 if self.a[k] == self.b[k]: 257 self.equal.append(k) 258 else: 259 self.not_equal.append(k)
260
261 - def intersection(self):
262 'return list of keys shared between a and b' 263 return self.intersection
264
265 - def only_a(self):
266 'return list of keys only present in a' 267 return self.only_a
268
269 - def only_b(self):
270 'return list of keys only present in b' 271 return self.only_b
272
273 - def equal(self):
274 'return list of keys present in both a and b whole values are equal' 275 return self.equal
276
277 - def not_equal(self):
278 'return list of keys present in both a and b whole values are not equal' 279 return self.not_equal
280
281 - def get_change_set(self, dict_lhs, dict_rhs):
282 '''Return changes necessary to make dict_lhs equivalent to dict_rhs, 283 (e.g. lhs = rhs), the two dictionary parameters are specified as 284 either the string 'a' or the string 'b' corresponding to the parameters 285 this class was created with. 286 287 Return value is a dictionary with 3 keys (add, del, mod) whose values 288 are dictionaries containing containing (key,value) pairs to add, 289 delete, or modify respectively in dict_lhs.''' 290 291 if dict_lhs == dict_rhs or dict_lhs not in "ab" or dict_rhs not in "ab": 292 raise ValueError 293 294 if dict_lhs == 'a': 295 a = self.a 296 b = self.b 297 only_a = self.only_a 298 only_b = self.only_b 299 elif dict_lhs == 'b': 300 a = self.b 301 b = self.a 302 only_a = self.only_b 303 only_b = self.only_a 304 else: 305 raise ValueError 306 307 self._add = {} 308 for k in only_b: 309 self._add[k] = b[k] 310 311 self._del = {} 312 for k in only_a: 313 self._del[k] = a[k] 314 315 self._mod = {} 316 for k in self.not_equal: 317 self._mod[k] = b[k] 318 319 change_set = {'add':self._add, 'del':self._del, 'mod':self._mod} 320 return change_set
321 322
323 - def is_equal(self):
324 if len(self.only_a) == 0 and len(self.only_b) == 0 and len(self.not_equal) == 0: 325 return True 326 else: 327 return False
328
329 - def dump(self):
330 'Print the results of the dictionary comparision' 331 print "intersection = %s" % ",".join(self.intersection) 332 print "only a = %s" % ",".join(self.only_a) 333 print "only b = %s" % ",".join(self.only_b) 334 print "equal = %s" % ",".join(self.equal) 335 print "not equal = %s" % ",".join(self.not_equal)
336
337 -def dump_change_set(cs):
338 _add = cs['add'] 339 _del = cs['del'] 340 _mod = cs['mod'] 341 342 if len(_add.keys()): 343 print "Key/Values to ADD" 344 for k in _add.keys(): 345 print " %s=%s" % (k, _add[k]) 346 347 if len(_del.keys()): 348 print "Keys to DELETE" 349 for k in _del.keys(): 350 print " %s=%s" % (k, _del[k]) 351 352 if len(_mod.keys()): 353 print "Key/Values to Modify" 354 for k in _mod.keys(): 355 print " %s=%s" % (k, _mod[k])
356 357
358 -def should_ignore_dir (base_dir, ignore_dir_list, dir):
359 dir = os.path.normpath (dir) 360 361 for ignore_dir in ignore_dir_list: 362 ignore_path = os.path.normpath (os.path.join (base_dir, ignore_dir)) 363 364 if fnmatch.fnmatch (dir, ignore_path): 365 return True 366 367 parent = os.path.dirname (dir) 368 if parent != dir: 369 return should_ignore_dir (base_dir, ignore_dir_list, parent) 370 else: 371 return False
372
373 -def should_ignore_file (base_dir, ignore_dir_list, ignore_file_list, file):
374 file = os.path.normpath (file) 375 376 for ignore_file in ignore_file_list: 377 ignore_path = os.path.normpath (os.path.join (base_dir, ignore_file)) 378 379 if fnmatch.fnmatch (file, ignore_path): 380 return True 381 382 return should_ignore_dir (base_dir, ignore_dir_list, os.path.dirname (file))
383