ADD_SUBDIRECTORY(appliskel)
SALOME_CONFIGURE_FILE(VERSION.in VERSION INSTALL ${SALOME_INSTALL_BINS})
-SALOME_CONFIGURE_FILE(salomeLauncherUtils.py.in salomeLauncherUtils.py)
+SALOME_CONFIGURE_FILE(salomeContextUtils.py.in salomeContextUtils.py)
# ===============================================================
# Files to be installed
runSession.py
runConsole.py
salomeConsole.py
- ${CMAKE_CURRENT_BINARY_DIR}/salomeLauncherUtils.py
- salomeRunner.py
+ ${CMAKE_CURRENT_BINARY_DIR}/salomeContextUtils.py
+ salomeContext.py
salome_session.py
salome_utils.py
searchFreePort.py
# define folder to store omniorb config (initially in virtual application folder)
try:
- from salomeLauncherUtils import setOmniOrbUserPath
+ from salomeContextUtils import setOmniOrbUserPath
setOmniOrbUserPath()
except Exception, e:
print e
__initialize()
if args == ['--help']:
- from salomeRunner import usage
+ from salomeContext import usage
usage()
sys.exit(0)
- from salomeLauncherUtils import getConfigFileNames
+ from salomeContextUtils import getConfigFileNames
configFileNames, args, unexisting = getConfigFileNames(args, checkExistence=True)
if len(unexisting) > 0:
print "ERROR: unexisting configuration file(s): " + ', '.join(unexisting)
sys.exit(1)
- # Create a SalomeRunner which parses configFileNames to initialize environment
+ # Create a SalomeContext which parses configFileNames to initialize environment
try:
- from salomeRunner import SalomeRunner, SalomeRunnerException
- runner = SalomeRunner(configFileNames)
+ from salomeContext import SalomeContext, SalomeContextException
+ context = SalomeContext(configFileNames)
# Here set specific variables, if needed
- # runner.addToPath('mypath')
- # runner.addToLdLibraryPath('myldlibrarypath')
- # runner.addToPythonPath('mypythonpath')
- # runner.setEnviron('myvarname', 'value')
+ # context.addToPath('mypath')
+ # context.addToLdLibraryPath('myldlibrarypath')
+ # context.addToPythonPath('mypythonpath')
+ # context.setEnviron('myvarname', 'value')
# Start SALOME, parsing command line arguments
- runner.go(args)
- print 'Thank you for using SALOME!'
+ context.go(args)
+ #print 'Thank you for using SALOME!'
- except SalomeRunnerException, e:
+ except SalomeContextException, e:
import logging
logging.getLogger("salome").error(e)
sys.exit(1)
from salome_utils import verbose, setVerbose, getPortNumber, getHomeDir
-from salomeLauncherUtils import getScriptsAndArgs
+from salomeContextUtils import getScriptsAndArgs
# names of tags in XML configuration file
doc_tag = "document"
if not args['gui'] or not args['session_gui']:
toimport = args['pyscript']
- from salomeLauncherUtils import formatScriptsAndArgs
+ from salomeContextUtils import formatScriptsAndArgs
command = formatScriptsAndArgs(toimport)
if command:
proc = subprocess.Popen(command, shell=True)
searchFreePort(args, 0)
clt = useSalome(args, modules_list, modules_root_dir)
- if args.has_key('shutdown_servers') :
+ if args.has_key('shutdown_servers') :
var = args['shutdown_servers']
- if hasattr(var, 'delete') and callable(getattr(var, 'delete')) :
+ if hasattr(var, 'delete') and callable(getattr(var, 'delete')) :
var.delete()
return clt
# define folder to store omniorb config (initially in virtual application folder)
try:
- from salomeLauncherUtils import setOmniOrbUserPath
+ from salomeContextUtils import setOmniOrbUserPath
setOmniOrbUserPath()
except Exception, e:
print e
foreGround(clt, args)
pass
# --
- if args.has_key('shutdown_servers') :
+ if args.has_key('shutdown_servers') :
var = args['shutdown_servers']
- if hasattr(var, 'delete') and callable(getattr(var, 'delete')) :
+ if hasattr(var, 'delete') and callable(getattr(var, 'delete')) :
var.delete()
pass
#
--- /dev/null
+# Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+import os
+import sys
+import logging
+import ConfigParser
+
+from parseConfigFile import parseConfigFile
+from parseConfigFile import convertEnvFileToConfigFile
+
+import tempfile
+import pickle
+import subprocess
+import platform
+
+from salomeContextUtils import SalomeContextException
+from salomeContextUtils import getScriptsAndArgs, formatScriptsAndArgs
+
+def usage():
+ #exeName = os.path.splitext(os.path.basename(__file__))[0]
+
+ msg = '''\
+Usage: salome [command] [options] [--config=file1,...,filen]
+
+Commands:
+ start Launches SALOME virtual application [DEFAULT]
+ shell Executes a script under SALOME application environment
+ connect Connects a Python console to the active SALOME session
+ killall Kill all SALOME running sessions
+ info Display some information about SALOME
+ help Show this message
+ coffee Yes! SALOME can also make coffee!!"
+
+Use salome start --help or salome shell --help
+to show help on start and shell commands.
+'''
+
+ print msg
+#
+
+"""
+The SalomeContext class in an API to configure SALOME environment then
+start SALOME using a single python command.
+
+"""
+class SalomeContext:
+ """
+ Initialize environment from a list of configuration files
+ identified by their names.
+ These files should be in appropriate (new .cfg) format.
+ However you can give old .sh environment files; in this case,
+ the SalomeContext class will try to automatically convert them
+ to .cfg format before setting the environment.
+ """
+ def __init__(self, configFileNames=[]):
+ #it could be None explicitely (if user use multiples setEnviron...for standalone)
+ if configFileNames==None:
+ return
+
+ if len(configFileNames) == 0:
+ raise SalomeContextException("No configuration files given")
+
+ reserved=['PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'PV_PLUGIN_PATH']
+ for filename in configFileNames:
+ basename, extension = os.path.splitext(filename)
+ if extension == ".cfg":
+ self.__setEnvironmentFromConfigFile(filename, reserved)
+ elif extension == ".sh":
+ #new convert procedures, temporary could be use not to be automatically deleted
+ #temp = tempfile.NamedTemporaryFile(suffix='.cfg', delete=False)
+ temp = tempfile.NamedTemporaryFile(suffix='.cfg')
+ try:
+ convertEnvFileToConfigFile(filename, temp.name, reserved)
+ self.__setEnvironmentFromConfigFile(temp.name, reserved)
+ except ConfigParser.ParsingError, e:
+ self.getLogger().warning("Invalid token found when parsing file: %s\n"%(filename))
+ print e
+ print '\n'
+ finally:
+ # Automatically cleans up the file
+ temp.close()
+ else:
+ self.getLogger().warning("Unrecognized extension for configuration file: %s", filename)
+ #
+
+ def go(self, args):
+ # Run this module as a script, in order to use appropriate Python interpreter
+ # according to current path (initialized from environment files).
+ kill = False
+ for e in args:
+ if "--shutdown-server" in e:
+ kill = True
+ args.remove(e)
+
+ absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
+ proc = subprocess.Popen(['python', os.path.join(absoluteAppliPath,"bin","salome","salomeContext.py"), pickle.dumps(self), pickle.dumps(args)], shell=False, close_fds=True)
+ proc.communicate()
+ if kill:
+ self._killAll(args)
+ #
+
+ """Append value to PATH environment variable"""
+ def addToPath(self, value):
+ self.addToEnviron('PATH', value)
+ #
+
+ """Append value to LD_LIBRARY_PATH environment variable"""
+ def addToLdLibraryPath(self, value):
+ self.addToEnviron('LD_LIBRARY_PATH', value)
+ #
+
+ """Append value to PYTHONPATH environment variable"""
+ def addToPythonPath(self, value):
+ self.addToEnviron('PYTHONPATH', value)
+ #
+
+ """Set environment variable to value"""
+ def setEnviron(self, name, value, overwrite=False):
+ env = os.getenv(name, '')
+ if env and not overwrite:
+ self.getLogger().warning("Environment variable already existing (and not overwritten): %s=%s", name, value)
+ return
+
+ if env:
+ self.getLogger().warning("Overwriting environment variable: %s=%s", name, value)
+
+ value = os.path.expandvars(value) # expand environment variables
+ self.getLogger().debug("Set environment variable: %s=%s", name, value)
+ os.environ[name] = value
+ #
+
+ """Unset environment variable"""
+ def unsetEnviron(self, name):
+ if os.environ.has_key(name):
+ del os.environ[name]
+ #
+
+ """Append value to environment variable"""
+ def addToEnviron(self, name, value, separator=os.pathsep):
+ if value == '':
+ return
+
+ value = os.path.expandvars(value) # expand environment variables
+ self.getLogger().debug("Add to %s: %s", name, value)
+ env = os.getenv(name, None)
+ if env is None:
+ os.environ[name] = value
+ else:
+ os.environ[name] = value + separator + env
+ #
+
+ ###################################
+ # This begins the private section #
+ ###################################
+
+ def __parseArguments(self, args):
+ if len(args) == 0 or args[0].startswith("-"):
+ return None, args
+
+ command = args[0]
+ options = args[1:]
+
+ availableCommands = {
+ 'start' : '_runAppli',
+ 'shell' : '_runSession',
+ 'connect' : '_runConsole',
+ 'killall': '_killAll',
+ 'info': '_showInfo',
+ 'help': '_usage',
+ 'coffee' : '_makeCoffee'
+ }
+
+ if not command in availableCommands.keys():
+ command = "start"
+ options = args
+
+ return availableCommands[command], options
+ #
+
+ """
+ Run SALOME!
+ Args consist in a mandatory command followed by optionnal parameters.
+ See usage for details on commands.
+ """
+ def _getStarted(self, args):
+ command, options = self.__parseArguments(args)
+ sys.argv = options
+
+ if command is None:
+ if args and args[0] in ["-h","--help","help"]:
+ usage()
+ sys.exit(0)
+ # try to default to "start" command
+ command = "_runAppli"
+
+ try:
+ res = getattr(self, command)(options) # run appropriate method
+ return res or (None, None)
+ except SystemExit, exc:
+ if exc==0:
+ sys.exit(0) #catch sys.exit(0) happy end no warning
+ if exc==1:
+ self.getLogger().warning("SystemExit 1 in method %s.", command)
+ sys.exit(1)
+ except StandardError:
+ self.getLogger().error("Unexpected error:")
+ import traceback
+ traceback.print_exc()
+ sys.exit(1)
+ except SalomeContextException, e:
+ self.getLogger().error(e)
+ sys.exit(1)
+ #
+
+ def __setEnvironmentFromConfigFile(self, filename, reserved=[]):
+ unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved)
+
+ # unset variables
+ for var in unsetVars:
+ self.unsetEnviron(var)
+
+ # set environment
+ for reserved in reservedDict:
+ a = filter(None, reservedDict[reserved]) # remove empty elements
+ reformattedVals = ':'.join(a)
+ self.addToEnviron(reserved, reformattedVals)
+ pass
+
+ for key,val in configVars:
+ self.setEnviron(key, val, overwrite=True)
+ pass
+
+ sys.path[:0] = os.getenv('PYTHONPATH','').split(':')
+ #
+
+ def _runAppli(self, args=[]):
+ # Initialize SALOME environment
+ sys.argv = ['runSalome'] + args
+ import setenv
+ setenv.main(True)
+
+ import runSalome
+ runSalome.runSalome()
+ #
+
+ def _runSession(self, args=[]):
+ sys.argv = ['runSession'] + args
+ import runSession
+ runSession.configureSession(args)
+
+ import setenv
+ setenv.main(True)
+
+ scriptArgs = getScriptsAndArgs(args)
+ command = formatScriptsAndArgs(scriptArgs)
+ if command:
+ sep = ";"
+ if sys.platform == "win32":
+ sep= "&"
+ command = command.split(sep)
+ outmsg = []
+ errmsg = []
+ for cmd in command:
+ cmd = cmd.strip().split(' ')
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ (stdoutdata, stderrdata) = proc.communicate()
+ if stdoutdata or stderrdata:
+ outmsg.append(stdoutdata)
+ errmsg.append(stderrdata)
+
+ return ("".join(outmsg), "".join(errmsg))
+ else:
+ absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
+ cmd = ["/bin/bash", "--rcfile", absoluteAppliPath + "/.bashrc" ]
+ proc = subprocess.Popen(cmd, shell=False, close_fds=True)
+ proc.wait()
+ #
+
+ def _runConsole(self, args=[]):
+ # Initialize SALOME environment
+ sys.argv = ['runConsole'] + args
+ import setenv
+ setenv.main(True)
+
+ import runConsole
+ runConsole.connect()
+ #
+
+ def _killAll(self, args=[]):
+ absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
+ try:
+ import PortManager # mandatory
+ from multiprocessing import Process
+ from killSalomeWithPort import killMyPort
+ ports = PortManager.getBusyPorts()
+
+ if ports:
+ import tempfile
+ for port in ports:
+ with tempfile.NamedTemporaryFile():
+ p = Process(target = killMyPort, args=(port,))
+ p.start()
+ p.join()
+
+ p = Process(target = killMyPort, args=(2809,))
+ p.start()
+ p.join()
+ except ImportError:
+ from killSalome import killAllPorts
+ killAllPorts()
+ pass
+
+ #
+
+ def _showInfo(self, args=[]):
+ print "Running with python", platform.python_version()
+ self._runAppli(["--version"])
+ #
+
+ def _usage(self, unused=[]):
+ usage()
+ #
+
+ def _makeCoffee(self, args=[]):
+ print " ("
+ print " ) ("
+ print " ___...(-------)-....___"
+ print " .-\"\" ) ( \"\"-."
+ print " .-\'``\'|-._ ) _.-|"
+ print " / .--.| `\"\"---...........---\"\"` |"
+ print " / / | |"
+ print " | | | |"
+ print " \\ \\ | |"
+ print " `\\ `\\ | |"
+ print " `\\ `| |"
+ print " _/ /\\ /"
+ print " (__/ \\ /"
+ print " _..---\"\"` \\ /`\"\"---.._"
+ print " .-\' \\ / \'-."
+ print " : `-.__ __.-\' :"
+ print " : ) \"\"---...---\"\" ( :"
+ print " \'._ `\"--...___...--\"` _.\'"
+ print " \\\"\"--..__ __..--\"\"/"
+ print " \'._ \"\"\"----.....______.....----\"\"\" _.\'"
+ print " `\"\"--..,,_____ _____,,..--\"\"`"
+ print " `\"\"\"----\"\"\"`"
+ sys.exit(0)
+ #
+
+ # Add the following two methods since logger is not pickable
+ # Ref: http://stackoverflow.com/questions/2999638/how-to-stop-attributes-from-being-pickled-in-python
+ def __getstate__(self):
+ d = dict(self.__dict__)
+ if hasattr(self, '_logger'):
+ del d['_logger']
+ return d
+ #
+ def __setstate__(self, d):
+ self.__dict__.update(d) # I *think* this is a safe way to do it
+ #
+ # Excluding self._logger from pickle operation imply using the following method to access logger
+ def getLogger(self):
+ if not hasattr(self, '_logger'):
+ self._logger = logging.getLogger(__name__)
+ #self._logger.setLevel(logging.DEBUG)
+ self._logger.setLevel(logging.ERROR)
+ return self._logger
+ #
+
+###
+import pickle
+if __name__ == "__main__":
+ if len(sys.argv) == 3:
+ context = pickle.loads(sys.argv[1])
+ args = pickle.loads(sys.argv[2])
+ (out, err) = context._getStarted(args)
+ if out:
+ sys.stdout.write(out)
+ if err:
+ sys.stderr.write(err)
+ else:
+ usage()
+#
--- /dev/null
+#! /usr/bin/env python
+
+# Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+import os
+import sys
+import glob
+import subprocess
+import re
+
+"""
+Define a specific exception class to manage exceptions related to SalomeContext
+"""
+class SalomeContextException(Exception):
+ """Report error messages to the user interface of SalomeContext."""
+#
+
+def __listDirectory(path):
+ allFiles = []
+ for root, dirs, files in os.walk(path):
+ configFileNames = glob.glob(os.path.join(root,'*.cfg')) + glob.glob(os.path.join(root,'*.sh'))
+ allFiles += configFileNames
+ return allFiles
+#
+
+def __getConfigFileNamesDefault():
+ absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
+ if not absoluteAppliPath:
+ return []
+
+ envdDir = absoluteAppliPath + '/env.d'
+ if not os.path.isdir(envdDir):
+ return []
+
+ return __listDirectory(envdDir)
+#
+
+def getConfigFileNames(args, checkExistence=False):
+ # special case: configuration files are provided by user
+ # Search for command-line argument(s) --config=file1,file2,..., filen
+ # Search for command-line argument(s) --config=dir1,dir2,..., dirn
+ configOptionPrefix = "--config="
+ configArgs = [ str(x) for x in args if str(x).startswith(configOptionPrefix) ]
+
+ if len(configArgs) == 0:
+ return __getConfigFileNamesDefault(), args, []
+
+ args = [ x for x in args if not x.startswith(configOptionPrefix) ]
+ allLists = [ x.replace(configOptionPrefix, '') for x in configArgs ]
+
+ configFileNames = []
+ unexisting = []
+ for currentList in allLists:
+ elements = currentList.split(',')
+ for elt in elements:
+ elt = os.path.realpath(os.path.expanduser(elt))
+ if os.path.isdir(elt):
+ configFileNames += __listDirectory(elt)
+ else:
+ if checkExistence and not os.path.isfile(elt):
+ unexisting += [elt]
+ else:
+ configFileNames += [elt]
+
+ return configFileNames, args, unexisting
+#
+
+# Return an array of dictionaries {script_name: [list_of_its_args]}
+def getScriptsAndArgs(args=[]):
+ # Syntax of args: script.py [args:a1,a2=val,an] ... script.py [args:a1,a2=val,an]
+ scriptArgs = []
+ currentKey = None
+ argsPrefix = "args:"
+ callPython = False
+ currentScript = None
+
+ for i in range(len(args)):
+ elt = args[i]
+
+ if elt.startswith(argsPrefix):
+ if not currentKey or callPython:
+ raise SalomeContextException("args list must follow corresponding script file in command line.")
+ elt = elt.replace(argsPrefix, '')
+ scriptArgs[len(scriptArgs)-1][currentKey] = elt.split(",")
+ currentKey = None
+ callPython = False
+ elif elt.startswith("python"):
+ callPython = True
+ elif os.path.isfile(elt) or os.path.isfile(elt+".py"):
+ if elt[-4:] != ".hdf":
+ if elt[-3:] == ".py":
+ currentScript = os.path.abspath(elt)
+ elif os.path.isfile(elt+".py"):
+ currentScript = os.path.abspath(elt+".py")
+ else:
+ currentScript = os.path.abspath(elt) # python script not necessary has .py extension
+ pass
+ if currentScript and callPython:
+ currentKey = "@PYTHONBIN@ "+currentScript
+ scriptArgs.append({currentKey:[]})
+ callPython = False
+ elif currentScript:
+ if not os.access(currentScript, os.X_OK):
+ currentKey = "@PYTHONBIN@ "+currentScript
+ scriptArgs.append({currentKey:[]})
+ else:
+ ispython = False
+ try:
+ fn = open(currentScript)
+ for i in xrange(10): # read only 10 first lines
+ ln = fn.readline()
+ if re.search("#!.*python"):
+ ispython = True
+ break
+ pass
+ fn.close()
+ except:
+ pass
+ if not ispython and currentScript[-3:] == ".py":
+ currentKey = "@PYTHONBIN@ "+currentScript
+ else:
+ currentKey = currentScript
+ pass
+ scriptArgs.append({currentKey:[]})
+ # end for loop
+ return scriptArgs
+#
+
+# Formatting scripts and args as a Bash-like command-line:
+# script1.py [args] ; script2.py [args] ; ...
+def formatScriptsAndArgs(scriptArgs=[]):
+ commands = []
+ for sc_dict in scriptArgs:
+ for script, sc_args in sc_dict.items(): # single entry
+ cmd = script
+ if sc_args:
+ cmd = cmd + " " + " ".join(sc_args)
+ commands.append(cmd)
+ sep = " ; "
+ if sys.platform == "win32":
+ sep= " & "
+ command = sep.join(["%s"%x for x in commands])
+ return command
+#
+
+# Ensure OMNIORB_USER_PATH is defined. This variable refers to a the folder in which
+# SALOME will write omniOrb configuration files.
+# If OMNIORB_USER_PATH is already set, only checks write access to associated directory ;
+# an exception is raised if check fails. It allows users for choosing a specific folder.
+# Else the function sets OMNIORB_USER_PATH this way:
+# - If APPLI environment variable is set, OMNIORB_USER_PATH is set to ${APPLI}/USERS.
+# The function does not check USERS folder existence or wrute access. This folder
+# must exist ; this is the case if SALOME virtual application has been create using
+# appli_gen.py script.
+# - Else OMNIORB_USER_PATH is set to user home directory.
+def setOmniOrbUserPath():
+ omniorbUserPath = os.getenv("OMNIORB_USER_PATH")
+ if omniorbUserPath:
+ if not os.access(omniorbUserPath, os.W_OK):
+ raise Exception("Unable to get write access to directory: %s"%omniorbUserPath)
+ pass
+ else:
+ homePath = os.path.realpath(os.path.expanduser('~'))
+ #defaultOmniorbUserPath = os.path.join(homePath, ".salomeConfig/USERS")
+ defaultOmniorbUserPath = homePath
+ if os.getenv("APPLI"):
+ defaultOmniorbUserPath = os.path.join(homePath, os.getenv("APPLI"), "USERS")
+ pass
+ os.environ["OMNIORB_USER_PATH"] = defaultOmniorbUserPath
+#
+++ /dev/null
-#! /usr/bin/env python
-
-# Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-#
-
-import os
-import sys
-import glob
-import subprocess
-import re
-
-"""
-Define a specific exception class to manage exceptions related to SalomeRunner
-"""
-class SalomeRunnerException(Exception):
- """Report error messages to the user interface of SalomeRunner."""
-#
-
-def __listDirectory(path):
- allFiles = []
- for root, dirs, files in os.walk(path):
- configFileNames = glob.glob(os.path.join(root,'*.cfg')) + glob.glob(os.path.join(root,'*.sh'))
- allFiles += configFileNames
- return allFiles
-#
-
-def __getConfigFileNamesDefault():
- absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
- if not absoluteAppliPath:
- return []
-
- envdDir = absoluteAppliPath + '/env.d'
- if not os.path.isdir(envdDir):
- return []
-
- return __listDirectory(envdDir)
-#
-
-def getConfigFileNames(args, checkExistence=False):
- # special case: configuration files are provided by user
- # Search for command-line argument(s) --config=file1,file2,..., filen
- # Search for command-line argument(s) --config=dir1,dir2,..., dirn
- configOptionPrefix = "--config="
- configArgs = [ str(x) for x in args if str(x).startswith(configOptionPrefix) ]
-
- if len(configArgs) == 0:
- return __getConfigFileNamesDefault(), args, []
-
- args = [ x for x in args if not x.startswith(configOptionPrefix) ]
- allLists = [ x.replace(configOptionPrefix, '') for x in configArgs ]
-
- configFileNames = []
- unexisting = []
- for currentList in allLists:
- elements = currentList.split(',')
- for elt in elements:
- elt = os.path.realpath(os.path.expanduser(elt))
- if os.path.isdir(elt):
- configFileNames += __listDirectory(elt)
- else:
- if checkExistence and not os.path.isfile(elt):
- unexisting += [elt]
- else:
- configFileNames += [elt]
-
- return configFileNames, args, unexisting
-#
-
-# Return an array of dictionaries {script_name: [list_of_its_args]}
-def getScriptsAndArgs(args=[]):
- # Syntax of args: script.py [args:a1,a2=val,an] ... script.py [args:a1,a2=val,an]
- scriptArgs = []
- currentKey = None
- argsPrefix = "args:"
- callPython = False
- currentScript = None
-
- for i in range(len(args)):
- elt = args[i]
-
- if elt.startswith(argsPrefix):
- if not currentKey or callPython:
- raise SalomeRunnerException("args list must follow corresponding script file in command line.")
- elt = elt.replace(argsPrefix, '')
- scriptArgs[len(scriptArgs)-1][currentKey] = elt.split(",")
- currentKey = None
- callPython = False
- elif elt.startswith("python"):
- callPython = True
- elif os.path.isfile(elt) or os.path.isfile(elt+".py"):
- if elt[-4:] != ".hdf":
- if elt[-3:] == ".py":
- currentScript = os.path.abspath(elt)
- elif os.path.isfile(elt+".py"):
- currentScript = os.path.abspath(elt+".py")
- else:
- currentScript = os.path.abspath(elt) # python script not necessary has .py extension
- pass
- if currentScript and callPython:
- currentKey = "@PYTHONBIN@ "+currentScript
- scriptArgs.append({currentKey:[]})
- callPython = False
- elif currentScript:
- if not os.access(currentScript, os.X_OK):
- currentKey = "@PYTHONBIN@ "+currentScript
- scriptArgs.append({currentKey:[]})
- else:
- ispython = False
- try:
- fn = open(currentScript)
- for i in xrange(10): # read only 10 first lines
- ln = fn.readline()
- if re.search("#!.*python"):
- ispython = True
- break
- pass
- fn.close()
- except:
- pass
- if not ispython and currentScript[-3:] == ".py":
- currentKey = "@PYTHONBIN@ "+currentScript
- else:
- currentKey = currentScript
- pass
- scriptArgs.append({currentKey:[]})
- # end for loop
- return scriptArgs
-#
-
-# Formatting scripts and args as a Bash-like command-line:
-# script1.py [args] ; script2.py [args] ; ...
-def formatScriptsAndArgs(scriptArgs=[]):
- commands = []
- for sc_dict in scriptArgs:
- for script, sc_args in sc_dict.items(): # single entry
- cmd = script
- if sc_args:
- cmd = cmd + " " + " ".join(sc_args)
- commands.append(cmd)
- sep = " ; "
- if sys.platform == "win32":
- sep= " & "
- command = sep.join(["%s"%x for x in commands])
- return command
-#
-
-# Ensure OMNIORB_USER_PATH is defined. This variable refers to a the folder in which
-# SALOME will write omniOrb configuration files.
-# If OMNIORB_USER_PATH is already set, only checks write access to associated directory ;
-# an exception is raised if check fails. It allows users for choosing a specific folder.
-# Else the function sets OMNIORB_USER_PATH this way:
-# - If APPLI environment variable is set, OMNIORB_USER_PATH is set to ${APPLI}/USERS.
-# The function does not check USERS folder existence or wrute access. This folder
-# must exist ; this is the case if SALOME virtual application has been create using
-# appli_gen.py script.
-# - Else OMNIORB_USER_PATH is set to user home directory.
-def setOmniOrbUserPath():
- omniorbUserPath = os.getenv("OMNIORB_USER_PATH")
- if omniorbUserPath:
- if not os.access(omniorbUserPath, os.W_OK):
- raise Exception("Unable to get write access to directory: %s"%omniorbUserPath)
- pass
- else:
- homePath = os.path.realpath(os.path.expanduser('~'))
- #defaultOmniorbUserPath = os.path.join(homePath, ".salomeConfig/USERS")
- defaultOmniorbUserPath = homePath
- if os.getenv("APPLI"):
- defaultOmniorbUserPath = os.path.join(homePath, os.getenv("APPLI"), "USERS")
- pass
- os.environ["OMNIORB_USER_PATH"] = defaultOmniorbUserPath
-#
+++ /dev/null
-# Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-#
-
-import os
-import sys
-import logging
-import ConfigParser
-
-from parseConfigFile import parseConfigFile
-from parseConfigFile import convertEnvFileToConfigFile
-
-import tempfile
-import pickle
-import subprocess
-import platform
-
-from salomeLauncherUtils import SalomeRunnerException
-from salomeLauncherUtils import getScriptsAndArgs, formatScriptsAndArgs
-
-def usage():
- #exeName = os.path.splitext(os.path.basename(__file__))[0]
-
- msg = '''\
-Usage: salome [command] [options] [--config=file1,...,filen]
-
-Commands:
- start Launches SALOME virtual application [DEFAULT]
- shell Executes a script under SALOME application environment
- connect Connects a Python console to the active SALOME session
- killall Kill all SALOME running sessions
- info Display some information about SALOME
- help Show this message
- coffee Yes! SALOME can also make coffee!!"
-
-Use salome start --help or salome shell --help
-to show help on start and shell commands.
-'''
-
- print msg
-#
-
-"""
-The SalomeRunner class in an API to configure SALOME environment then
-start SALOME using a single python command.
-
-"""
-class SalomeRunner:
- """
- Initialize environment from a list of configuration files
- identified by their names.
- These files should be in appropriate (new .cfg) format.
- However you can give old .sh environment files; in this case,
- the SalomeRunner class will try to automatically convert them
- to .cfg format before setting the environment.
- """
- def __init__(self, configFileNames=[]):
- #it could be None explicitely (if user use multiples setEnviron...for standalone)
- if configFileNames==None:
- return
-
- if len(configFileNames) == 0:
- raise SalomeRunnerException("No configuration files given")
-
- reserved=['PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'PV_PLUGIN_PATH']
- for filename in configFileNames:
- basename, extension = os.path.splitext(filename)
- if extension == ".cfg":
- self.__setEnvironmentFromConfigFile(filename, reserved)
- elif extension == ".sh":
- #new convert procedures, temporary could be use not to be automatically deleted
- #temp = tempfile.NamedTemporaryFile(suffix='.cfg', delete=False)
- temp = tempfile.NamedTemporaryFile(suffix='.cfg')
- try:
- convertEnvFileToConfigFile(filename, temp.name, reserved)
- self.__setEnvironmentFromConfigFile(temp.name, reserved)
- except ConfigParser.ParsingError, e:
- self.getLogger().warning("Invalid token found when parsing file: %s\n"%(filename))
- print e
- print '\n'
- finally:
- # Automatically cleans up the file
- temp.close()
- else:
- self.getLogger().warning("Unrecognized extension for configuration file: %s", filename)
- #
-
- def go(self, args):
- # Run this module as a script, in order to use appropriate Python interpreter
- # according to current path (initialized from environment files).
- kill = False
- for e in args:
- if "--shutdown-server" in e:
- kill = True
- args.remove(e)
-
- absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
- proc = subprocess.Popen(['python', os.path.join(absoluteAppliPath,"bin","salome","salomeRunner.py"), pickle.dumps(self), pickle.dumps(args)], shell=False, close_fds=True)
- proc.communicate()
- if kill:
- self._killAll(args)
- #
-
- """Append value to PATH environment variable"""
- def addToPath(self, value):
- self.addToEnviron('PATH', value)
- #
-
- """Append value to LD_LIBRARY_PATH environment variable"""
- def addToLdLibraryPath(self, value):
- self.addToEnviron('LD_LIBRARY_PATH', value)
- #
-
- """Append value to PYTHONPATH environment variable"""
- def addToPythonPath(self, value):
- self.addToEnviron('PYTHONPATH', value)
- #
-
- """Set environment variable to value"""
- def setEnviron(self, name, value, overwrite=False):
- env = os.getenv(name, '')
- if env and not overwrite:
- self.getLogger().warning("Environment variable already existing (and not overwritten): %s=%s", name, value)
- return
-
- if env:
- self.getLogger().warning("Overwriting environment variable: %s=%s", name, value)
-
- value = os.path.expandvars(value) # expand environment variables
- self.getLogger().debug("Set environment variable: %s=%s", name, value)
- os.environ[name] = value
- #
-
- """Unset environment variable"""
- def unsetEnviron(self, name):
- if os.environ.has_key(name):
- del os.environ[name]
- #
-
- """Append value to environment variable"""
- def addToEnviron(self, name, value, separator=os.pathsep):
- if value == '':
- return
-
- value = os.path.expandvars(value) # expand environment variables
- self.getLogger().debug("Add to %s: %s", name, value)
- env = os.getenv(name, None)
- if env is None:
- os.environ[name] = value
- else:
- os.environ[name] = value + separator + env
- #
-
- ###################################
- # This begins the private section #
- ###################################
-
- def __parseArguments(self, args):
- if len(args) == 0 or args[0].startswith("-"):
- return None, args
-
- command = args[0]
- options = args[1:]
-
- availableCommands = {
- 'start' : '_runAppli',
- 'shell' : '_runSession',
- 'connect' : '_runConsole',
- 'killall': '_killAll',
- 'info': '_showInfo',
- 'help': '_usage',
- 'coffee' : '_makeCoffee'
- }
-
- if not command in availableCommands.keys():
- command = "start"
- options = args
-
- return availableCommands[command], options
- #
-
- """
- Run SALOME!
- Args consist in a mandatory command followed by optionnal parameters.
- See usage for details on commands.
- """
- def _getStarted(self, args):
- command, options = self.__parseArguments(args)
- sys.argv = options
-
- if command is None:
- if args and args[0] in ["-h","--help","help"]:
- usage()
- sys.exit(0)
- # try to default to "start" command
- command = "_runAppli"
-
- try:
- res = getattr(self, command)(options) # run appropriate method
- return res or (None, None)
- except SystemExit, exc:
- if exc==0:
- sys.exit(0) #catch sys.exit(0) happy end no warning
- if exc==1:
- self.getLogger().warning("SystemExit 1 in method %s.", command)
- sys.exit(1)
- except StandardError:
- self.getLogger().error("Unexpected error:")
- import traceback
- traceback.print_exc()
- sys.exit(1)
- except SalomeRunnerException, e:
- self.getLogger().error(e)
- sys.exit(1)
- #
-
- def __setEnvironmentFromConfigFile(self, filename, reserved=[]):
- unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved)
-
- # unset variables
- for var in unsetVars:
- self.unsetEnviron(var)
-
- # set environment
- for reserved in reservedDict:
- a = filter(None, reservedDict[reserved]) # remove empty elements
- reformattedVals = ':'.join(a)
- self.addToEnviron(reserved, reformattedVals)
- pass
-
- for key,val in configVars:
- self.setEnviron(key, val, overwrite=True)
- pass
-
- sys.path[:0] = os.getenv('PYTHONPATH','').split(':')
- #
-
- def _runAppli(self, args=[]):
- # Initialize SALOME environment
- sys.argv = ['runSalome'] + args
- import setenv
- setenv.main(True)
-
- import runSalome
- runSalome.runSalome()
- #
-
- def _runSession(self, args=[]):
- sys.argv = ['runSession'] + args
- import runSession
- runSession.configureSession(args)
-
- import setenv
- setenv.main(True)
-
- scriptArgs = getScriptsAndArgs(args)
- command = formatScriptsAndArgs(scriptArgs)
- if command:
- sep = ";"
- if sys.platform == "win32":
- sep= "&"
- command = command.split(sep)
- outmsg = []
- errmsg = []
- for cmd in command:
- cmd = cmd.strip().split(' ')
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdoutdata, stderrdata) = proc.communicate()
- if stdoutdata or stderrdata:
- outmsg.append(stdoutdata)
- errmsg.append(stderrdata)
-
- return ("".join(outmsg), "".join(errmsg))
- else:
- absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
- cmd = ["/bin/bash", "--rcfile", absoluteAppliPath + "/.bashrc" ]
- proc = subprocess.Popen(cmd, shell=False, close_fds=True)
- proc.wait()
- #
-
- def _runConsole(self, args=[]):
- # Initialize SALOME environment
- sys.argv = ['runConsole'] + args
- import setenv
- setenv.main(True)
-
- import runConsole
- runConsole.connect()
- #
-
- def _killAll(self, args=[]):
- absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
- try:
- import PortManager # mandatory
- from multiprocessing import Process
- from killSalomeWithPort import killMyPort
- ports = PortManager.getBusyPorts()
-
- if ports:
- import tempfile
- for port in ports:
- with tempfile.NamedTemporaryFile():
- p = Process(target = killMyPort, args=(port,))
- p.start()
- p.join()
-
- p = Process(target = killMyPort, args=(2809,))
- p.start()
- p.join()
- except ImportError:
- from killSalome import killAllPorts
- killAllPorts()
- pass
-
- #
-
- def _showInfo(self, args=[]):
- print "Running with python", platform.python_version()
- self._runAppli(["--version"])
- #
-
- def _usage(self, unused=[]):
- usage()
- #
-
- def _makeCoffee(self, args=[]):
- print " ("
- print " ) ("
- print " ___...(-------)-....___"
- print " .-\"\" ) ( \"\"-."
- print " .-\'``\'|-._ ) _.-|"
- print " / .--.| `\"\"---...........---\"\"` |"
- print " / / | |"
- print " | | | |"
- print " \\ \\ | |"
- print " `\\ `\\ | |"
- print " `\\ `| |"
- print " _/ /\\ /"
- print " (__/ \\ /"
- print " _..---\"\"` \\ /`\"\"---.._"
- print " .-\' \\ / \'-."
- print " : `-.__ __.-\' :"
- print " : ) \"\"---...---\"\" ( :"
- print " \'._ `\"--...___...--\"` _.\'"
- print " \\\"\"--..__ __..--\"\"/"
- print " \'._ \"\"\"----.....______.....----\"\"\" _.\'"
- print " `\"\"--..,,_____ _____,,..--\"\"`"
- print " `\"\"\"----\"\"\"`"
- sys.exit(0)
- #
-
- # Add the following two methods since logger is not pickable
- # Ref: http://stackoverflow.com/questions/2999638/how-to-stop-attributes-from-being-pickled-in-python
- def __getstate__(self):
- d = dict(self.__dict__)
- if hasattr(self, '_logger'):
- del d['_logger']
- return d
- #
- def __setstate__(self, d):
- self.__dict__.update(d) # I *think* this is a safe way to do it
- #
- # Excluding self._logger from pickle operation imply using the following method to access logger
- def getLogger(self):
- if not hasattr(self, '_logger'):
- self._logger = logging.getLogger(__name__)
- #self._logger.setLevel(logging.DEBUG)
- self._logger.setLevel(logging.ERROR)
- return self._logger
- #
-
-###
-import pickle
-if __name__ == "__main__":
- if len(sys.argv) == 3:
- runner = pickle.loads(sys.argv[1])
- args = pickle.loads(sys.argv[2])
- (out, err) = runner._getStarted(args)
- if out:
- sys.stdout.write(out)
- if err:
- sys.stderr.write(err)
- else:
- usage()
-#