Package PyFoam :: Package Basics :: Module Utilities
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.Basics.Utilities

  1  #  ICE Revision: $Id$ 
  2  """ Utility functions 
  3   
  4  Can be used via a class or as functions""" 
  5   
  6  import sys 
  7  from PyFoam.ThirdParty.six import print_ 
  8  from PyFoam.Error import warning,error 
  9  import subprocess 
 10  import os,fnmatch 
 11   
 12  if sys.version_info<(2,6): 
 13      from popen2 import popen4 
 14  else: 
 15      from subprocess import Popen,PIPE,STDOUT 
 16  from os import listdir,path,remove as removeFile 
 17   
 18  import re 
 19   
 20  try: 
 21      import shutil 
 22  except ImportError: 
 23      # this is an old python-version without it. We'll try to work around it 
 24      pass 
 25   
26 -class Utilities(object):
27 """Class with utility methods 28 29 Can be inherited without side effects by classes that need these 30 methods""" 31
32 - def __init__(self):
33 pass
34
35 - def execute(self,cmd,debug=False,workdir=None,echo=None):
36 """Execute the command cmd. If specified change the working directory 37 38 Currently no error-handling is done 39 @return: A list with all the output-lines of the execution""" 40 if debug: 41 print_(cmd) 42 43 oldDir=None 44 if workdir: 45 oldDir=os.getcwd() 46 os.chdir(workdir) 47 48 if type(cmd)==list: 49 fpath=cmd[0] 50 else: 51 fpath=cmd.split(" ")[0] 52 53 # Check if the file is there. Then we assume that this is a script 54 if os.path.exists(fpath): 55 # Script seems to be unexecutable 56 if not os.access(fpath, os.X_OK): 57 error("The script file",fpath,"is not executable") 58 59 if sys.version_info<(2,6): 60 raus,rein = popen4(cmd) 61 else: 62 p = Popen(cmd, shell=True, 63 stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True, 64 universal_newlines=True) 65 (rein,raus)=(p.stdin,p.stdout) 66 if echo!=None: 67 tmp=[] 68 while p.poll()==None: 69 l=raus.readline() 70 print_(echo,l,end="") 71 tmp.append(l) 72 else: 73 tmp=raus.readlines() 74 # line=raus.readline() 75 # while line!="": 76 # print line 77 # line=raus.readline() 78 79 if oldDir: 80 os.chdir(oldDir) 81 82 return tmp
83
84 - def remove(self,f):
85 """Remove a file if it exists.""" 86 if path.exists(f): 87 removeFile(f)
88
89 - def rmtree(self,dst,ignore_errors=False):
90 """Encapsulates the shutil rmtree and provides an alternative for 91 old Python-version""" 92 try: 93 if path.isdir(dst): 94 shutil.rmtree(dst,ignore_errors=ignore_errors) 95 else: 96 os.remove(dst) 97 except NameError: 98 self.execute("rm -rf "+dst)
99
100 - def copytree(self,src,dst, 101 symlinks=False,force=False):
102 """Encapsulates the shutil copytree and provides an alternative for 103 old Python-version""" 104 if force and path.exists(dst): 105 if path.isdir(dst): 106 self.rmtree(dst) 107 else: 108 os.remove(dst) 109 try: 110 if path.isdir(dst): 111 dst=path.join(dst,path.basename(path.abspath(src))) 112 113 if path.islink(src) and symlinks: 114 os.symlink(path.realpath(src),dst) 115 elif path.isdir(src): 116 shutil.copytree(src,dst, 117 symlinks=symlinks) 118 else: 119 self.copyfile(src,dst) 120 except NameError: 121 cpOptions="-R" 122 if not symlinks: 123 cpOptions+=" -L" 124 self.execute("cp "+cpOptions+" "+src+" "+dst)
125
126 - def copyfile(self,src,dst):
127 """Encapsulates the shutil copyfile and provides an alternative for 128 old Python-version""" 129 try: 130 if path.isdir(dst): 131 dst=path.join(dst,path.basename(path.abspath(src))) 132 shutil.copyfile(src,dst) 133 shutil.copymode(src,dst) 134 except NameError: 135 self.execute("cp "+src+" "+dst)
136
137 - def writeDictionaryHeader(self,f):
138 """Writes a dummy header so OpenFOAM accepts the file as a dictionary 139 @param f: The file to write to 140 @type f: file""" 141 142 f.write(""" 143 // * * * * * * * * * // 144 FoamFile 145 { 146 version 0.5; 147 format ascii; 148 root "ROOT"; 149 case "CASE"; 150 class dictionary; 151 object nix; 152 } 153 """)
154 155 excludeNames=["^.svn$" , "~$"] 156
157 - def listDirectory(self,d):
158 """Lists the files in a directory, but excludes certain names 159 and files with certain endings 160 @param d: The directory to list 161 @return: List of the found files and directories""" 162 163 result=[] 164 165 excludes=list(map(re.compile,self.excludeNames)) 166 167 for n in listdir(d): 168 ok=True 169 170 for e in excludes: 171 if e.search(n): 172 ok=False 173 break 174 175 if ok: 176 result.append(n) 177 178 return result
179
180 - def which(self,progname):
181 """Get the full path. Return None if not found""" 182 try: 183 return shutil.which(progname) 184 except AttributeError: 185 # shutil has no which 186 pipe = subprocess.Popen('which '+progname, 187 shell=True, 188 stdout=subprocess.PIPE, 189 stderr=subprocess.STDOUT) 190 191 (fullname, errout) = pipe.communicate(input=input) 192 193 stat = pipe.returncode 194 195 if stat: 196 warning("which can not find a match for",progname) 197 return None 198 else: 199 return fullname
200
201 - def find(self,pattern, path,directoriesToo=True):
202 """Find all files whose names match 203 @param pattern: glob-style pattern 204 @param path: path under which this files are to be searched 205 @param directoriesToo: also match directories?""" 206 result = [] 207 for root, dirs, files in os.walk(path): 208 for name in files: 209 if fnmatch.fnmatch(name, pattern): 210 result.append(os.path.join(root, name)) 211 if directoriesToo: 212 for name in dirs: 213 if fnmatch.fnmatch(name, pattern): 214 result.append(os.path.join(root, name)) 215 return result
216
217 - def humanReadableSize(self,num):
218 """Lifted from http://stackoverflow.com/questions/1094841/reusable-library-to-get-human-readable-version-of-file-size 219 Gets a number in bytes and returns a human readable string""" 220 for x in ['bytes','KB','MB','GB']: 221 if num < 1024.0 and num > -1024.0: 222 return "%3.1f%s" % (num, x) 223 num /= 1024.0 224 return "%3.1f%s" % (num, 'TB')
225
226 - def diskUsage(self,fpath):
227 """Calculate the disk space used at the specified path in bytes""" 228 try: 229 return int( 230 subprocess.Popen( 231 ["du","-sb",fpath], 232 stdout=subprocess.PIPE, 233 stderr=open(os.devnull,"w") 234 ).communicate()[0].split()[0]) 235 except IndexError: 236 # assume that this du does not support -b 237 return int( 238 subprocess.Popen( 239 ["du","-sk",fpath], 240 stdout=subprocess.PIPE 241 ).communicate()[0].split()[0])*1024
242
243 -def diskUsage(fpath):
244 """Calls the method of the same name from the Utilites class""" 245 return Utilities().diskUsage(fpath)
246
247 -def humanReadableSize(num):
248 """Calls the method of the same name from the Utilites class""" 249 return Utilities().humanReadableSize(num)
250
251 -def which(prog):
252 """Calls the method of the same name from the Utilites class""" 253 return Utilities().which(prog)
254
255 -def execute(cmd,debug=False,workdir=None,echo=None):
256 """Calls the method of the same name from the Utilites class""" 257 return Utilities().execute(cmd,debug,workdir,echo)
258
259 -def writeDictionaryHeader(f):
260 """Calls the method of the same name from the Utilites class""" 261 Utilities().writeDictionaryHeader(f)
262
263 -def listDirectory(d):
264 """Calls the method of the same name from the Utilites class""" 265 return Utilities().listDirectory(d)
266
267 -def rmtree(path,ignore_errors=False):
268 """Calls the method of the same name from the Utilites class""" 269 return Utilities().rmtree(path,ignore_errors=ignore_errors)
270
271 -def copytree(src,dest,symlinks=False,force=False):
272 """Calls the method of the same name from the Utilites class""" 273 return Utilities().copytree(src,dest,symlinks=symlinks,force=force)
274
275 -def remove(f):
276 """Calls the method of the same name from the Utilites class""" 277 return Utilities().remove(f)
278
279 -def copyfile(src,dest):
280 """Calls the method of the same name from the Utilites class""" 281 return Utilities().copyfile(src,dest)
282
283 -def find(pattern,path,directoriesToo=True):
284 """Calls the method of the same name from the Utilites class""" 285 return Utilities().find(pattern,path,directoriesToo=directoriesToo)
286 287 # Should work with Python3 and Python2 288