ENH: Added XSL script to convert DocBook to MarkDown
[freefoam.git] / tutorials / Allrun.py.in
blob1d5497bca5ff4fde681752b4e94c00c99654292e
1 #!@PYTHON_EXECUTABLE@
3 import sys
4 import os
5 import os.path
6 import imp
7 import inspect
8 import re
9 sys.path.insert(0, '@FOAM_PYTHON_DIR@')
10 from FreeFOAM.compat import *
11 import FreeFOAM.tutorial
12 import FreeFOAM.util
14 class LogParserError(Exception):
15 """Thrown when parsing of the log file failed."""
16 def __init__(self, msg):
17 Exception.__init__(self, msg)
18 def __str__(self):
19 return self.args[0]
22 class AllTutorialsRunner(FreeFOAM.tutorial.TutorialRunner):
23 def __init__(self):
24 FreeFOAM.tutorial.TutorialRunner.__init__(self)
25 self.tutorials_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
27 def main(self):
28 # prevent python from creating byte-compiled files (python >= 2.6)
29 try:
30 sys.dont_write_bytecode = True
31 except:
32 pass
33 # Recursively run all tutorials
34 pwd = os.getcwd()
35 i = 0
36 for parent, dirs, files in os.walk(self.tutorials_dir):
37 if parent == self.tutorials_dir:
38 continue
39 if 'Allrun' in files:
40 # don't recurse
41 del dirs[:]
42 i += 1
43 os.chdir(parent)
44 f = open('Allrun', 'rt')
45 try:
46 m = imp.load_module('Allrun'+str(i), f, f.name,
47 (os.path.splitext(f.name)[1], 'r', imp.PY_SOURCE))
48 if hasattr(m, 'register_cases') and inspect.isfunction(
49 m.register_cases):
50 m.register_cases(self)
51 else:
52 for d in dir(m):
53 a = getattr(m, d)
54 if inspect.isclass(a) and (
55 FreeFOAM.tutorial.CaseRunner in inspect.getmro(a)):
56 self.add_case(a())
57 except Exception, e:
58 FreeFOAM.util.cecho(
59 '${RED}*** Error ***${NORMAL} In '+os.path.abspath(f.name))
60 raise
61 os.chdir(pwd)
63 ret = FreeFOAM.tutorial.TutorialRunner.main(self)
65 if not self.did_run:
66 return ret
68 # Analyse all log files
69 testReport = open(
70 os.path.join(self.tutorials_dir, 'testLoopReport'), 'wt')
71 logs = open(os.path.join(self.tutorials_dir, 'logs'), 'wt')
72 for parent, dirs, files in os.walk(self.tutorials_dir):
73 for f in files:
74 if f[0:4] == 'log.':
75 # skip test directories if not in test_mode and vice versa
76 if bool(parent[-5:] == '-test') ^ bool(self.test_mode):
77 continue
78 l = os.path.join(parent, f)
79 logs.writelines(open(l, 'rt').readlines())
80 logs.write('\n\n')
81 self._logReport(l, testReport)
82 logs.close()
83 testReport.close()
85 if self.test_mode:
86 self._testReport()
88 def _logReport(self, logName, reportFile):
89 """Extracts useful info from log file `logName` and writes it to file
90 object `reportFile`."""
91 case = None
92 app = None
93 fatalError = False
94 singularity = False
95 completed = False
96 success = False
97 time = ''
98 for l in open(logName, 'rt'):
99 m = re.match(
100 r'(?:APPLICATION:\s+(?P<app>\S+)|CASE:\s+(?P<case>\S+))', l)
101 if m:
102 d = m.groupdict()
103 if d['app']:
104 app = d['app']
105 elif d['case']:
106 case = d['case']
107 if re.search('FOAM FATAL', l):
108 fatalError = True
109 elif re.search(r'U[xyz](:|\s)*solution singularity', l):
110 singularity = True
111 elif re.match(r'^\s*[Ee]nd\s*\.?\s*$', l):
112 completed = True
113 elif re.match(r'^REPORT:\s+SUCCESS', l):
114 success = True
115 else:
116 m = re.search(r'Execution\S+\s+=\s+(?P<time>\S+\s+\S+)', l)
117 if m:
118 time = m.group('time')
120 if bool(case) != bool(app):
121 raise LogParserError('Failed to parse "%s"'%logName)
122 elif not case and not app:
123 # skip this
124 return
126 appAndCase = "Application %s - case %s"%(app,
127 os.path.relpath(case, self.tutorials_dir))
129 if fatalError:
130 reportFile.write('%s: ** FOAM FATAL ERROR **\n'%appAndCase)
131 elif singularity:
132 reportFile.write('%s: ** Solution singularity **\n'%appAndCase)
133 elif completed and success:
134 reportFile.write('%s: completed'%appAndCase)
135 if len(time) > 0:
136 reportFile.write(' in %s\n'%time)
137 else:
138 reportFile.write('\n')
139 else:
140 reportFile.write('%s: unconfirmed completion\n'%appAndCase)
142 def _testReport(self):
143 fv_schemes = (
144 'gradScheme',
145 'divScheme',
146 'laplacianScheme',
147 'interpolationScheme',
148 'snGradScheme',
149 'fluxRequired',
151 solvers_tmp = {}
152 schemes_tmp = {}
153 # traverse tree
154 for parent, dirs, files in os.walk(self.tutorials_dir):
155 # skip test directories if not in test_mode and vice versa
156 if bool(parent[-5:] == '-test') ^ bool(self.test_mode):
157 continue
158 # loop over files
159 for f in files:
160 if f[0:4] == 'log.':
161 # scan log for APPLICATION and then for schemes and solver
162 # information
163 log = open(os.path.join(parent, f), 'rt')
164 app = None
165 for l in log:
166 if app == None:
167 m = re.match(r'APPLICATION:\s*(?P<app>\S+)', l)
168 if m:
169 app = os.path.basename(m.group('app'))
170 if app not in solvers_tmp:
171 solvers_tmp[app] = set()
172 schemes_tmp[app] = {}
173 else:
174 for st in fv_schemes:
175 if re.search(st, l):
176 if st not in schemes_tmp[app]:
177 schemes_tmp[app][st] = set()
178 schemes_tmp[app][st].add(l.split()[-1])
179 m = re.match(r'(\S+):\s+Solving for', l)
180 if m:
181 solvers_tmp[app].add(m.group(1))
182 # write schemes and solvers information per application
183 SC = open(os.path.join(self.tutorials_dir, 'FvSchemes'), 'wt')
184 SO = open(os.path.join(self.tutorials_dir, 'FvSolution'), 'wt')
185 applications = solvers_tmp.keys()
186 applications.sort()
187 for app in applications:
188 SC.write('%s\n'%app)
189 SO.write('%s\n'%app)
190 for st in fv_schemes:
191 SC.write(' %s\n'%st)
192 if st in schemes_tmp[app] and len(schemes_tmp[app][st]) > 0:
193 tmp = list(schemes_tmp[app][st])
194 tmp.sort()
195 SC.write(' '+'\n '.join(tmp)+'\n')
196 if len(solvers_tmp[app]) > 0:
197 tmp = list(solvers_tmp[app])
198 tmp.sort()
199 SO.write(' '+'\n '.join(tmp)+'\n')
200 SO.close()
201 SC.close()
203 if __name__ == '__main__':
204 os.chdir(os.path.abspath(os.path.dirname(sys.argv[0])))
205 sys.argv[0] = os.path.basename(sys.argv[0])
206 sys.exit(AllTutorialsRunner().main())
208 # ------------------- vim: set sw=3 sts=3 ft=python et: ------------ end-of-file