Salome HOME
Merge changes from 'master' branch.
[modules/kernel.git] / bin / salomeContext.py
index 2bed9040420850b03b6122bada1bef81d7837802..aa8ce10a654fc742b830fca5b18045e52178084f 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2013-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2013-2017  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
 import os
 import sys
 import logging
-import ConfigParser
+import configparser
 
 from parseConfigFile import parseConfigFile
-from parseConfigFile import convertEnvFileToConfigFile
 
 import tempfile
 import pickle
@@ -42,7 +41,7 @@ Commands:
     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
+                    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.
@@ -51,14 +50,16 @@ Commands:
                     Do not start a new one.
     test            Run SALOME tests.
     info            Display some information about SALOME.
+    doc <module(s)> Show online module documentation (if available).
+                    Module names must be separated by blank characters.
     help            Show this message.
 
-If no command is given, default to start.
+If no command is given, default is start.
 
 Command options:
 ================
-    Use salome <command> --help to show help on command ; available for commands:
-    start, shell, connect, test, info.
+    Use salome <command> --help to show help on command. Available for the
+    following commands: start, shell, connect, test, info.
 
 --config=<file,folder,...>
 ==========================
@@ -67,7 +68,7 @@ Command options:
     any blank characters.
 '''
 
-  print msg
+  print(msg)
 #
 
 """
@@ -79,49 +80,34 @@ class SalomeContext:
   """
   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
-  to .cfg format before setting the context.
+  These files should be in appropriate .cfg format.
   """
   def __init__(self, configFileNames=0):
     self.getLogger().setLevel(logging.INFO)
-    #it could be None explicitely (if user use multiples setVariable...for standalone)
+    #it could be None explicitly (if user use multiples setVariable...for standalone)
     if configFileNames is None:
        return
     configFileNames = configFileNames or []
     if len(configFileNames) == 0:
       raise SalomeContextException("No configuration files given")
 
-    reserved=['PATH', 'DYLD_LIBRARY_PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'PV_PLUGIN_PATH', 'INCLUDE', 'LIBPATH', 'SALOME_PLUGINS_PATH']
+    reserved=['PATH', 'DYLD_FALLBACK_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'PV_PLUGIN_PATH', 'INCLUDE', 'LIBPATH', 'SALOME_PLUGINS_PATH', 'LIBRARY_PATH', 'QT_PLUGIN_PATH']
     for filename in configFileNames:
       basename, extension = os.path.splitext(filename)
       if extension == ".cfg":
         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)
-          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()
-          sys.exit(1)
       else:
-        self.getLogger().warning("Unrecognized extension for configuration file: %s", filename)
+        self.getLogger().error("Unrecognized extension for configuration file: %s", filename)
   #
 
-  def __loadMPI(self, module_name):
-    print "Trying to load MPI module: %s..."%module_name,
+  def __loadEnvModules(self, env_modules):
+    print("Trying to load env modules: %s..." % ' '.join(env_modules))
     try:
-      out, err = subprocess.Popen(["modulecmd", "python", "load", module_name], stdout=subprocess.PIPE).communicate()
-      exec out # define specific environment variables
-      print " OK"
+      out, err = subprocess.Popen(["modulecmd", "python", "load"] + env_modules, stdout=subprocess.PIPE).communicate()
+      exec(out) # define specific environment variables
+      print("OK")
     except:
-      print " ** Failed **"
+      print("** Failed **")
       pass
   #
 
@@ -129,20 +115,22 @@ class SalomeContext:
     import os
     # Run this module as a script, in order to use appropriate Python interpreter
     # 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)]
+    env_modules_option = "--with-env-modules="
+    env_modules_l = [x for x in args if x.startswith(env_modules_option)]
+    if env_modules_l:
+      env_modules = env_modules_l[-1][len(env_modules_option):].split(',')
+      self.__loadEnvModules(env_modules)
+      args = [x for x in args if not x.startswith(env_modules_option)]
     else:
-      mpi_module = os.getenv("SALOME_MPI_MODULE_NAME", None)
-      if mpi_module:
-        self.__loadMPI(mpi_module)
+      env_modules = os.getenv("SALOME_ENV_MODULES", None)
+      if env_modules:
+        self.__loadEnvModules(env_modules.split(','))
 
     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)
+    selfBytes= pickle.dumps(self, protocol=0)
+    argsBytes= pickle.dumps(args, protocol=0)
+    proc = subprocess.Popen(['python3', os.path.join(absoluteAppliPath,"bin","salome","salomeContext.py"), selfBytes.decode(), argsBytes.decode()], shell=False, close_fds=True, env=env_copy)
     out, err = proc.communicate()
     return out, err, proc.returncode
   #
@@ -156,6 +144,11 @@ class SalomeContext:
   def addToLdLibraryPath(self, value):
     if platform.system() == 'Windows':
       self.addToVariable('PATH', value)
+    elif platform.system() == 'Darwin':
+      if "LAPACK" in value:
+        self.addToVariable('DYLD_FALLBACK_LIBRARY_PATH', value)
+      else:
+        self.addToVariable('DYLD_LIBRARY_PATH', value)
     else:
       self.addToVariable('LD_LIBRARY_PATH', value)
   #
@@ -174,11 +167,11 @@ class SalomeContext:
   def setVariable(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)
+      self.getLogger().error("Environment variable already existing (and not overwritten): %s=%s", name, value)
       return
 
     if env:
-      self.getLogger().warning("Overwriting environment variable: %s=%s", name, value)
+      self.getLogger().debug("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)
@@ -225,12 +218,13 @@ class SalomeContext:
       'killall' : '_killAll',
       'test'    : '_runTests',
       'info'    : '_showInfo',
+      'doc'     : '_showDoc',
       'help'    : '_usage',
       'coffee'  : '_makeCoffee',
       'car'     : '_getCar',
       }
 
-    if not command in availableCommands.keys():
+    if command not in availableCommands:
       command = "start"
       options = args
 
@@ -239,7 +233,7 @@ class SalomeContext:
 
   """
   Run SALOME!
-  Args consist in a mandatory command followed by optionnal parameters.
+  Args consist in a mandatory command followed by optional parameters.
   See usage for details on commands.
   """
   def _startSalome(self, args):
@@ -262,25 +256,25 @@ class SalomeContext:
     if command is None:
       if args and args[0] in ["-h","--help","help"]:
         usage()
-        sys.exit(0)
+        return 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, returncode:
-      if returncode != 0:
-        self.getLogger().warning("SystemExit %s in method %s.", returncode, command)
-      sys.exit(returncode)
-    except StandardError:
+      return res or 0
+    except SystemExit as ex:
+      if ex.code != 0:
+        self.getLogger().error("SystemExit %s in method %s.", ex.code, command)
+      return ex.code
+    except SalomeContextException as e:
+      self.getLogger().error(e)
+      return 1
+    except Exception:
       self.getLogger().error("Unexpected error:")
       import traceback
       traceback.print_exc()
-      sys.exit(1)
-    except SalomeContextException, e:
-      self.getLogger().error(e)
-      sys.exit(1)
+      return 1
   #
 
   def __setContextFromConfigFile(self, filename, reserved=None):
@@ -288,30 +282,10 @@ class SalomeContext:
       reserved = []
     try:
       unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved)
-    except SalomeContextException, e:
+    except SalomeContextException as 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.__setContextFromConfigFile(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)
+      self.getLogger().error(msg)
+      return 1
 
     # unset variables
     for var in unsetVars:
@@ -319,7 +293,7 @@ class SalomeContext:
 
     # set context
     for reserved in reservedDict:
-      a = filter(None, reservedDict[reserved]) # remove empty elements
+      a = [_f for _f in reservedDict[reserved] if _f] # remove empty elements
       a = [ os.path.realpath(x) for x in a ]
       reformattedVals = os.pathsep.join(a)
       if reserved in ["INCLUDE", "LIBPATH"]:
@@ -347,26 +321,28 @@ class SalomeContext:
 
     import runSalome
     runSalome.runSalome()
+    return 0
   #
 
   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
+      print("***")
+      print("*** SALOME context has already been set.")
+      print("*** Enter 'exit' (only once!) to leave SALOME context.")
+      print("***")
+      return 0
 
     os.environ["SALOME_CONTEXT_SET"] = "yes"
-    print "***"
-    print "*** SALOME context is now set."
-    print "*** Enter 'exit' (only once!) to leave SALOME context."
-    print "***"
+    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()
+    proc.communicate()
+    return proc.returncode
   #
 
   def _runSession(self, args=None):
@@ -400,8 +376,8 @@ class SalomeContext:
       args = []
     ports = args
     if not ports:
-      print "Port number(s) not provided to command: salome kill <port(s)>"
-      return
+      print("Port number(s) not provided to command: salome kill <port(s)>")
+      return 1
 
     from multiprocessing import Process
     from killSalomeWithPort import killMyPort
@@ -411,7 +387,7 @@ class SalomeContext:
         p = Process(target = killMyPort, args=(port,))
         p.start()
         p.join()
-    pass
+    return 0
   #
 
   def _killAll(self, unused=None):
@@ -419,7 +395,7 @@ class SalomeContext:
       import PortManager # mandatory
       from multiprocessing import Process
       from killSalomeWithPort import killMyPort
-      ports = PortManager.getBusyPorts()
+      ports = PortManager.getBusyPorts()['this']
 
       if ports:
         import tempfile
@@ -433,6 +409,7 @@ class SalomeContext:
       from killSalome import killAllPorts
       killAllPorts()
       pass
+    return 0
   #
 
   def _runTests(self, args=None):
@@ -446,6 +423,34 @@ class SalomeContext:
     return runTests.runTests(args, exe="salome test")
   #
 
+  def _showSoftwareVersions(self, softwares=None):
+    config = configparser.SafeConfigParser()
+    absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH')
+    filename = os.path.join(absoluteAppliPath, "sha1_collections.txt")
+    versions = {}
+    max_len = 0
+    with open(filename) as f:
+      for line in f:
+        try:
+          software, version, sha1 = line.split()
+          versions[software.upper()] = version
+          if len(software) > max_len:
+            max_len = len(software)
+        except:
+          pass
+        pass
+      pass
+    if softwares:
+      for soft in softwares:
+        if versions.has_key(soft.upper()):
+          print(soft.upper().rjust(max_len), versions[soft.upper()])
+    else:
+      import collections
+      od = collections.OrderedDict(sorted(versions.items()))
+      for name, version in od.iteritems():
+        print(name.rjust(max_len), versions[name])
+    pass
+
   def _showInfo(self, args=None):
     if args is None:
       args = []
@@ -454,94 +459,142 @@ class SalomeContext:
     epilog  = """\n
 Display some information about SALOME.\n
 Available options are:
-    -p,--ports        Show list of busy ports (running SALOME instances).
-    -v,--version      Show running SALOME version.
-    -h,--help         Show this message.
+    -p,--ports                     Show the list of busy ports (running SALOME instances).
+    -s,--softwares [software(s)]   Show the list and versions of SALOME softwares.
+                                   Software names must be separated by blank characters.
+                                   If no software is given, show version of all 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
+      print(usage + epilog)
+      return 0
 
     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]
+      this_ports = ports['this']
+      other_ports = ports['other']
+      if this_ports or other_ports:
+          print("SALOME instances are running on the following ports:")
+          if this_ports:
+              print("   This application:", this_ports)
+          else:
+              print("   No SALOME instances of this application")
+          if other_ports:
+              print("   Other applications:", other_ports)
+          else:
+              print("   No SALOME instances of other applications")
+      else:
+          print("No SALOME instances are running")
+
+    if "-s" in args or "--softwares" in args:
+      if "-s" in args:
+        index = args.index("-s")
+      else:
+        index = args.index("--softwares")
+      indexEnd=index+1
+      while indexEnd < len(args) and args[indexEnd][0] != "-":
+        indexEnd = indexEnd + 1
+      self._showSoftwareVersions(softwares=args[index+1:indexEnd])
 
     if "-v" in args or "--version" in args:
-      print "Running with python", platform.python_version()
-      self._runAppli(["--version"])
+      print("Running with python", platform.python_version())
+      return self._runAppli(["--version"])
+
+    return 0
   #
 
+  def _showDoc(self, args=None):
+    if args is None:
+      args = []
+
+    modules = args
+    if not modules:
+      print("Module(s) not provided to command: salome doc <module(s)>")
+      return 1
+
+    appliPath = os.getenv("ABSOLUTE_APPLI_PATH")
+    if not appliPath:
+      raise SalomeContextException("Unable to find application path. Please check that the variable ABSOLUTE_APPLI_PATH is set.")
+    baseDir = os.path.join(appliPath, "share", "doc", "salome")
+    for module in modules:
+      docfile = os.path.join(baseDir, "gui", module.upper(), "index.html")
+      if not os.path.isfile(docfile):
+        docfile = os.path.join(baseDir, "tui", module.upper(), "index.html")
+      if not os.path.isfile(docfile):
+        docfile = os.path.join(baseDir, "dev", module.upper(), "index.html")
+      if os.path.isfile(docfile):
+        out, err = subprocess.Popen(["xdg-open", docfile]).communicate()
+      else:
+        print("Online documentation is not accessible for module:", module)
+
   def _usage(self, unused=None):
     usage()
   #
 
   def _makeCoffee(self, unused=None):
-    print "                        ("
-    print "                          )     ("
-    print "                   ___...(-------)-....___"
-    print "               .-\"\"       )    (          \"\"-."
-    print "         .-\'``\'|-._             )         _.-|"
-    print "        /  .--.|   `\"\"---...........---\"\"`   |"
-    print "       /  /    |                             |"
-    print "       |  |    |                             |"
-    print "        \\  \\   |                             |"
-    print "         `\\ `\\ |                             |"
-    print "           `\\ `|            SALOME           |"
-    print "           _/ /\\            4 EVER           /"
-    print "          (__/  \\             <3            /"
-    print "       _..---\"\"` \\                         /`\"\"---.._"
-    print "    .-\'           \\                       /          \'-."
-    print "   :               `-.__             __.-\'              :"
-    print "   :                  ) \"\"---...---\"\" (                 :"
-    print "    \'._               `\"--...___...--\"`              _.\'"
-    print "      \\\"\"--..__                              __..--\"\"/"
-    print "       \'._     \"\"\"----.....______.....----\"\"\"     _.\'"
-    print "          `\"\"--..,,_____            _____,,..--\"\"`"
-    print "                        `\"\"\"----\"\"\"`"
-    print ""
-    print "                    SALOME is working for you; what else?"
-    print ""
-    sys.exit(0)
+    print("                        (")
+    print("                          )     (")
+    print("                   ___...(-------)-....___")
+    print("               .-\"\"       )    (          \"\"-.")
+    print("         .-\'``\'|-._             )         _.-|")
+    print("        /  .--.|   `\"\"---...........---\"\"`   |")
+    print("       /  /    |                             |")
+    print("       |  |    |                             |")
+    print("        \\  \\   |                             |")
+    print("         `\\ `\\ |                             |")
+    print("           `\\ `|            SALOME           |")
+    print("           _/ /\\            4 EVER           /")
+    print("          (__/  \\             <3            /")
+    print("       _..---\"\"` \\                         /`\"\"---.._")
+    print("    .-\'           \\                       /          \'-.")
+    print("   :               `-.__             __.-\'              :")
+    print("   :                  ) \"\"---...---\"\" (                 :")
+    print("    \'._               `\"--...___...--\"`              _.\'")
+    print("      \\\"\"--..__                              __..--\"\"/")
+    print("       \'._     \"\"\"----.....______.....----\"\"\"     _.\'")
+    print("          `\"\"--..,,_____            _____,,..--\"\"`")
+    print("                        `\"\"\"----\"\"\"`")
+    print("")
+    print("                    SALOME is working for you; what else?")
+    print("")
   #
 
   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)
+    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("")
   #
 
   # Add the following two methods since logger is not pickable
@@ -567,14 +620,11 @@ Available options are:
 
 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)
-    if err:
-      sys.stderr.write(err)
+    context = pickle.loads(sys.argv[1].encode())
+    args = pickle.loads(sys.argv[2].encode())
+
+    status = context._startSalome(args)
+    sys.exit(status)
   else:
     usage()
 #