Salome HOME
Fixed problem with dump study and small optimization:
[modules/kernel.git] / bin / salomeContext.py
index 51e0c51a90340118b34bc7b86878071c1a245790..c5eda0a516aae432bd351660860b6baa6970c852 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2013-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2013-2016  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
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -33,32 +33,36 @@ import platform
 from salomeContextUtils import SalomeContextException
 
 def usage():
 from salomeContextUtils import SalomeContextException
 
 def usage():
-  #exeName = os.path.splitext(os.path.basename(__file__))[0]
-
   msg = '''\
 Usage: salome [command] [options] [--config=<file,folder,...>]
 
 Commands:
 =========
   msg = '''\
 Usage: salome [command] [options] [--config=<file,folder,...>]
 
 Commands:
 =========
-    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 for current user
-    info          Display some information about SALOME
-    help          Show this message
-    coffee        Yes! SALOME can also make coffee!!
+    start           Start a new SALOME instance.
+    context         Initialize SALOME context. Current environment is extended.
+    shell           Initialize SALOME context, attached to the last created SALOME
+                    instance if any, and executes scripts passed as command arguments.
+                    User works in a Shell terminal; SALOME environment is set but
+                    application is not started.
+    connect         Connect a Python console to the active SALOME instance.
+    kill <port(s)>  Terminate SALOME instances running on given ports for current user.
+                    Port numbers must be separated by blank characters.
+    killall         Terminate *all* SALOME running instances for current user.
+                    Do not start a new one.
+    test            Run SALOME tests.
+    info            Display some information about SALOME.
+    help            Show this message.
 
 If no command is given, default to start.
 
 Command options:
 ================
 
 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.
+    Use salome <command> --help to show help on command ; available for commands:
+    start, shell, connect, test, info.
 
 --config=<file,folder,...>
 ==========================
 
 --config=<file,folder,...>
 ==========================
-    Initialize SALOME environment from a list of context files and/or a list
+    Initialize SALOME context from a list of context files and/or a list
     of folders containing context files. The list is comma-separated, whithout
     any blank characters.
 '''
     of folders containing context files. The list is comma-separated, whithout
     any blank characters.
 '''
@@ -67,20 +71,21 @@ Command options:
 #
 
 """
 #
 
 """
-The SalomeContext class in an API to configure SALOME environment then
+The SalomeContext class in an API to configure SALOME context then
 start SALOME using a single python command.
 
 """
 class SalomeContext:
   """
 start SALOME using a single python command.
 
 """
 class SalomeContext:
   """
-  Initialize environment from a list of configuration files
+  Initialize context 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
   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.
+  to .cfg format before setting the context.
   """
   def __init__(self, configFileNames=0):
   """
   def __init__(self, configFileNames=0):
+    self.getLogger().setLevel(logging.INFO)
     #it could be None explicitely (if user use multiples setVariable...for standalone)
     if configFileNames is None:
        return
     #it could be None explicitely (if user use multiples setVariable...for standalone)
     if configFileNames is None:
        return
@@ -88,18 +93,18 @@ class SalomeContext:
     if len(configFileNames) == 0:
       raise SalomeContextException("No configuration files given")
 
     if len(configFileNames) == 0:
       raise SalomeContextException("No configuration files given")
 
-    reserved=['PATH', 'DYLD_LIBRARY_PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'PV_PLUGIN_PATH']
+    reserved=['PATH', 'DYLD_LIBRARY_PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'PV_PLUGIN_PATH', 'INCLUDE', 'LIBPATH', 'SALOME_PLUGINS_PATH']
     for filename in configFileNames:
       basename, extension = os.path.splitext(filename)
       if extension == ".cfg":
     for filename in configFileNames:
       basename, extension = os.path.splitext(filename)
       if extension == ".cfg":
-        self.__setEnvironmentFromConfigFile(filename, reserved)
+        self.__setContextFromConfigFile(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)
       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)
+          self.__setContextFromConfigFile(temp.name, reserved)
           temp.close()
         except (ConfigParser.ParsingError, ValueError) as e:
           self.getLogger().error("Invalid token found when parsing file: %s\n"%(filename))
           temp.close()
         except (ConfigParser.ParsingError, ValueError) as e:
           self.getLogger().error("Invalid token found when parsing file: %s\n"%(filename))
@@ -109,23 +114,37 @@ class SalomeContext:
         self.getLogger().warning("Unrecognized extension for configuration file: %s", filename)
   #
 
         self.getLogger().warning("Unrecognized extension for configuration file: %s", filename)
   #
 
+  def __loadMPI(self, module_name):
+    print "Trying to load MPI module: %s..."%module_name,
+    try:
+      out, err = subprocess.Popen(["modulecmd", "python", "load", module_name], stdout=subprocess.PIPE).communicate()
+      exec out # define specific environment variables
+      print " OK"
+    except:
+      print " ** Failed **"
+      pass
+  #
+
   def runSalome(self, args):
   def runSalome(self, args):
+    import os
     # Run this module as a script, in order to use appropriate Python interpreter
     # 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)
+    # according to current path (initialized from context files).
+    mpi_module_option = "--with-mpi-module="
+    mpi_module = [x for x in args if x.startswith(mpi_module_option)]
+    if mpi_module:
+      mpi_module = mpi_module[0][len(mpi_module_option):]
+      self.__loadMPI(mpi_module)
+      args = [x for x in args if not x.startswith(mpi_module_option)]
+    else:
+      mpi_module = os.getenv("SALOME_MPI_MODULE_NAME", None)
+      if mpi_module:
+        self.__loadMPI(mpi_module)
 
 
-    import os
     absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
     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)
     absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
     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, proc.returncode
+    out, err = proc.communicate()
+    return out, err, proc.returncode
   #
 
   """Append value to PATH environment variable"""
   #
 
   """Append value to PATH environment variable"""
@@ -135,7 +154,10 @@ class SalomeContext:
 
   """Append value to LD_LIBRARY_PATH environment variable"""
   def addToLdLibraryPath(self, value):
 
   """Append value to LD_LIBRARY_PATH environment variable"""
   def addToLdLibraryPath(self, value):
-    self.addToVariable('LD_LIBRARY_PATH', value)
+    if platform.system() == 'Windows':
+      self.addToVariable('PATH', value)
+    else:
+      self.addToVariable('LD_LIBRARY_PATH', value)
   #
 
   """Append value to DYLD_LIBRARY_PATH environment variable"""
   #
 
   """Append value to DYLD_LIBRARY_PATH environment variable"""
@@ -195,13 +217,17 @@ class SalomeContext:
     options = args[1:]
 
     availableCommands = {
     options = args[1:]
 
     availableCommands = {
-      'start' :   '_runAppli',
-      'shell' :   '_runSession',
+      'start'   : '_runAppli',
+      'context' : '_setContext',
+      'shell'   : '_runSession',
       'connect' : '_runConsole',
       'connect' : '_runConsole',
-      'killall':  '_killAll',
-      'info':     '_showInfo',
-      'help':     '_usage',
-      'coffee' :  '_makeCoffee'
+      'kill'    : '_kill',
+      'killall' : '_killAll',
+      'test'    : '_runTests',
+      'info'    : '_showInfo',
+      'help'    : '_usage',
+      'coffee'  : '_makeCoffee',
+      'car'     : '_getCar',
       }
 
     if not command in availableCommands.keys():
       }
 
     if not command in availableCommands.keys():
@@ -217,13 +243,16 @@ class SalomeContext:
   See usage for details on commands.
   """
   def _startSalome(self, args):
   See usage for details on commands.
   """
   def _startSalome(self, args):
+    import os
+    import sys
     try:
     try:
-      import os
+      from setenv import add_path
       absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH')
       absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH')
-      import sys
-      path = os.path.join(absoluteAppliPath, "bin", "salome")
-      if not path in sys.path:
-        sys.path[:0] = [path]
+      path = os.path.realpath(os.path.join(absoluteAppliPath, "bin", "salome"))
+      add_path(path, "PYTHONPATH")
+      path = os.path.realpath(os.path.join(absoluteAppliPath, "bin", "salome", "appliskel"))
+      add_path(path, "PYTHONPATH")
+
     except:
       pass
 
     except:
       pass
 
@@ -254,7 +283,7 @@ class SalomeContext:
       sys.exit(1)
   #
 
       sys.exit(1)
   #
 
-  def __setEnvironmentFromConfigFile(self, filename, reserved=None):
+  def __setContextFromConfigFile(self, filename, reserved=None):
     if reserved is None:
       reserved = []
     try:
     if reserved is None:
       reserved = []
     try:
@@ -265,12 +294,13 @@ class SalomeContext:
       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')
       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):
+      #if ext == ".cfg" and os.path.isfile(sh_file):
+      if False:
         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)
         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)
+          self.__setContextFromConfigFile(temp.name, reserved)
           msg += "OK\n"
           self.getLogger().warning(msg)
           temp.close()
           msg += "OK\n"
           self.getLogger().warning(msg)
           temp.close()
@@ -288,18 +318,24 @@ class SalomeContext:
     for var in unsetVars:
       self.unsetVariable(var)
 
     for var in unsetVars:
       self.unsetVariable(var)
 
-    # set environment
+    # set context
     for reserved in reservedDict:
       a = filter(None, reservedDict[reserved]) # remove empty elements
     for reserved in reservedDict:
       a = filter(None, reservedDict[reserved]) # remove empty elements
+      a = [ os.path.realpath(x) for x in a ]
       reformattedVals = os.pathsep.join(a)
       reformattedVals = os.pathsep.join(a)
-      self.addToVariable(reserved, reformattedVals)
+      if reserved in ["INCLUDE", "LIBPATH"]:
+        self.addToVariable(reserved, reformattedVals, separator=' ')
+      else:
+        self.addToVariable(reserved, reformattedVals)
       pass
 
     for key,val in configVars:
       self.setVariable(key, val, overwrite=True)
       pass
 
       pass
 
     for key,val in configVars:
       self.setVariable(key, val, overwrite=True)
       pass
 
-    sys.path[:0] = os.getenv('PYTHONPATH','').split(os.pathsep)
+    pythonpath = os.getenv('PYTHONPATH','').split(os.pathsep)
+    pythonpath = [ os.path.realpath(x) for x in pythonpath ]
+    sys.path[:0] = pythonpath
   #
 
   def _runAppli(self, args=None):
   #
 
   def _runAppli(self, args=None):
@@ -308,18 +344,38 @@ class SalomeContext:
     # Initialize SALOME environment
     sys.argv = ['runSalome'] + args
     import setenv
     # Initialize SALOME environment
     sys.argv = ['runSalome'] + args
     import setenv
-    setenv.main(True)
+    setenv.main(True, exeName="salome start")
 
     import runSalome
     runSalome.runSalome()
   #
 
 
     import runSalome
     runSalome.runSalome()
   #
 
+  def _setContext(self, args=None):
+    salome_context_set = os.getenv("SALOME_CONTEXT_SET")
+    if salome_context_set:
+      print "***"
+      print "*** SALOME context has already been set."
+      print "*** Enter 'exit' (only once!) to leave SALOME context."
+      print "***"
+      return
+
+    os.environ["SALOME_CONTEXT_SET"] = "yes"
+    print "***"
+    print "*** SALOME context is now set."
+    print "*** Enter 'exit' (only once!) to leave SALOME context."
+    print "***"
+
+    cmd = ["/bin/bash"]
+    proc = subprocess.Popen(cmd, shell=False, close_fds=True)
+    return proc.communicate()
+  #
+
   def _runSession(self, args=None):
     if args is None:
       args = []
     sys.argv = ['runSession'] + args
     import runSession
   def _runSession(self, args=None):
     if args is None:
       args = []
     sys.argv = ['runSession'] + args
     import runSession
-    params, args = runSession.configureSession(args)
+    params, args = runSession.configureSession(args, exe="salome shell")
 
     sys.argv = ['runSession'] + args
     import setenv
 
     sys.argv = ['runSession'] + args
     import setenv
@@ -332,18 +388,34 @@ class SalomeContext:
     if args is None:
       args = []
     # Initialize SALOME environment
     if args is None:
       args = []
     # Initialize SALOME environment
-    sys.argv = ['runConsole'] + args
+    sys.argv = ['runConsole']
     import setenv
     setenv.main(True)
 
     import setenv
     setenv.main(True)
 
-    cmd = ["python", "-c", "import runConsole\nrunConsole.connect()" ]
-    proc = subprocess.Popen(cmd, shell=False, close_fds=True)
-    return proc.communicate()
+    import runConsole
+    return runConsole.connect(args)
   #
 
   #
 
-  def _killAll(self, args=None):
+  def _kill(self, args=None):
     if args is None:
       args = []
     if args is None:
       args = []
+    ports = args
+    if not ports:
+      print "Port number(s) not provided to command: salome kill <port(s)>"
+      return
+
+    from multiprocessing import Process
+    from killSalomeWithPort import killMyPort
+    import tempfile
+    for port in ports:
+      with tempfile.NamedTemporaryFile():
+        p = Process(target = killMyPort, args=(port,))
+        p.start()
+        p.join()
+    pass
+  #
+
+  def _killAll(self, unused=None):
     try:
       import PortManager # mandatory
       from multiprocessing import Process
     try:
       import PortManager # mandatory
       from multiprocessing import Process
@@ -358,22 +430,81 @@ class SalomeContext:
             p.start()
             p.join()
     except ImportError:
             p.start()
             p.join()
     except ImportError:
+      # :TODO: should be declared obsolete
       from killSalome import killAllPorts
       killAllPorts()
       pass
       from killSalome import killAllPorts
       killAllPorts()
       pass
+  #
 
 
+  def _runTests(self, args=None):
+    if args is None:
+      args = []
+    sys.argv = ['runTests']
+    import setenv
+    setenv.main(True)
+
+    import runTests
+    return runTests.runTests(args, exe="salome test")
   #
 
   #
 
+  def _showSoftwareVersions(self):
+    config = ConfigParser.SafeConfigParser()
+    absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH')
+    filename = os.path.join(absoluteAppliPath, ".softwares_versions")
+    try:
+      config.read(filename)
+      sections = config.sections()
+      for section in sections:
+        entries = config.items(section, raw=True) # do not use interpolation
+        for key,val in entries:
+          version,text = [ x.strip() for x in val.split(',') ]
+          print "%s: %s"%(text, version)
+    except:
+      import traceback
+      traceback.print_exc()
+      return
+    pass
+
   def _showInfo(self, args=None):
   def _showInfo(self, args=None):
-    print "Running with python", platform.python_version()
-    self._runAppli(["--version"])
+    if args is None:
+      args = []
+
+    usage = "Usage: salome info [options]"
+    epilog  = """\n
+Display some information about SALOME.\n
+Available options are:
+    -p,--ports        Show the list of busy ports (running SALOME instances).
+    -s,--softwares    Show the list and versions of SALOME softwares.
+    -v,--version      Show running SALOME version.
+    -h,--help         Show this message.
+"""
+    if not args:
+      args = ["--version"]
+
+    if "-h" in args or "--help" in args:
+      print usage + epilog
+      return
+
+    if "-p" in args or "--ports" in args:
+      import PortManager
+      ports = PortManager.getBusyPorts()
+      print "SALOME instances are running on ports:", ports
+      if ports:
+        print "Last started instance on port %s"%ports[-1]
+
+    if "-s" in args or "--softwares" in args:
+      self._showSoftwareVersions()
+
+    if "-v" in args or "--version" in args:
+      print "Running with python", platform.python_version()
+      self._runAppli(["--version"])
   #
 
   def _usage(self, unused=None):
     usage()
   #
 
   #
 
   def _usage(self, unused=None):
     usage()
   #
 
-  def _makeCoffee(self, args=None):
+  def _makeCoffee(self, unused=None):
     print "                        ("
     print "                          )     ("
     print "                   ___...(-------)-....___"
     print "                        ("
     print "                          )     ("
     print "                   ___...(-------)-....___"
@@ -384,9 +515,9 @@ class SalomeContext:
     print "       |  |    |                             |"
     print "        \\  \\   |                             |"
     print "         `\\ `\\ |                             |"
     print "       |  |    |                             |"
     print "        \\  \\   |                             |"
     print "         `\\ `\\ |                             |"
-    print "           `\\ `|                             |"
-    print "           _/ /\\                             /"
-    print "          (__/  \\                           /"
+    print "           `\\ `|            SALOME           |"
+    print "           _/ /\\            4 EVER           /"
+    print "          (__/  \\             <3            /"
     print "       _..---\"\"` \\                         /`\"\"---.._"
     print "    .-\'           \\                       /          \'-."
     print "   :               `-.__             __.-\'              :"
     print "       _..---\"\"` \\                         /`\"\"---.._"
     print "    .-\'           \\                       /          \'-."
     print "   :               `-.__             __.-\'              :"
@@ -396,6 +527,43 @@ class SalomeContext:
     print "       \'._     \"\"\"----.....______.....----\"\"\"     _.\'"
     print "          `\"\"--..,,_____            _____,,..--\"\"`"
     print "                        `\"\"\"----\"\"\"`"
     print "       \'._     \"\"\"----.....______.....----\"\"\"     _.\'"
     print "          `\"\"--..,,_____            _____,,..--\"\"`"
     print "                        `\"\"\"----\"\"\"`"
+    print ""
+    print "                    SALOME is working for you; what else?"
+    print ""
+    sys.exit(0)
+  #
+
+  def _getCar(self, unused=None):
+    print "                                              _____________"
+    print "                                  ..---:::::::-----------. ::::;;."
+    print "                               .\'\"\"\"\"\"\"                  ;;   \\  \":."
+    print "                            .\'\'                          ;     \\   \"\\__."
+    print "                          .\'                            ;;      ;   \\\\\";"
+    print "                        .\'                              ;   _____;   \\\\/"
+    print "                      .\'                               :; ;\"     \\ ___:\'."
+    print "                    .\'--...........................    : =   ____:\"    \\ \\"
+    print "               ..-\"\"                               \"\"\"\'  o\"\"\"     ;     ; :"
+    print "          .--\"\"  .----- ..----...    _.-    --.  ..-\"     ;       ;     ; ;"
+    print "       .\"\"_-     \"--\"\"-----\'\"\"    _-\"        .-\"\"         ;        ;    .-."
+    print "    .\'  .\'   SALOME             .\"         .\"              ;       ;   /. |"
+    print "   /-./\'         4 EVER <3    .\"          /           _..  ;       ;   ;;;|"
+    print "  :  ;-.______               /       _________==.    /_  \\ ;       ;   ;;;;"
+    print "  ;  / |      \"\"\"\"\"\"\"\"\"\"\".---.\"\"\"\"\"\"\"          :    /\" \". |;       ; _; ;;;"
+    print " /\"-/  |                /   /                  /   /     ;|;      ;-\" | ;\';"
+    print ":-  :   \"\"\"----______  /   /              ____.   .  .\"\'. ;;   .-\"..T\"   ."
+    print "\'. \"  ___            \"\":   \'\"\"\"\"\"\"\"\"\"\"\"\"\"\"    .   ; ;    ;; ;.\" .\"   \'--\""
+    print " \",   __ \"\"\"  \"\"---... :- - - - - - - - - \' \'  ; ;  ;    ;;\"  .\""
+    print "  /. ;  \"\"\"---___                             ;  ; ;     ;|.\"\""
+    print " :  \":           \"\"\"----.    .-------.       ;   ; ;     ;:"
+    print "  \\  \'--__               \\   \\        \\     /    | ;     ;;"
+    print "   \'-..   \"\"\"\"---___      :   .______..\\ __/..-\"\"|  ;   ; ;"
+    print "       \"\"--..       \"\"\"--\"        m l s         .   \". . ;"
+    print "             \"\"------...                  ..--\"\"      \" :"
+    print "                        \"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"    \\        /"
+    print "                                               \"------\""
+    print ""
+    print "                                Drive your simulation properly with SALOME!"
+    print ""
     sys.exit(0)
   #
 
     sys.exit(0)
   #