6 from parseConfigFile import parseConfigFile
7 from parseConfigFile import convertEnvFileToConfigFile
16 Define a specific exception class to manage exceptions related to SalomeRunner
18 class SalomeRunnerException(Exception):
19 """Report error messages to the user interface of SalomeRunner."""
24 The SalomeRunner class in an API to configure SALOME environment then
25 start SALOME using a single python command.
30 Initialize environment from a list of configuration files
31 identified by their names.
32 These files should be in appropriate (new .cfg) format.
33 However you can give old .sh environment files; in this case,
34 the SalomeRunner class will try to automatically convert them
35 to .cfg format before setting the environment.
37 def __init__(self, configFileNames=[]):
38 #it could be None explicitely (if user use multiples setEnviron...for standalone)
39 if configFileNames==None:
42 if len(configFileNames) == 0:
43 raise SalomeRunnerException("No configuration files given")
45 for filename in configFileNames:
46 basename, extension = os.path.splitext(filename)
47 if extension == ".cfg":
48 self.__setEnvironmentFromConfigFile(filename)
49 elif extension == ".sh":
50 #new convert procedures, temporary could be use not to be automatically deleted
51 temp = tempfile.NamedTemporaryFile(suffix='.cfg', delete=False)
52 #temp = tempfile.NamedTemporaryFile(suffix='.cfg')
54 convertEnvFileToConfigFile(filename, temp.name)
55 self.__setEnvironmentFromConfigFile(temp.name)
56 except ConfigParser.ParsingError, e:
57 self.getLogger().warning("Invalid token found when parsing file: %s\n"%(filename))
61 # Automatically cleans up the file
64 self.getLogger().warning("Unrecognized extension for configuration file: %s", filename)
68 # Run this module as a script, in order to use appropriate Python interpreter
69 # according to current path (initialized from environment files).
70 absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
71 proc = subprocess.Popen(['python', absoluteAppliPath+'/bin/salome/salomeRunner.py', pickle.dumps(self), pickle.dumps(args)], shell=False, close_fds=True)
75 """Append value to PATH environment variable"""
76 def addToPath(self, value):
77 self.__addToReserved('PATH', value)
80 """Append value to LD_LIBRARY_PATH environment variable"""
81 def addToLdLibraryPath(self, value):
82 self.__addToReserved('LD_LIBRARY_PATH', value)
85 """Append value to PYTHONPATH environment variable"""
86 def addToPythonPath(self, value):
87 self.__addToReserved('PYTHONPATH', value)
90 """Append value to TCLLIBPATH environment variable"""
91 def addToTclLibPath(self, value):
92 self.__addToReservedTclTk('TCLLIBPATH', value)
95 """Append value to TKLIBPATH environment variable"""
96 def addToTkLibPath(self, value):
97 self.__addToReservedTclTk('TKLIBPATH', value)
100 """Set environment variable to value"""
101 def setEnviron(self, name, value, overwrite=True):
102 env = os.getenv(name, '')
103 if env and not overwrite:
104 self.getLogger().warning("Environment variable already existing (and not overwritten): %s, %s", name, value)
108 self.getLogger().warning("Environment variable overwriting: %s, %s", name, value)
110 value = os.path.expandvars(value) # expand environment variables
111 self.getLogger().debug("Set environment variable: %s=%s", name, value)
112 os.environ[name] = value
115 """Unset environment variable"""
116 def unsetEnviron(self, name):
117 if os.environ.has_key(name):
121 ###################################
122 # This begins the private section #
123 ###################################
125 def _usage(self, unused=[]):
126 exeName = os.path.splitext(os.path.basename(__file__))[0]
129 Usage: %s [command] [options] [--config=file1,...,filen]
132 start Launches SALOME virtual application [DEFAULT]
133 shell Executes a script under SALOME application environment
134 connect Connects a Python console to the active SALOME session
135 killall Kill all SALOME running sessions
136 info Display some information about SALOME
137 help Show this message
138 coffee Yes! SALOME can also make coffee!!"\
145 def __parseArguments(self, args):
146 if len(args) == 0 or args[0].startswith("-"):
152 availableCommands = {
153 'start' : '_runAppli',
154 'shell' : '_runSession',
155 'connect' : '_runConsole',
156 'killall': '_killAll',
159 'coffee' : '_makeCoffee'
162 if not command in availableCommands.keys():
163 self.getLogger().error("Unrecognized command: %s.", command)
167 return availableCommands[command], options
172 Args consist in a mandatory command followed by optionnal parameters.
173 See usage for details on commands.
175 def _getStarted(self, args):
176 command, options = self.__parseArguments(args)
180 if args and args[0] in ["-h","--help","help"]:
183 # try to default to "start" command
184 command = "_runAppli"
187 getattr(self, command)(options) # run appropriate method
188 except AttributeError:
189 self.getLogger().error("Method %s is not implemented.", command)
191 except SystemExit, exc:
193 sys.exit(0) #catch sys.exit(0) happy end no warning
195 self.getLogger().warning("SystemExit 1 in method %s.", command)
198 self.getLogger().error("Unexpected error:")
200 traceback.print_exc()
204 def __setEnvironmentFromConfigFile(self, filename):
205 unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved=['PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH'])
208 for var in unsetVars:
209 self.unsetEnviron(var)
212 for reserved in reservedDict:
213 a = filter(None, reservedDict[reserved]) # remove empty elements
214 reformattedVals = ':'.join(a)
215 self.__addToReserved(reserved, reformattedVals)
218 for key,val in configVars:
219 self.setEnviron(key, val, overwrite=True)
222 sys.path[:0] = os.getenv('PYTHONPATH','').split(':')
225 def __addToReserved(self, name, value):
229 value = os.path.expandvars(value) # expand environment variables
230 self.getLogger().debug("Add to %s: %s", name, value)
231 env = os.getenv(name, None)
233 os.environ[name] = value
235 os.environ[name] = value + os.pathsep + env
238 def __addToReservedTclTk(self, name, value):
242 value = os.path.expandvars(value) # expand environment variables
243 self.getLogger().debug("Add to %s: %s", name, value)
244 env = os.getenv(name, None)
245 #http://computer-programming-forum.com/57-tcl/1dfddc136afccb94.htm
246 #Tcl treats the contents of that variable as a list. Be happy, for you can now use drive letters on windows.
248 os.environ[name] = value
250 os.environ[name] = value + " " + env #explicitely whitespace
253 def _runAppli(self, args=[]):
254 # Initialize SALOME environment
255 sys.argv = ['runSalome'] + args
260 runSalome.runSalome()
263 def _runSession(self, args=[]):
264 sys.argv = ['runSession'] + args
266 runSession.configureSession(args)
273 # if exe does not contain any slashes (/), search in PATH
274 # if exe contains slashes:
275 # if exe begins with a slash, use this absolute path
276 # else build absolute path relative to current working directory
277 if (os.sep in exe) and (exe[0] is not os.sep):
278 args[0] = os.getcwd() + os.sep + exe
280 proc = subprocess.Popen(args, shell=False, close_fds=True)
283 absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
284 cmd = ["/bin/bash", "--rcfile", absoluteAppliPath + "/.bashrc" ]
285 proc = subprocess.Popen(cmd, shell=False, close_fds=True)
289 def _runConsole(self, args=[]):
290 # Initialize SALOME environment
291 sys.argv = ['runConsole'] + args
299 def _killAll(self, args=[]):
300 #self._runAppli(['-k'] + args)
301 from killSalome import killAllPorts
305 def _showInfo(self, args=[]):
306 print "Running with python", platform.python_version()
307 self._runAppli(["--version"])
310 def _makeCoffee(self, args=[]):
313 print " ___...(-------)-....___"
314 print " .-\"\" ) ( \"\"-."
315 print " .-\'``\'|-._ ) _.-|"
316 print " / .--.| `\"\"---...........---\"\"` |"
324 print " _..---\"\"` \\ /`\"\"---.._"
325 print " .-\' \\ / \'-."
326 print " : `-.__ __.-\' :"
327 print " : ) \"\"---...---\"\" ( :"
328 print " \'._ `\"--...___...--\"` _.\'"
329 print " \\\"\"--..__ __..--\"\"/"
330 print " \'._ \"\"\"----.....______.....----\"\"\" _.\'"
331 print " `\"\"--..,,_____ _____,,..--\"\"`"
332 print " `\"\"\"----\"\"\"`"
336 # Add the following two methods since logger is not pickable
337 # Ref: http://stackoverflow.com/questions/2999638/how-to-stop-attributes-from-being-pickled-in-python
338 def __getstate__(self):
339 d = dict(self.__dict__)
340 if hasattr(self, '_logger'):
344 def __setstate__(self, d):
345 self.__dict__.update(d) # I *think* this is a safe way to do it
347 # Excluding self._logger from pickle operation imply using the following method to access logger
349 if not hasattr(self, '_logger'):
350 self._logger = logging.getLogger(__name__)
351 #self._logger.setLevel(logging.DEBUG)
357 if __name__ == "__main__":
358 if len(sys.argv) == 3:
359 runner = pickle.loads(sys.argv[1])
360 args = pickle.loads(sys.argv[2])
361 runner._getStarted(args)
363 SalomeRunner()._usage()