]> SALOME platform Git repositories - modules/kernel.git/commitdiff
Salome HOME
rename salome runner/launcher as salome context
authorCédric Aguerre <cedric.aguerre@edf.fr>
Tue, 11 Mar 2014 14:22:11 +0000 (15:22 +0100)
committerCédric Aguerre <cedric.aguerre@edf.fr>
Tue, 11 Mar 2014 14:22:11 +0000 (15:22 +0100)
bin/CMakeLists.txt
bin/appliskel/salome
bin/launchConfigureParser.py
bin/runSalome.py
bin/salomeContext.py [new file with mode: 0644]
bin/salomeContextUtils.py.in [new file with mode: 0644]
bin/salomeLauncherUtils.py.in [deleted file]
bin/salomeRunner.py [deleted file]

index 431f7f961596143adf153cbf20f1b24ef7835b91..455fc61e15aaa94f3e6589de0b9f6f60d576cb2d 100755 (executable)
@@ -20,7 +20,7 @@
 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
@@ -49,8 +49,8 @@ SET(SCRIPTS
   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
index baeead6c44428e6a8daf83af1d7f1f4b928f478a..e61b6cbab6c3fcfb9d96043a328ebec13427d381 100755 (executable)
@@ -40,7 +40,7 @@ def __initialize():
 
   # 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
@@ -52,32 +52,32 @@ def main(args):
   __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)
index 2176d4e7fab2dfdb9f18b91d1c3bb3f74a6c0f4e..cfb247f619dcbfef936d53549b6061ca2a5d0519 100755 (executable)
@@ -28,7 +28,7 @@ import types
 
 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"
index df7b7b0c6de345d4e429ced9af0d4f835ba3cdaf..514bd07fc7339aa2061e6ce81ab584a29f4cb131 100755 (executable)
@@ -764,7 +764,7 @@ def useSalome(args, modules_list, modules_root_dir):
                 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)
@@ -812,9 +812,9 @@ def no_main():
     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
 
@@ -825,7 +825,7 @@ def main():
 
     # 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
@@ -944,9 +944,9 @@ def runSalome():
         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
 #
diff --git a/bin/salomeContext.py b/bin/salomeContext.py
new file mode 100644 (file)
index 0000000..d7d282c
--- /dev/null
@@ -0,0 +1,400 @@
+# 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()
+#
diff --git a/bin/salomeContextUtils.py.in b/bin/salomeContextUtils.py.in
new file mode 100644 (file)
index 0000000..a48e668
--- /dev/null
@@ -0,0 +1,187 @@
+#! /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
+#
diff --git a/bin/salomeLauncherUtils.py.in b/bin/salomeLauncherUtils.py.in
deleted file mode 100644 (file)
index 0b03c39..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-#! /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
-#
diff --git a/bin/salomeRunner.py b/bin/salomeRunner.py
deleted file mode 100644 (file)
index a12311c..0000000
+++ /dev/null
@@ -1,400 +0,0 @@
-# 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()
-#