1 """
2 Application-class that implements pyFoamCreateModuleFile.py
3
4 Generate a Modules modulefile for OpenFOAM using differences in environment
5 variables before and after sourcing the main OpenFOAM configuration file
6
7 For more information on Modules, visit the Environment Modules Project:
8 http://modules.sourceforge.net
9
10 Usage : pyFoamCreateModuleFile.py OpenFOAM_CfgFile moduleFile
11
12 For example: pyFoamCreateModuleFile.py ./bashrc /tmp/module
13
14 Warning #1: This command will not work if your OpenFOAM environment variabales are already
15 initialized.
16
17 Warning #2: This command will not work if you are using the superuser account (aka: root)
18
19 Author:
20 Martin Beaudoin, Hydro-Quebec, 2012. All rights reserved
21
22 """
23
24 import os
25 import sys
26 import string
27 import re
28 from optparse import OptionGroup
29
30 from PyFoamApplication import PyFoamApplication
31 from PyFoam.RunDictionary.ParsedParameterFile import ParsedParameterFile
32 from PyFoam.Basics.Utilities import execute
33 from sets import Set
34 from os import path
35
38 description="""
39 Create a Modules modulefile for OpenFOAM. Input parameter 'OpenFOAM configuration file': bashrc or cshrc file for OpenFOAM; usually $WM_PROJECT_DIR/etc/bashrc or $WM_PROJECT_DIR/etc/cshrc. Output parameter 'modulefile': the resulting module file. For more information on Modules, visit the Environment Modules Project: http://http://modules.sourceforge.net
40 """
41 PyFoamApplication.__init__(self,
42 args=args,
43 description=description,
44 usage="%prog OpenFOAM_cfgFile modulefile",
45 interspersed=True,
46 changeVersion=False,
47 nr=2)
48
50 module=OptionGroup(self.parser,
51 "Module",
52 "Options specific for the module-utility")
53 self.parser.add_option_group(module)
54
55 module.add_option("--csh",
56 action="store_true",
57 dest="useCshell",
58 default=False,
59 help='Use csh instead of bash for activating the OpenFOAM configuration')
60 module.add_option("--clear-environment",
61 action="store_true",
62 dest="clearEnvironment",
63 default=False,
64 help='Attempt to clear the environment of all traces of an OpenFOAM-installation before proceeding. This is no substitute to having a clean environment')
65
66
68 """Remove all duplicates from PATH env var. Order preserving"""
69 checked = []
70 for e in pathEnvVar.split(':'):
71 if e not in checked:
72 checked.append(e)
73
74 return string.join(checked, ':')
75
77 """Remove components from PATH env var where a substring is present. Order preserving"""
78 keepComponents = []
79 pathComponents = pathEnvVar.split(':')
80
81 for e in pathComponents:
82 if e.find(removeSubStr) < 0:
83 keepComponents.append(e)
84
85 return string.join(keepComponents, ':')
86
88 """Remove components from PATH env var. Order preserving"""
89 keepComponents = []
90 pathComponents = pathEnvVar.split(':')
91 removeComponents = removePathComponents.split(':')
92
93 for e in pathComponents:
94 if e not in removeComponents:
95 keepComponents.append(e)
96
97 return string.join(keepComponents, ':')
98
99
101 """Write Modules file header"""
102 fid.write("#%Module1.0\n")
103 fid.write("\n")
104 fid.write("proc ModulesHelp { } {\n")
105 fid.write(" puts stderr \"OpenFOAM version " + version + "\"\n")
106 fid.write("}\n")
107 fid.write("\n")
108 fid.write("module-whatis \"OpenFOAM version " + version + "\"\n")
109
110
116
117 - def writeModuleEnvironmentEntry(self, fid, envVarDict, homeVar, userVar):
118 """Write Modules file environment variables"""
119 fid.write("\n")
120 fid.write("set HOME \"$env(HOME)\"\n")
121 fid.write("set USER \"$env(USER)\"\n")
122 fid.write("\n")
123 fid.write("# Environment variables\n")
124
125
126 pathVars = {}
127
128
129 keylist = envVarDict.keys()
130 keylist.sort()
131 for k in keylist:
132 value = envVarDict[k][0]
133
134
135 value = value.replace(homeVar, "$HOME")
136
137
138 value = value.replace(userVar, "$USER")
139
140 if k.find('PATH') > -1 and value != ":":
141 pathVars[k] = value
142 else:
143 fid.write("setenv " + k + " " + "\"" + value + "\""+ "\n")
144
145
146 fid.write("\n")
147 fid.write("# Various PATH variables\n")
148 for k in pathVars:
149 value = pathVars[k]
150 if len(value) > 0:
151 fid.write("prepend-path " + k + " " + "\"" + pathVars[k] + "\""+ "\n")
152 fid.write("\n")
153
154
155
156
157
158
159
160 fid.write("# Temporary TCL variables for the environment variables\n")
161 fid.write("# Module will need this for the aliases when parsing this file\n")
162 for k in keylist:
163 fid.write("if [info exists env(" + k + ")] {set " + k + ' \"$env(' + k + ')\"}\n')
164 fid.write("\n")
165
166
167 - def writeModuleAliasEntry(self, fid, aliasesVarDict, homeVar, userVar):
168 """Write Modules file aliases"""
169 fid.write("# Aliases\n")
170
171
172 keylist = aliasesVarDict.keys()
173 keylist.sort()
174 for k in keylist:
175 value = aliasesVarDict[k][0]
176
177
178 value = value.replace(homeVar, "$HOME")
179
180
181 value = value.replace(userVar, "$USER")
182
183 fid.write("set-alias " + k + " " + "\"" + value + "\""+ "\n")
184
186 cfgFile=self.parser.getArgs()[0]
187 moduleFile=self.parser.getArgs()[1]
188 useCsh = self.opts.useCshell
189
190 if self.opts.clearEnvironment:
191 self.warning("Clearing environment of variables that might come from an OpenFAOM-installation. Nevertheless it is preferable to use a clean environment")
192 try:
193 oldVersion=os.environ["WM_PROJECT_VERSION"]
194 except KeyError:
195 self.warning("Seems to be a clean environment anyway")
196 oldVersion=None
197
198 if oldVersion:
199 for e in os.environ.keys():
200 for p in ["WM_","FOAM_"]:
201 if e.find(p)==0:
202 del os.environ[e]
203 break
204 for p in ["PATH","DYLD_LIBRARY_PATH","LD_LIBRARY_PATH","MANPATH","PV_PLUGIN_PATH"]:
205 if p in os.environ:
206 lst=os.environ[p].split(":")
207 os.environ[p]=":".join([l for l in lst if l.find(oldVersion)<0])
208
209 if path.exists(cfgFile) and path.isfile(cfgFile) and os.access(cfgFile, os.R_OK):
210 print " Using file " + cfgFile + " for loading the OpenFOAM environment"
211
212
213 fileData = open(cfgFile).read()
214 if not useCsh and "setenv" in fileData:
215 self.error(" Error: Detecting 'setenv' instructions in this bash file. Please provide a configuration file compatible for bash, or use the --csh option.")
216 elif useCsh and "export" in fileData:
217 self.error(" Error: Detecting 'export' instructions in this csh file. Please provide a configuration file compatible for csh.")
218 else:
219 print " The configuration file seems ok"
220 else:
221 self.error(" Error: Cannot access file: " + cfgFile)
222
223
224
225 if os.getenv("WM_PROJECT") != None:
226 self.error(""" Error: Cannot run with OpenFOAM environment variables already present
227 You need to run this script from a clean environment""")
228
229
230
231
232
233
234
235 if os.getenv("USER") == "root":
236 self.error(""" Error: You should not run this script from the 'root' account.
237 Please invoke this pyFoam command from a plain OpenFOAM user account.
238 Then, make the result file available to the super user (root) of the"
239 destination host in order to install the modules configuration files.""")
240
241
242
243 shellCmd = 'bash -c'
244 sourceCmd = '.'
245
246 if useCsh:
247 shellCmd = 'csh -c'
248 sourceCmd = 'source'
249
250 oldEnv=Set(execute(shellCmd + ' "env|sort"'))
251 oldAliases=Set(execute(shellCmd + ' "alias|sort"'))
252
253
254 newEnv=Set(execute(shellCmd + ' \"' + sourceCmd + ' ' + cfgFile + '; env|sort"'))
255 newAliases=Set(execute(shellCmd + ' \"' + sourceCmd + ' ' + cfgFile + '; alias|sort"'))
256
257
258
259 oldPath = {}
260 newPath = {}
261 homeVar = ""
262 userVar = ""
263
264 for v in oldEnv:
265 if v.find('=') > -1:
266 key, value = v.split('=', 1)
267
268
269 if key.find('PATH') > -1:
270 oldPath[key] = value.replace('\n', '')
271
272
273
274
275
276
277
278
279
280
281
282 oldPath[key] = self.removeComponentWithSubstrFromPathEnvVar(oldPath[key], 'PyFoam')
283
284
285 if key == 'HOME':
286 homeVar = value.replace('\n', '')
287
288
289 if key == 'USER':
290 userVar = value.replace('\n', '')
291
292
293
294 moduleEnv=newEnv - oldEnv
295 moduleAliases=newAliases - oldAliases
296
297
298 envVar = {}
299
300
301 aliasesVar = {}
302
303
304 for v in moduleEnv:
305 if v.find('=') > -1:
306 key, value = v.split('=')
307
308
309 value = value.replace('\n', '')
310
311
312 if key.find('PATH') > -1:
313 newPath[key] = value
314 else:
315 envVar.setdefault(key, []).append(value)
316
317
318 for v in newPath:
319 if v in oldPath:
320
321 newPath[v] = self.removeComponentFromPathEnvVar(newPath[v], oldPath[v])
322
323
324 newPath[v] = self.uniqifyPathEnvVar(newPath[v])
325 envVar.setdefault(v, []).append(newPath[v])
326
327
328 for v in moduleAliases:
329 if v.find('=') > -1:
330 key, value = v.split('=', 1)
331
332
333 key = key.replace("alias ", "")
334 value = value.replace('\n', "")
335 value = value.replace('\'', "")
336 aliasesVar.setdefault(key, []).append(value)
337
338
339 print " Generating modulefile: " , moduleFile
340
341 f = open(moduleFile, 'w')
342
343 self.writeModuleFileHeader(f, envVar["WM_PROJECT_VERSION"][0])
344 self.writeModuleEnvironmentEntry(f, envVar, homeVar, userVar)
345 self.writeModuleAliasEntry(f, aliasesVar, homeVar, userVar)
346 self.writeModuleFileFooter(f)
347
348 f.close()
349 print " Done\n"
350