FIX: Typos in asciidoc conf file dependencies
[freefoam.git] / tutorials / Allrun.py.in
blob5f3b98c44b6c51f1b5d2f2e7847cfa6bb04280b5
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 FreeFOAM.tutorial.TutorialRunner.main(self)
65 # Analyse all log files
66 testReport = open(
67 os.path.join(self.tutorials_dir, 'testLoopReport'), 'wt')
68 logs = open(os.path.join(self.tutorials_dir, 'logs'), 'wt')
69 for parent, dirs, files in os.walk(self.tutorials_dir):
70 for f in files:
71 if f[0:4] == 'log.':
72 # skip test directories if not in test_mode and vice versa
73 if bool(parent[-5:] == '-test') ^ bool(self.test_mode):
74 continue
75 l = os.path.join(parent, f)
76 logs.writelines(open(l, 'rt').readlines())
77 logs.write('\n\n')
78 self._logReport(l, testReport)
79 logs.close()
80 testReport.close()
82 if self.test_mode:
83 self._testReport()
85 def _logReport(self, logName, reportFile):
86 """Extracts useful info from log file `logName` and writes it to file
87 object `reportFile`."""
88 case = None
89 app = None
90 fatalError = False
91 singularity = False
92 completed = False
93 success = False
94 time = ''
95 for l in open(logName, 'rt'):
96 m = re.match(
97 r'(?:APPLICATION:\s+(?P<app>\S+)|CASE:\s+(?P<case>\S+))', l)
98 if m:
99 d = m.groupdict()
100 if d['app']:
101 app = d['app']
102 elif d['case']:
103 case = d['case']
104 if re.search('FOAM FATAL', l):
105 fatalError = True
106 elif re.search(r'U[xyz](:|\s)*solution singularity', l):
107 singularity = True
108 elif re.match(r'^\s*[Ee]nd\s*\.?\s*$', l):
109 completed = True
110 elif re.match(r'^REPORT:\s+SUCCESS', l):
111 success = True
112 else:
113 m = re.search(r'Execution\S+\s+=\s+(?P<time>\S+\s+\S+)', l)
114 if m:
115 time = m.group('time')
117 if bool(case) != bool(app):
118 raise LogParserError('Failed to parse "%s"'%logName)
119 elif not case and not app:
120 # skip this
121 return
123 self.tutorials_dir = os.path.abspath(os.path.dirname(__file__))
124 appAndCase = "Application %s - case %s"%(app,
125 os.path.relpath(case, self.tutorials_dir))
127 if fatalError:
128 reportFile.write('%s: ** FOAM FATAL ERROR **\n'%appAndCase)
129 elif singularity:
130 reportFile.write('%s: ** Solution singularity **\n'%appAndCase)
131 elif completed and success:
132 reportFile.write('%s: completed'%appAndCase)
133 if len(time) > 0:
134 reportFile.write(' in %s\n'%time)
135 else:
136 reportFile.write('\n')
137 else:
138 reportFile.write('%s: unconfirmed completion\n'%appAndCase)
140 def _testReport(self):
141 fv_schemes = (
142 'gradScheme',
143 'divScheme',
144 'laplacianScheme',
145 'interpolationScheme',
146 'snGradScheme',
147 'fluxRequired',
149 solvers_tmp = {}
150 schemes_tmp = {}
151 # traverse tree
152 for parent, dirs, files in os.walk(self.tutorials_dir):
153 # skip test directories if not in test_mode and vice versa
154 if bool(parent[-5:] == '-test') ^ bool(self.test_mode):
155 continue
156 # loop over files
157 for f in files:
158 if f[0:4] == 'log.':
159 # scan log for APPLICATION and then for schemes and solver
160 # information
161 log = open(os.path.join(parent, f), 'rt')
162 app = None
163 for l in log:
164 if app == None:
165 m = re.match(r'APPLICATION:\s*(?P<app>\S+)', l)
166 if m:
167 app = os.path.basename(m.group('app'))
168 if app not in solvers_tmp:
169 solvers_tmp[app] = set()
170 schemes_tmp[app] = {}
171 else:
172 for st in fv_schemes:
173 if re.search(st, l):
174 if st not in schemes_tmp[app]:
175 schemes_tmp[app][st] = set()
176 schemes_tmp[app][st].add(l.split()[-1])
177 m = re.match(r'(\S+):\s+Solving for', l)
178 if m:
179 solvers_tmp[app].add(m.group(1))
180 # write schemes and solvers information per application
181 SC = open(os.path.join(self.tutorials_dir, 'FvSchemes'), 'wt')
182 SO = open(os.path.join(self.tutorials_dir, 'FvSolution'), 'wt')
183 applications = solvers_tmp.keys()
184 applications.sort()
185 for app in applications:
186 SC.write('%s\n'%app)
187 SO.write('%s\n'%app)
188 for st in fv_schemes:
189 SC.write(' %s\n'%st)
190 if st in schemes_tmp[app] and len(schemes_tmp[app][st]) > 0:
191 tmp = list(schemes_tmp[app][st])
192 tmp.sort()
193 SC.write(' '+'\n '.join(tmp)+'\n')
194 if len(solvers_tmp[app]) > 0:
195 tmp = list(solvers_tmp[app])
196 tmp.sort()
197 SO.write(' '+'\n '.join(tmp)+'\n')
198 SO.close()
199 SC.close()
201 if __name__ == '__main__':
202 os.chdir(os.path.abspath(os.path.dirname(sys.argv[0])))
203 sys.exit(AllTutorialsRunner().main())
205 # ------------------- vim: set sw=3 sts=3 ft=python et: ------------ end-of-file