6 from parseConfigFile import parseConfigFile
7 from parseConfigFile import convertEnvFileToConfigFile
14 from salomeLauncherUtils import SalomeRunnerException
15 from salomeLauncherUtils import getScriptsAndArgs, formatScriptsAndArgs
18 The SalomeRunner class in an API to configure SALOME environment then
19 start SALOME using a single python command.
24 Initialize environment from a list of configuration files
25 identified by their names.
26 These files should be in appropriate (new .cfg) format.
27 However you can give old .sh environment files; in this case,
28 the SalomeRunner class will try to automatically convert them
29 to .cfg format before setting the environment.
31 def __init__(self, configFileNames=[]):
32 #it could be None explicitely (if user use multiples setEnviron...for standalone)
33 if configFileNames==None:
36 if len(configFileNames) == 0:
37 raise SalomeRunnerException("No configuration files given")
39 for filename in configFileNames:
40 basename, extension = os.path.splitext(filename)
41 if extension == ".cfg":
42 self.__setEnvironmentFromConfigFile(filename)
43 elif extension == ".sh":
44 #new convert procedures, temporary could be use not to be automatically deleted
45 #temp = tempfile.NamedTemporaryFile(suffix='.cfg', delete=False)
46 temp = tempfile.NamedTemporaryFile(suffix='.cfg')
48 convertEnvFileToConfigFile(filename, temp.name)
49 self.__setEnvironmentFromConfigFile(temp.name)
50 except ConfigParser.ParsingError, e:
51 self.getLogger().warning("Invalid token found when parsing file: %s\n"%(filename))
55 # Automatically cleans up the file
58 self.getLogger().warning("Unrecognized extension for configuration file: %s", filename)
62 # Run this module as a script, in order to use appropriate Python interpreter
63 # according to current path (initialized from environment files).
64 absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
65 proc = subprocess.Popen(['python', absoluteAppliPath+'/bin/salome/salomeRunner.py', pickle.dumps(self), pickle.dumps(args)], shell=False, close_fds=True)
69 """Append value to PATH environment variable"""
70 def addToPath(self, value):
71 self.__addToReserved('PATH', value)
74 """Append value to LD_LIBRARY_PATH environment variable"""
75 def addToLdLibraryPath(self, value):
76 self.__addToReserved('LD_LIBRARY_PATH', value)
79 """Append value to PYTHONPATH environment variable"""
80 def addToPythonPath(self, value):
81 self.__addToReserved('PYTHONPATH', value)
84 """Append value to TCLLIBPATH environment variable"""
85 def addToTclLibPath(self, value):
86 self.__addToReservedTclTk('TCLLIBPATH', value)
89 """Append value to TKLIBPATH environment variable"""
90 def addToTkLibPath(self, value):
91 self.__addToReservedTclTk('TKLIBPATH', value)
94 """Set environment variable to value"""
95 def setEnviron(self, name, value, overwrite=False):
96 env = os.getenv(name, '')
97 if env and not overwrite:
98 self.getLogger().warning("Environment variable already existing (and not overwritten): %s=%s", name, value)
102 self.getLogger().warning("Overwriting environment variable: %s=%s", name, value)
104 value = os.path.expandvars(value) # expand environment variables
105 self.getLogger().debug("Set environment variable: %s=%s", name, value)
106 os.environ[name] = value
109 """Unset environment variable"""
110 def unsetEnviron(self, name):
111 if os.environ.has_key(name):
115 ###################################
116 # This begins the private section #
117 ###################################
119 def _usage(self, unused=[]):
120 #exeName = os.path.splitext(os.path.basename(__file__))[0]
123 Usage: salome [command] [options] [--config=file1,...,filen]
126 start Launches SALOME virtual application [DEFAULT]
127 shell Executes a script under SALOME application environment
128 connect Connects a Python console to the active SALOME session
129 killall Kill all SALOME running sessions
130 info Display some information about SALOME
131 help Show this message
132 coffee Yes! SALOME can also make coffee!!"\
139 def __parseArguments(self, args):
140 if len(args) == 0 or args[0].startswith("-"):
146 availableCommands = {
147 'start' : '_runAppli',
148 'shell' : '_runSession',
149 'connect' : '_runConsole',
150 'killall': '_killAll',
153 'coffee' : '_makeCoffee'
156 if not command in availableCommands.keys():
160 return availableCommands[command], options
165 Args consist in a mandatory command followed by optionnal parameters.
166 See usage for details on commands.
168 def _getStarted(self, args):
169 command, options = self.__parseArguments(args)
173 if args and args[0] in ["-h","--help","help"]:
176 # try to default to "start" command
177 command = "_runAppli"
180 res = getattr(self, command)(options) # run appropriate method
181 return res or (None, None)
182 except SystemExit, exc:
184 sys.exit(0) #catch sys.exit(0) happy end no warning
186 self.getLogger().warning("SystemExit 1 in method %s.", command)
188 except StandardError:
189 self.getLogger().error("Unexpected error:")
191 traceback.print_exc()
193 except SalomeRunnerException, e:
194 self.getLogger().error(e)
198 def __setEnvironmentFromConfigFile(self, filename):
199 unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved=['PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH'])
202 for var in unsetVars:
203 self.unsetEnviron(var)
206 for reserved in reservedDict:
207 a = filter(None, reservedDict[reserved]) # remove empty elements
208 reformattedVals = ':'.join(a)
209 self.__addToReserved(reserved, reformattedVals)
212 for key,val in configVars:
213 self.setEnviron(key, val, overwrite=True)
216 sys.path[:0] = os.getenv('PYTHONPATH','').split(':')
219 def __addToReserved(self, name, value):
223 value = os.path.expandvars(value) # expand environment variables
224 self.getLogger().debug("Add to %s: %s", name, value)
225 env = os.getenv(name, None)
227 os.environ[name] = value
229 os.environ[name] = value + os.pathsep + env
232 def __addToReservedTclTk(self, name, value):
236 value = os.path.expandvars(value) # expand environment variables
237 self.getLogger().debug("Add to %s: %s", name, value)
238 env = os.getenv(name, None)
239 #http://computer-programming-forum.com/57-tcl/1dfddc136afccb94.htm
240 #Tcl treats the contents of that variable as a list. Be happy, for you can now use drive letters on windows.
242 os.environ[name] = value
244 os.environ[name] = value + " " + env #explicitely whitespace
247 def _runAppli(self, args=[]):
248 # Initialize SALOME environment
249 sys.argv = ['runSalome'] + args
254 runSalome.runSalome()
257 def _runSession(self, args=[]):
258 sys.argv = ['runSession'] + args
260 runSession.configureSession(args)
265 scriptArgs = getScriptsAndArgs(args)
266 command = formatScriptsAndArgs(scriptArgs)
268 proc = subprocess.Popen(command, shell=True, close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
269 return proc.communicate()
271 absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
272 cmd = ["/bin/bash", "--rcfile", absoluteAppliPath + "/.bashrc" ]
273 proc = subprocess.Popen(cmd, shell=False, close_fds=True)
277 def _runConsole(self, args=[]):
278 # Initialize SALOME environment
279 sys.argv = ['runConsole'] + args
287 def _killAll(self, args=[]):
288 from killSalome import killAllPorts
292 def _showInfo(self, args=[]):
293 print "Running with python", platform.python_version()
294 self._runAppli(["--version"])
297 def _makeCoffee(self, args=[]):
300 print " ___...(-------)-....___"
301 print " .-\"\" ) ( \"\"-."
302 print " .-\'``\'|-._ ) _.-|"
303 print " / .--.| `\"\"---...........---\"\"` |"
311 print " _..---\"\"` \\ /`\"\"---.._"
312 print " .-\' \\ / \'-."
313 print " : `-.__ __.-\' :"
314 print " : ) \"\"---...---\"\" ( :"
315 print " \'._ `\"--...___...--\"` _.\'"
316 print " \\\"\"--..__ __..--\"\"/"
317 print " \'._ \"\"\"----.....______.....----\"\"\" _.\'"
318 print " `\"\"--..,,_____ _____,,..--\"\"`"
319 print " `\"\"\"----\"\"\"`"
323 # Add the following two methods since logger is not pickable
324 # Ref: http://stackoverflow.com/questions/2999638/how-to-stop-attributes-from-being-pickled-in-python
325 def __getstate__(self):
326 d = dict(self.__dict__)
327 if hasattr(self, '_logger'):
331 def __setstate__(self, d):
332 self.__dict__.update(d) # I *think* this is a safe way to do it
334 # Excluding self._logger from pickle operation imply using the following method to access logger
336 if not hasattr(self, '_logger'):
337 self._logger = logging.getLogger(__name__)
338 #self._logger.setLevel(logging.DEBUG)
339 self._logger.setLevel(logging.ERROR)
345 if __name__ == "__main__":
346 if len(sys.argv) == 3:
347 runner = pickle.loads(sys.argv[1])
348 args = pickle.loads(sys.argv[2])
349 (out, err) = runner._getStarted(args)
351 sys.stdout.write(out)
353 sys.stderr.write(err)
355 SalomeRunner()._usage()