Salome HOME
Merge branch 'V7_5_BR'
[modules/kernel.git] / bin / salomeContext.py
index 98d2453571e990b9917cefa86b4a4c46cc25f563..954f86fd89344adc396033cb9c4cfccebc004939 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2013-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2013-2015  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
@@ -31,25 +31,36 @@ 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]
+Usage: salome [command] [options] [--config=<file,folder,...>]
 
 Commands:
-    start         Launches SALOME virtual application [DEFAULT]
-    shell         Executes a script under SALOME application environment
+=========
+    start         Starts a SALOME session (through virtual application)
+    shell         Initializes SALOME environment, and executes scripts passed
+                  as command arguments
     connect       Connects a Python console to the active SALOME session
-    killall       Kill all SALOME running sessions
+    killall       Kill all SALOME running sessions for current user
     info          Display some information about SALOME
     help          Show this message
-    coffee        Yes! SALOME can also make coffee!!"
+    coffee        Yes! SALOME can also make coffee!!
 
-Use salome start --help or salome shell --help
-to show help on start and shell commands.
+If no command is given, default to start.
+
+Command options:
+================
+    Use salome <command> --help to show help on command ; available for start
+    and shell commands.
+
+--config=<file,folder,...>
+==========================
+    Initialize SALOME environment from a list of context files and/or a list
+    of folders containing context files. The list is comma-separated, whithout
+    any blank characters.
 '''
 
   print msg
@@ -69,11 +80,11 @@ class SalomeContext:
   the SalomeContext class will try to automatically convert them
   to .cfg format before setting the environment.
   """
-  def __init__(self, configFileNames=[]):
+  def __init__(self, configFileNames=0):
     #it could be None explicitely (if user use multiples setVariable...for standalone)
-    if configFileNames==None:
+    if configFileNames is None:
        return
-
+    configFileNames = configFileNames or []
     if len(configFileNames) == 0:
       raise SalomeContextException("No configuration files given")
 
@@ -89,13 +100,11 @@ class SalomeContext:
         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()
+        except (ConfigParser.ParsingError, ValueError) as e:
+          self.getLogger().error("Invalid token found when parsing file: %s\n"%(filename))
+          temp.close()
+          sys.exit(1)
       else:
         self.getLogger().warning("Unrecognized extension for configuration file: %s", filename)
   #
@@ -103,18 +112,20 @@ class SalomeContext:
   def runSalome(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)
+#    kill = False
+#    for e in args:
+#      if "--shutdown-server" in e:
+#        kill = True
+#        args.remove(e)
 
+    import os
     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)
+    env_copy = os.environ.copy()
+    proc = subprocess.Popen(['python', os.path.join(absoluteAppliPath,"bin","salome","salomeContext.py"), pickle.dumps(self), pickle.dumps(args)], shell=False, close_fds=True, env=env_copy)
     msg = proc.communicate()
-    if kill:
-      self._killAll(args)
-    return msg
#   if kill:
#     self._killAll(args)
+    return msg, proc.returncode
   #
 
   """Append value to PATH environment variable"""
@@ -206,6 +217,16 @@ class SalomeContext:
   See usage for details on commands.
   """
   def _startSalome(self, args):
+    try:
+      import os
+      absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH')
+      import sys
+      path = os.path.realpath(os.path.join(absoluteAppliPath, "bin", "salome"))
+      if not path in sys.path:
+        sys.path[:0] = [path]
+    except:
+      pass
+
     command, options = self.__parseArguments(args)
     sys.argv = options
 
@@ -219,12 +240,10 @@ class SalomeContext:
     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 SystemExit, returncode:
+      if returncode != 0:
+        self.getLogger().warning("SystemExit %s in method %s.", returncode, command)
+      sys.exit(returncode)
     except StandardError:
       self.getLogger().error("Unexpected error:")
       import traceback
@@ -235,8 +254,35 @@ class SalomeContext:
       sys.exit(1)
   #
 
-  def __setEnvironmentFromConfigFile(self, filename, reserved=[]):
-    unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved)
+  def __setEnvironmentFromConfigFile(self, filename, reserved=None):
+    if reserved is None:
+      reserved = []
+    try:
+      unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved)
+    except SalomeContextException, e:
+      msg = "%s"%e
+      file_dir = os.path.dirname(filename)
+      file_base = os.path.basename(filename)
+      base_no_ext, ext = os.path.splitext(file_base)
+      sh_file = os.path.join(file_dir, base_no_ext+'.sh')
+      if ext == ".cfg" and os.path.isfile(sh_file):
+        msg += "Found similar %s file; trying to parse this one instead..."%(base_no_ext+'.sh')
+        temp = tempfile.NamedTemporaryFile(suffix='.cfg')
+        try:
+          convertEnvFileToConfigFile(sh_file, temp.name, reserved)
+          self.__setEnvironmentFromConfigFile(temp.name, reserved)
+          msg += "OK\n"
+          self.getLogger().warning(msg)
+          temp.close()
+          return
+        except (ConfigParser.ParsingError, ValueError) as e:
+          msg += "Invalid token found when parsing file: %s\n"%(sh_file)
+          self.getLogger().error(msg)
+          temp.close()
+          sys.exit(1)
+      else:
+        self.getLogger().error(msg)
+        sys.exit(1)
 
     # unset variables
     for var in unsetVars:
@@ -245,7 +291,8 @@ class SalomeContext:
     # set environment
     for reserved in reservedDict:
       a = filter(None, reservedDict[reserved]) # remove empty elements
-      reformattedVals = ':'.join(a)
+      a = [ os.path.realpath(x) for x in a ]
+      reformattedVals = os.pathsep.join(a)
       self.addToVariable(reserved, reformattedVals)
       pass
 
@@ -253,10 +300,14 @@ class SalomeContext:
       self.setVariable(key, val, overwrite=True)
       pass
 
-    sys.path[:0] = os.getenv('PYTHONPATH','').split(':')
+    pythonpath = os.getenv('PYTHONPATH','').split(os.pathsep)
+    pythonpath = [ os.path.realpath(x) for x in pythonpath ]
+    sys.path[:0] = pythonpath
   #
 
-  def _runAppli(self, args=[]):
+  def _runAppli(self, args=None):
+    if args is None:
+      args = []
     # Initialize SALOME environment
     sys.argv = ['runSalome'] + args
     import setenv
@@ -266,41 +317,23 @@ class SalomeContext:
     runSalome.runSalome()
   #
 
-  def _runSession(self, args=[]):
+  def _runSession(self, args=None):
+    if args is None:
+      args = []
     sys.argv = ['runSession'] + args
     import runSession
-    runSession.configureSession(args)
+    params, args = runSession.configureSession(args)
 
+    sys.argv = ['runSession'] + 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)
-        proc = subprocess.Popen(cmd)
-        (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)
-      return proc.communicate()
+    return runSession.runSession(params, args)
   #
 
-  def _runConsole(self, args=[]):
+  def _runConsole(self, args=None):
+    if args is None:
+      args = []
     # Initialize SALOME environment
     sys.argv = ['runConsole'] + args
     import setenv
@@ -311,8 +344,9 @@ class SalomeContext:
     return proc.communicate()
   #
 
-  def _killAll(self, args=[]):
-    absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
+  def _killAll(self, args=None):
+    if args is None:
+      args = []
     try:
       import PortManager # mandatory
       from multiprocessing import Process
@@ -326,10 +360,6 @@ class SalomeContext:
             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()
@@ -337,16 +367,16 @@ class SalomeContext:
 
   #
 
-  def _showInfo(self, args=[]):
+  def _showInfo(self, args=None):
     print "Running with python", platform.python_version()
     self._runAppli(["--version"])
   #
 
-  def _usage(self, unused=[]):
+  def _usage(self, unused=None):
     usage()
   #
 
-  def _makeCoffee(self, args=[]):
+  def _makeCoffee(self, args=None):
     print "                        ("
     print "                          )     ("
     print "                   ___...(-------)-....___"
@@ -388,16 +418,16 @@ class SalomeContext:
     if not hasattr(self, '_logger'):
       self._logger = logging.getLogger(__name__)
       #self._logger.setLevel(logging.DEBUG)
+      #self._logger.setLevel(logging.WARNING)
       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._startSalome(args)
     if out:
       sys.stdout.write(out)