1
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
24 pass
25
27 """Class with utility methods
28
29 Can be inherited without side effects by classes that need these
30 methods"""
31
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
54 if os.path.exists(fpath):
55
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
75
76
77
78
79 if oldDir:
80 os.chdir(oldDir)
81
82 return tmp
83
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
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
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
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
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
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
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
237 return int(
238 subprocess.Popen(
239 ["du","-sk",fpath],
240 stdout=subprocess.PIPE
241 ).communicate()[0].split()[0])*1024
242
244 """Calls the method of the same name from the Utilites class"""
245 return Utilities().diskUsage(fpath)
246
250
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
262
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
276 """Calls the method of the same name from the Utilites class"""
277 return Utilities().remove(f)
278
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
288