Module io
[hide private]
[frames] | no frames]

Source Code for Module io

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2003-2006 Edward d'Auvergne                                   # 
  4  #                                                                             # 
  5  # This file is part of the program relax.                                     # 
  6  #                                                                             # 
  7  # relax is free software; you can redistribute it and/or modify               # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation; either version 2 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # relax is distributed in the hope that it will be useful,                    # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with relax; if not, write to the Free Software                        # 
 19  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   # 
 20  #                                                                             # 
 21  ############################################################################### 
 22   
 23  import __builtin__ 
 24   
 25  # BZ2 compression module. 
 26  try: 
 27      from bz2 import BZ2File 
 28      __builtin__.bz2_module = 1 
 29  except ImportError, message: 
 30      __builtin__.bz2_module = 0 
 31      __builtin__.bz2_module_message = message.args[0] 
 32   
 33  # Gzip compression module. 
 34  from gzip import GzipFile 
 35   
 36  # Devnull. 
 37  try: 
 38      from os import devnull 
 39      __builtin__.devnull_import = 1 
 40  except ImportError, message: 
 41      __builtin__.devnull_import = 0 
 42      __builtin__.devnull_import_message = message.args[0] 
 43   
 44  from os import F_OK, X_OK, access, altsep, getenv, makedirs, pathsep, remove, sep, stat 
 45  from os.path import expanduser 
 46  from re import match, search 
 47  from string import split 
 48  import sys 
 49  from sys import stdin, stdout, stderr 
 50   
 51   
52 -class IO:
53 - def __init__(self, relax):
54 """Class containing the file operations. 55 56 IO streams 57 ~~~~~~~~~~ 58 59 Standard python IO streams: 60 61 sys.stdin = self.python_stdin 62 sys.stdout = self.python_stdout 63 sys.stderr = self.python_stderr 64 65 Logging IO streams: 66 67 sys.stdin = self.log_stdin = self.python_stdin 68 sys.stdout = self.log_stdout = self.log_file 69 sys.stderr = self.log_stdout = (self.python_stderr, self.log_file) 70 71 Tee IO streams: 72 73 sys.stdin = self.tee_stdin = self.python_stdin 74 sys.stdout = self.tee_stdout = (self.python_stdout, self.tee_file) 75 sys.stderr = self.tee_stdout = (self.python_stderr, self.tee_file) 76 """ 77 78 self.relax = relax 79 80 # Standard python IO streams. 81 self.python_stdin = stdin 82 self.python_stdout = stdout 83 self.python_stderr = stderr 84 85 # Logging IO streams. 86 self.log_stdin = stdin 87 self.log_stdout = None 88 self.log_stderr = SplitIO() 89 90 # Tee IO streams. 91 self.tee_stdin = stdin 92 self.tee_stdout = SplitIO() 93 self.tee_stderr = SplitIO()
94 95
96 - def delete(self, file_name=None, dir=None):
97 """Function for deleting the given file.""" 98 99 # File path. 100 file_path = self.file_path(file_name, dir) 101 102 # Test if the file exists and determine the compression type. 103 if access(file_path, F_OK): 104 pass 105 elif access(file_path + '.bz2', F_OK): 106 file_path = file_path + '.bz2' 107 elif access(file_path + '.gz', F_OK): 108 file_path = file_path + '.gz' 109 else: 110 raise RelaxFileError, file_path 111 112 # Remove the file. 113 remove(file_path)
114 115
116 - def extract_data(self, file_name=None, dir=None, file_data=None, sep=None, compress_type=0):
117 """Open the file 'file' and return all the data.""" 118 119 # Data not already extracted from the file. 120 if not file_data: 121 # Open the file. 122 file = self.open_read_file(file_name=file_name, dir=dir, compress_type=compress_type) 123 124 # Read lines. 125 file_data = file.readlines() 126 127 # Create a data structure from the contents of the file split by either whitespace or the separator, sep. 128 data = [] 129 for i in xrange(len(file_data)): 130 if sep: 131 row = split(file_data[i], sep) 132 else: 133 row = split(file_data[i]) 134 data.append(row) 135 return data 136 137 # Close the file. 138 if not file_data: 139 file.close()
140 141
142 - def file_path(self, file_name=None, dir=None):
143 """Generate and expand the full file path.""" 144 145 # File name. 146 file_path = file_name 147 148 # Add the directory. 149 if dir: 150 file_path = dir + '/' + file_path 151 152 # Expand any ~ characters. 153 file_path = expanduser(file_path) 154 155 # Return the file path. 156 return file_path
157 158
159 - def log(self, file_name=None, dir=None, compress_type=0, print_flag=1):
160 """Function for turning logging on.""" 161 162 # Log file. 163 self.log_file, file_path = self.open_write_file(file_name=file_name, dir=dir, force=1, compress_type=compress_type, print_flag=print_flag, return_path=1) 164 165 # Print out. 166 if print_flag: 167 print "Redirecting the sys.stdin IO stream to the python stdin IO stream." 168 print "Redirecting the sys.stdout IO stream to the log file '%s'." % file_path 169 print "Redirecting the sys.stderr IO stream to both the python stderr IO stream and the log file '%s'." % file_path 170 171 # Set the logging IO streams. 172 self.log_stdout = self.log_file 173 self.log_stderr.split(self.python_stderr, self.log_file) 174 175 # IO stream redirection. 176 sys.stdin = self.log_stdin 177 sys.stdout = self.log_stdout 178 sys.stderr = self.log_stderr
179 180
181 - def logging_off(self, file_name=None, dir=None, print_flag=1):
182 """Function for turning logging and teeing off.""" 183 184 # Print out. 185 if print_flag: 186 print "Redirecting the sys.stdin IO stream to the python stdin IO stream." 187 print "Redirecting the sys.stdout IO stream to the python stdout IO stream." 188 print "Redirecting the sys.stderr IO stream to the python stderr IO stream." 189 190 # IO stream redirection. 191 sys.stdin = self.python_stdin 192 sys.stdout = self.python_stdout 193 sys.stderr = self.python_stderr
194 195
196 - def mkdir(self, dir=None, print_flag=1):
197 """Create the given directory, or exit if the directory exists.""" 198 199 # No directory given. 200 if dir == None: 201 return 202 203 # Make the directory. 204 try: 205 makedirs(dir) 206 except OSError: 207 if print_flag: 208 print "Directory ./" + dir + " already exists.\n"
209 210
211 - def open_read_file(self, file_name=None, dir=None, compress_type=0, print_flag=1):
212 """Open the file 'file' and return all the data.""" 213 214 # File path. 215 file_path = self.file_path(file_name, dir) 216 217 # Test if the file exists and determine the compression type. 218 if access(file_path, F_OK): 219 compress_type = 0 220 if search('.bz2$', file_path): 221 compress_type = 1 222 elif search('.gz$', file_path): 223 compress_type = 2 224 elif access(file_path + '.bz2', F_OK): 225 file_path = file_path + '.bz2' 226 compress_type = 1 227 elif access(file_path + '.gz', F_OK): 228 file_path = file_path + '.gz' 229 compress_type = 2 230 else: 231 raise RelaxFileError, file_path 232 233 # Open the file for reading. 234 try: 235 if print_flag: 236 print "Opening the file " + `file_path` + " for reading." 237 if compress_type == 0: 238 file = open(file_path, 'r') 239 elif compress_type == 1: 240 if bz2_module: 241 file = BZ2File(file_path, 'r') 242 else: 243 raise RelaxError, "Cannot open the file " + `file_path` + ", try uncompressing first. " + bz2_module_message + "." 244 elif compress_type == 2: 245 file = GzipFile(file_path, 'r') 246 except IOError, message: 247 raise RelaxError, "Cannot open the file " + `file_path` + ". " + message.args[1] + "." 248 249 # Return the opened file. 250 return file
251 252
253 - def open_write_file(self, file_name=None, dir=None, force=0, compress_type=0, print_flag=1, return_path=0):
254 """Function for opening a file for writing and creating directories if necessary.""" 255 256 # The null device. 257 if search('devnull', file_name): 258 # Devnull could not be imported! 259 if not devnull_import: 260 raise RelaxError, devnull_import_message + ". To use devnull, please upgrade to Python >= 2.4." 261 262 # Print out. 263 if print_flag: 264 print "Opening the null device file for writing." 265 266 # Open the null device. 267 file = open(devnull, 'w') 268 269 # Return the file. 270 if return_path: 271 return file, None 272 else: 273 return file 274 275 # Create the directories. 276 self.mkdir(dir, print_flag=0) 277 278 # File path. 279 file_path = self.file_path(file_name, dir) 280 281 # Bzip2 compression. 282 if compress_type == 1 and not search('.bz2$', file_path): 283 # Bz2 module exists. 284 if bz2_module: 285 file_path = file_path + '.bz2' 286 287 # Switch to gzip compression. 288 else: 289 print "Cannot use bz2 compression, using gzip compression instead. " + bz2_module_message + "." 290 compress_type = 2 291 292 # Gzip compression. 293 if compress_type == 2 and not search('.gz$', file_path): 294 file_path = file_path + '.gz' 295 296 # Fail if the file already exists and the force flag is set to 0. 297 if access(file_path, F_OK) and not force: 298 raise RelaxFileOverwriteError, (file_path, 'force flag') 299 300 # Open the file for writing. 301 try: 302 if print_flag: 303 print "Opening the file " + `file_path` + " for writing." 304 if compress_type == 0: 305 file = open(file_path, 'w') 306 elif compress_type == 1: 307 file = BZ2File(file_path, 'w') 308 elif compress_type == 2: 309 file = GzipFile(file_path, 'w') 310 except IOError, message: 311 raise RelaxError, "Cannot open the file " + `file_path` + ". " + message.args[1] + "." 312 313 # Return the opened file. 314 if return_path: 315 return file, file_path 316 else: 317 return file
318 319
320 - def strip(self, data):
321 """Function to remove all comment and empty lines from the file data structure.""" 322 323 # Initialise the new data array. 324 new = [] 325 326 # Loop over the data. 327 for i in xrange(len(data)): 328 # Empty lines. 329 if len(data[i]) == 0: 330 continue 331 332 # Comment lines. 333 elif match("#", data[i][0]): 334 continue 335 336 # Data lines. 337 else: 338 new.append(data[i]) 339 340 # Return the new data structure. 341 return new
342 343
344 - def tee(self, file_name=None, dir=None, compress_type=0, print_flag=1):
345 """Function for turning logging on.""" 346 347 # Tee file. 348 self.tee_file, file_path = self.open_write_file(file_name=file_name, dir=dir, force=1, compress_type=compress_type, print_flag=print_flag, return_path=1) 349 350 # Print out. 351 if print_flag: 352 print "Redirecting the sys.stdin IO stream to the python stdin IO stream." 353 print "Redirecting the sys.stdout IO stream to both the python stdout IO stream and the log file '%s'." % file_path 354 print "Redirecting the sys.stderr IO stream to both the python stderr IO stream and the log file '%s'." % file_path 355 356 # Set the tee IO streams. 357 self.tee_stdout.split(self.python_stdout, self.tee_file) 358 self.tee_stderr.split(self.python_stderr, self.tee_file) 359 360 # IO stream redirection. 361 sys.stdin = self.tee_stdin 362 sys.stdout = self.tee_stdout 363 sys.stderr = self.tee_stderr
364 365
366 - def test_binary(self, binary):
367 """Function for testing that the binary string corresponds to a valid executable file.""" 368 369 # Path separator RE string. 370 if altsep: 371 path_sep = '[' + sep + altsep + ']' 372 else: 373 path_sep = sep 374 375 # The full path of the program has been given (if a directory separatory has been supplied). 376 if search(path_sep, binary): 377 # Test that the binary exists. 378 if not access(binary, F_OK): 379 raise RelaxMissingBinaryError, binary 380 381 # Test that if the binary is executable. 382 if not access(binary, X_OK): 383 raise RelaxNonExecError, binary 384 385 # The path to the binary has not been given. 386 else: 387 # Get the PATH environmental variable. 388 path = getenv('PATH') 389 390 # Split PATH by the path separator. 391 path_list = split(path, pathsep) 392 393 # Test that the binary exists within the system path (and exit this function instantly once it has been found). 394 for path in path_list: 395 if access(path + sep + binary, F_OK): 396 return 397 398 # The binary is not located in the system path! 399 raise RelaxNoInPathError, binary
400 401
402 -class SplitIO:
403 - def __init__(self):
404 """Class for splitting an IO stream to two outputs."""
405 406
407 - def split(self, stream1, stream2):
408 """Function for setting the streams.""" 409 410 # Arguments. 411 self.stream1 = stream1 412 self.stream2 = stream2
413 414
415 - def write(self, text):
416 """Replacement write function.""" 417 418 # Write to stream1. 419 self.stream1.write(text) 420 421 # Write to stream2. 422 self.stream2.write(text)
423