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