1 """
2 Application-class that implements pyFoamListCases.py
3 """
4 from optparse import OptionGroup
5 from os import path,listdir,stat
6 import time,datetime
7 from stat import ST_MTIME
8 import string
9 import subprocess
10 import re
11
12 from PyFoamApplication import PyFoamApplication
13
14 from PyFoam.RunDictionary.SolutionDirectory import SolutionDirectory
15
16 from PyFoam import configuration
17
20 description="""\
21 List the valid OpenFOAM-cases in a number of directories along with
22 some basic information (number of timesteps, last timestep,
23 etc). Currently doesn't honor the parallel data
24 """
25 PyFoamApplication.__init__(self,
26 args=args,
27 description=description,
28 usage="%prog [<directories>]",
29 interspersed=True,
30 changeVersion=False,
31 nr=0,
32 exactNr=False)
33
34 sortChoices=["name","first","last","mtime","nrSteps","procs","diskusage","pFirst","pLast","nrParallel","nowTime","state","lastOutput","startedAt"]
35
37 what=OptionGroup(self.parser,
38 "What",
39 "Define what should be shown")
40 self.parser.add_option_group(what)
41
42 what.add_option("--dump",
43 action="store_true",
44 dest="dump",
45 default=False,
46 help="Dump the information as Python-dictionaries")
47
48 what.add_option("--disk-usage",
49 action="store_true",
50 dest="diskusage",
51 default=False,
52 help="Show the disk-usage of the case (in MB) - may take a long time")
53
54 what.add_option("--parallel-info",
55 action="store_true",
56 dest="parallel",
57 default=False,
58 help="Print information about parallel runs (if present): number of processors and processor first and last time. The mtime will be that of the processor-directories")
59
60 what.add_option("--no-state",
61 action="store_false",
62 dest="state",
63 default=True,
64 help="Don't read state-files")
65
66 what.add_option("--advanced-state",
67 action="store_true",
68 dest="advancedState",
69 default=False,
70 help="Additional state information (run started, last output seen)")
71
72 how=OptionGroup(self.parser,
73 "How",
74 "How the things should be shown")
75 self.parser.add_option_group(how)
76
77 how.add_option("--sort-by",
78 type="choice",
79 action="store",
80 dest="sort",
81 default=configuration().get("CommandOptionDefaults","sortListCases",default="name"),
82 choices=self.sortChoices,
83 help="Sort the cases by a specific key (Keys: "+string.join(self.sortChoices,", ")+") Default: %default")
84 how.add_option("--reverse-sort",
85 action="store_true",
86 dest="reverse",
87 default=False,
88 help="Sort in reverse order")
89 how.add_option("--relative-times",
90 action="store_true",
91 dest="relativeTime",
92 default=False,
93 help="Show the timestamps relative to the current time")
94
95 behave=OptionGroup(self.parser,
96 "Behaviour",
97 "Additional output etc")
98 self.parser.add_option_group(behave)
99
100 behave.add_option("--progress",
101 action="store_true",
102 dest="progress",
103 default=False,
104 help="Print the directories while they are being processed")
105
107 fName=path.join(sol.name,"PyFoamState."+sFile)
108 if not path.exists(fName):
109 return default
110 else:
111 self.hasState=True
112 return open(fName).read().strip()
113
115 dirs=self.parser.getArgs()
116
117 if len(dirs)==0:
118 dirs=[path.curdir]
119
120 cData=[]
121 totalDiskusage=0
122
123 self.hasState=False
124
125 for d in dirs:
126 for n in listdir(d):
127 cName=path.join(d,n)
128 if path.isdir(cName):
129 try:
130 sol=SolutionDirectory(cName,archive=None,paraviewLink=False)
131 if sol.isValid():
132 if self.opts.progress:
133 print "Processing",cName
134
135 data={}
136
137 data["mtime"]=stat(cName)[ST_MTIME]
138 times=sol.getTimes()
139 try:
140 data["first"]=times[0]
141 except IndexError:
142 data["first"]="None"
143 try:
144 data["last"]=times[-1]
145 except IndexError:
146 data["last"]="None"
147 data["nrSteps"]=len(times)
148 data["procs"]=sol.nrProcs()
149 data["pFirst"]=-1
150 data["pLast"]=-1
151 data["nrParallel"]=-1
152 if self.opts.parallel:
153 pTimes=sol.getParallelTimes()
154 data["nrParallel"]=len(pTimes)
155 if len(pTimes)>0:
156 data["pFirst"]=pTimes[0]
157 data["pLast"]=pTimes[-1]
158 data["name"]=cName
159 data["diskusage"]=-1
160 if self.opts.diskusage:
161 data["diskusage"]=int(subprocess.Popen(["du","-sm",cName], stdout=subprocess.PIPE).communicate()[0].split()[0])
162 totalDiskusage+=data["diskusage"]
163 if self.opts.parallel:
164 for f in listdir(cName):
165 if re.compile("processor[0-9]+").match(f):
166 data["mtime"]=max(stat(path.join(cName,f))[ST_MTIME],data["mtime"])
167
168 if self.opts.state:
169 try:
170 data["nowTime"]=float(self.readState(sol,"CurrentTime"))
171 except ValueError:
172 data["nowTime"]=None
173
174 try:
175 data["lastOutput"]=time.mktime(time.strptime(self.readState(sol,"LastOutputSeen")))
176 except ValueError:
177 data["lastOutput"]="nix"
178 try:
179 data["startedAt"]=time.mktime(time.strptime(self.readState(sol,"StartedAt")))
180 except ValueError:
181 data["startedAt"]="nix"
182
183 data["state"]=self.readState(sol,"TheState")
184
185 cData.append(data)
186 except OSError:
187 print cName,"is unreadable"
188
189 if self.opts.progress:
190 print "Sorting data"
191
192 if self.opts.reverse:
193 cData.sort(lambda x,y:cmp(y[self.opts.sort],x[self.opts.sort]))
194 else:
195 cData.sort(lambda x,y:cmp(x[self.opts.sort],y[self.opts.sort]))
196
197 if len(cData)==0:
198 print "No cases found"
199 return
200
201 if self.opts.dump:
202 print cData
203 return
204
205 lens={}
206 for k in cData[0].keys():
207 lens[k]=len(k)
208 for c in cData:
209 for k in ["mtime","lastOutput","startedAt"]:
210 try:
211 if self.opts.relativeTime:
212 c[k]=datetime.timedelta(seconds=long(time.time()-c[k]))
213 else:
214 c[k]=time.asctime(time.localtime(c[k]))
215 except KeyError:
216 pass
217 except TypeError:
218 c[k]=None
219
220 for k,v in c.iteritems():
221 lens[k]=max(lens[k],len(str(v)))
222
223 format=""
224 spec=["mtime"," | ","first"," - ","last"," (","nrSteps",") "]
225 if self.opts.parallel:
226 spec+=["| ","procs"," : ","pFirst"," - ","pLast"," (","nrParallel",") | "]
227 if self.opts.diskusage:
228 spec+=["diskusage"," MB "]
229 if self.hasState:
230 spec+=["nowTime"," s ","state"," | "]
231 if self.opts.advancedState:
232 spec+=["lastOutput"," | ","startedAt"," | "]
233
234 spec+=["name"]
235
236 for i,l in enumerate(spec):
237 if not l in cData[0].keys():
238 format+=l
239 else:
240 if i<len(spec)-1:
241 format+="%%(%s)%ds" % (l,lens[l])
242 else:
243 format+="%%(%s)s" % (l)
244
245 if self.opts.progress:
246 print "Printing\n\n"
247
248 header=format % dict(zip(cData[0].keys(),cData[0].keys()))
249 print header
250 print "-"*len(header)
251
252 for d in cData:
253 for k in d.keys():
254 d[k]=str(d[k])
255 print format % d
256
257 if self.opts.diskusage:
258 print "Total disk-usage:",totalDiskusage,"MB"
259