Salome HOME
add the possibility to bypass the reinitialisation of paths with a dedicated variable...
[tools/sat.git] / src / fileEnviron.py
index ba3d54a9515cc3c394eab7d858d460f38013ce3b..dbf0938545537fbe2e056f8434032a343a34c19e 100644 (file)
@@ -22,32 +22,6 @@ import src.debug as DBG
 import src.architecture
 import src.environment
 
-bat_header="""\
-@echo off
-
-rem The following variables are used only in case of a sat package
-set out_dir_Path=%~dp0
-"""
-
-
-bash_header="""\
-#!/bin/bash
-##########################################################################
-#
-# This line is used only in case of a sat package
-export out_dir_Path=$(cd $(dirname ${BASH_SOURCE[0]});pwd)
-
-###########################################################################
-"""
-
-cfg_header="""\
-[SALOME Configuration]
-"""
-
-Launcher_header="""\
-# a generated SALOME Configuration file using python syntax
-"""
-
 def get_file_environ(output, shell, environ=None):
     """Instantiate correct FileEnvironment sub-class.
     
@@ -55,14 +29,18 @@ def get_file_environ(output, shell, environ=None):
     :param shell str: the type of shell syntax to use.
     :param environ dict: a potential additional environment.
     """
+    if environ == None:
+        environ=src.environment.Environ({})
     if shell == "bash":
-        return BashFileEnviron(output, src.environment.Environ({}))
+        return BashFileEnviron(output, environ)
+    if shell == "tcl":
+        return TclFileEnviron(output, environ)
     if shell == "bat":
-        return BatFileEnviron(output, src.environment.Environ({}))
+        return BatFileEnviron(output, environ)
     if shell == "cfgForPy":
-        return LauncherFileEnviron(output, src.environment.Environ({}))
+        return LauncherFileEnviron(output, environ)
     if shell == "cfg":
-        return ContextFileEnviron(output, src.environment.Environ({}))
+        return ContextFileEnviron(output, environ)
     raise Exception("FileEnviron: Unknown shell = %s" % shell)
 
 class FileEnviron(object):
@@ -152,7 +130,6 @@ class FileEnviron(object):
             value_list = self.environ.get(key).split(sep)
             if self.environ._expandvars(value) in value_list:
                 do_append=False  # value is already in key path : we don't append it again
-                #print "\nCNC append_value value is already set!! key=%s, val=%s value_list=%s\n" % (key,self.environ._expandvars(value), value_list)
             
         if do_append:
             self.environ.append_value(key, value,sep)
@@ -192,7 +169,6 @@ class FileEnviron(object):
             exp_val=self.environ._expandvars(value)
             if exp_val in value_list:
                 do_not_prepend=True
-                #print "\nCNC prepend_value value is already set!! key=%s, val=%s value_list=%s\n" % (key,exp_val, value_list)
         if not do_not_prepend:
             self.environ.prepend_value(key, value,sep)
             self.set(key, value + sep + self.get(key))
@@ -234,7 +210,10 @@ class FileEnviron(object):
         
         :param key str: the environment variable
         """
-        return '${%s}' % key
+        if src.architecture.is_windows():
+            return '%' + key + '%'
+        else:
+            return '${%s}' % key
 
     def get_value(self, key):
         """Get the real value of the environment variable "key"
@@ -243,7 +222,7 @@ class FileEnviron(object):
         """
         return self.environ.get_value(key)
 
-    def finish(self, required):
+    def finish(self):
         """Add a final instruction in the out file (in case of file generation)
         
         :param required bool: Do nothing if required is False
@@ -261,12 +240,79 @@ class FileEnviron(object):
 
     def value_filter(self, value):
         res=value
-        # on windows platform, replace / by \
-        if src.architecture.is_windows():
-            res = value.replace("/","\\")
         return res
 
 
+class TclFileEnviron(FileEnviron):
+    """\
+    Class for tcl shell.
+    """
+    def __init__(self, output, environ=None):
+        """Initialization
+        
+        :param output file: the output file stream.
+        :param environ dict: a potential additional environment.
+        """
+        self._do_init(output, environ)
+        self.output.write(tcl_header.replace("<module_name>",
+                                             self.environ.get("sat_product_name")))
+        self.output.write("\nset software %s\n" % self.environ.get("sat_product_name") )
+        self.output.write("set version %s\n" % self.environ.get("sat_product_version") )
+        root=os.path.join(self.environ.get("sat_product_base_path"),  
+                                  "apps", 
+                                  self.environ.get("sat_product_base_name"), 
+                                  "$software", 
+                                  "$version")
+        self.output.write("set root %s\n" % root) 
+        modules_to_load=self.environ.get("sat_product_load_depend")
+        if len(modules_to_load)>0:
+            # write module load commands for product dependencies
+            self.output.write("\n")
+            for module_to_load in modules_to_load.split(";"):
+                self.output.write(module_to_load+"\n")
+
+    def set(self, key, value):
+        """Set the environment variable "key" to value "value"
+        
+        :param key str: the environment variable to set
+        :param value str: the value
+        """
+        self.output.write('setenv  %s "%s"\n' % (key, value))
+        self.environ.set(key, value)
+        
+    def get(self, key):
+        """\
+        Get the value of the environment variable "key"
+        
+        :param key str: the environment variable
+        """
+        return self.environ.get(key)
+
+    def append_value(self, key, value, sep=os.pathsep):
+        """append value to key using sep
+        
+        :param key str: the environment variable to append
+        :param value str: the value to append to key
+        :param sep str: the separator string
+        """
+        if sep==os.pathsep:
+            self.output.write('append-path  %s   %s\n' % (key, value))
+        else:
+            self.output.write('append-path --delim=\%c %s   %s\n' % (sep, key, value))
+
+    def prepend_value(self, key, value, sep=os.pathsep):
+        """prepend value to key using sep
+        
+        :param key str: the environment variable to prepend
+        :param value str: the value to prepend to key
+        :param sep str: the separator string
+        """
+        if sep==os.pathsep:
+            self.output.write('prepend-path  %s   %s\n' % (key, value))
+        else:
+            self.output.write('prepend-path --delim=\%c %s   %s\n' % (sep, key, value))
+
+        
 class BashFileEnviron(FileEnviron):
     """\
     Class for bash shell.
@@ -327,14 +373,6 @@ class BatFileEnviron(FileEnviron):
         self.output.write('set %s=%s\n' % (key, self.value_filter(value)))
         self.environ.set(key, value)
 
-    def finish(self, required=True):
-        """\
-        Add a final instruction in the out file (in case of file generation)
-        In the particular windows case, do nothing
-        
-        :param required bool: Do nothing if required is False
-        """
-        return
 
 class ContextFileEnviron(FileEnviron):
     """Class for a salome context configuration file.
@@ -405,13 +443,6 @@ class ContextFileEnviron(FileEnviron):
         """
         self.prepend_value(key, value)
 
-    def finish(self, required=True):
-        """Add a final instruction in the out file (in case of file generation)
-        
-        :param required bool: Do nothing if required is False
-        """
-        return
-
 
 class LauncherFileEnviron(FileEnviron):
     """\
@@ -425,14 +456,27 @@ class LauncherFileEnviron(FileEnviron):
         :param environ dict: a potential additional environment.
         """
         self._do_init(output, environ)
+        self.python_version=self.environ.get("sat_python_version")
+        self.bin_kernel_root_dir=self.environ.get("sat_bin_kernel_install_dir")
 
         # four whitespaces for first indentation in a python script
         self.indent="    "
         self.prefix="context."
         self.setVarEnv="setVariable"
-        
         self.begin=self.indent+self.prefix
-        self.output.write(Launcher_header)
+
+        # write the begining of launcher file.
+        # choose the template version corresponding to python version 
+        # and substitute BIN_KERNEL_INSTALL_DIR (the path to salomeContext.py)
+        if self.python_version == 2:
+            launcher_header=launcher_header2
+        else:
+            launcher_header=launcher_header3
+        # in case of Windows OS, Python scripts are not executable.  PyExe ?
+        if src.architecture.is_windows():
+            launcher_header = launcher_header.replace("#! /usr/bin/env python3",'')
+        self.output.write(launcher_header\
+                          .replace("BIN_KERNEL_INSTALL_DIR", self.bin_kernel_root_dir))
 
         # for these path, we use specialired functions in salomeContext api
         self.specialKeys={"PATH": "Path",
@@ -445,6 +489,10 @@ class LauncherFileEnviron(FileEnviron):
         if not self.environ.is_defined("PATH"):
             self.environ.set("PATH","")
 
+        if self.init_path:
+            self.output.write('\n'+self.indent)
+            self.add_echo("Modifier cette variable pour ne pas réinitialiser les PATHS")
+            self.output.write(self.indent+'reinitialise_paths=True\n\n')
 
     def add_echo(self, text):
         """Add a comment
@@ -460,16 +508,50 @@ class LauncherFileEnviron(FileEnviron):
         """
         self.output.write('# "WARNING %s"\n' % warning)
 
-    def append_value(self, key, value, sep=":"):
+    def append_value(self, key, value, sep=os.pathsep):
         """append value to key using sep,
         if value contains ":" or ";" then raise error
         
-        :param key str: the environment variable to append
-        :param value str: the value to append to key
+        :param key str: the environment variable to prepend
+        :param value str: the value to prepend to key
         :param sep str: the separator string
         """
-        # append is not defined in context api
-        self.prepend_value(key, value)
+        # check that value so no contain the system separator
+        separator=os.pathsep
+        msg="LauncherFileEnviron append key '%s' value '%s' contains forbidden character '%s'"
+        if separator in value:
+            raise Exception(msg % (key, value, separator))
+
+        is_key_defined=self.environ.is_defined(key)
+        conditional_reinit=False
+        if (self.init_path and (not is_key_defined)):
+            # reinitialisation mode set to true (the default)
+            # for the first occurrence of key, we set it.
+            # therefore key will not be inherited from environment
+            self.output.write(self.indent+'if reinitialise_paths:\n'+self.indent)
+            self.set(key, value)
+            self.output.write(self.indent+'else:\n'+self.indent)
+            conditional_reinit=True # in this case do not register value in self.environ a second time
+
+        # in all other cases we use append (except if value is already the key
+        do_append=True
+        if is_key_defined:
+            value_list = self.environ.get(key).split(sep)
+            # rem : value cannot be expanded (unlike bash/bat case) - but it doesn't matter.
+            if value in value_list:
+                do_append=False  # value is already in key path : we don't append it again
+            
+        if do_append:
+            if not conditional_reinit:
+                self.environ.append_value(key, value,sep) # register value in self.environ
+            if key in self.specialKeys.keys():
+                #for these special keys we use the specific salomeContext function
+                self.output.write(self.begin+'addTo%s(r"%s")\n' % 
+                                  (self.specialKeys[key], self.value_filter(value)))
+            else:
+                # else we use the general salomeContext addToVariable function
+                self.output.write(self.indent+'appendPath(r"%s", r"%s",separator="%s")\n' 
+                                  % (key, self.value_filter(value), sep))
 
     def append(self, key, value, sep=":"):
         """Same as append_value but the value argument can be a list
@@ -498,22 +580,28 @@ class LauncherFileEnviron(FileEnviron):
         if separator in value:
             raise Exception(msg % (key, value, separator))
 
-        if (self.init_path and (not self.environ.is_defined(key))):
+        is_key_defined=self.environ.is_defined(key)
+        conditional_reinit=False
+        if (self.init_path and (not is_key_defined)):
             # reinitialisation mode set to true (the default)
             # for the first occurrence of key, we set it.
             # therefore key will not be inherited from environment
+            self.output.write(self.indent+'if reinitialise_paths:\n'+self.indent)
             self.set(key, value)
-            return
+            self.output.write(self.indent+'else:\n'+self.indent)
+            conditional_reinit=True # in this case do not register value in self.environ a second time
+
         # in all other cases we use append (except if value is already the key
         do_append=True
-        if self.environ.is_defined(key):
+        if is_key_defined:
             value_list = self.environ.get(key).split(sep)
             # rem : value cannot be expanded (unlike bash/bat case) - but it doesn't matter.
             if value in value_list:
                 do_append=False  # value is already in key path : we don't append it again
             
         if do_append:
-            self.environ.append_value(key, value,sep) # register value in self.environ
+            if not conditional_reinit:
+                self.environ.append_value(key, value,sep) # register value in self.environ
             if key in self.specialKeys.keys():
                 #for these special keys we use the specific salomeContext function
                 self.output.write(self.begin+'addTo%s(r"%s")\n' % 
@@ -551,7 +639,7 @@ class LauncherFileEnviron(FileEnviron):
     
 
     def add_comment(self, comment):
-        # Special comment in case of the distène licence
+        # Special comment in case of the DISTENE licence
         if comment=="DISTENE license":
             self.output.write(self.indent+
                               "#"+
@@ -573,13 +661,18 @@ class LauncherFileEnviron(FileEnviron):
 
         self.output.write(self.indent+"# %s\n" % comment)
 
-    def finish(self, required=True):
+    def finish(self):
         """\
         Add a final instruction in the out file (in case of file generation)
         In the particular launcher case, do nothing
         
         :param required bool: Do nothing if required is False
         """
+        if self.python_version == 2:
+            launcher_tail=launcher_tail_py2
+        else:
+            launcher_tail=launcher_tail_py3
+        self.output.write(launcher_tail)
         return
 
 class ScreenEnviron(FileEnviron):
@@ -631,8 +724,48 @@ class ScreenEnviron(FileEnviron):
     def run_env_script(self, module, script):
         self.write("load", script, "", sign="")
 
-# The SALOME launcher template 
-withProfile =  """\
+
+#
+#  Headers
+#
+bat_header="""\
+@echo off
+
+rem The following variables are used only in case of a sat package
+set out_dir_Path=%~dp0
+"""
+
+tcl_header="""\
+#%Module -*- tcl -*-
+#
+# <module_name> module for use with 'environment-modules' package
+#
+"""
+
+bash_header="""\
+#!/bin/bash
+if [ "$BASH" = "" ]
+then
+  # check that the user is not using another shell
+  echo
+  echo "Warning! SALOME environment not initialized"
+  echo "You must run this script in a bash shell."
+  echo "As you are using another shell. Please first run: bash"
+  echo
+fi
+##########################################################################
+#
+# This line is used only in case of a sat package
+export out_dir_Path=$(cd $(dirname ${BASH_SOURCE[0]});pwd)
+
+###########################################################################
+"""
+
+cfg_header="""\
+[SALOME Configuration]
+"""
+
+launcher_header2="""\
 #! /usr/bin/env python
 
 ################################################################
@@ -643,7 +776,7 @@ withProfile =  """\
 import os
 import sys
 import subprocess
-
+import os.path
 
 # Add the pwdPath to able to run the launcher after unpacking a package
 # Used only in case of a salomeTools package
@@ -652,8 +785,7 @@ out_dir_Path=os.path.dirname(os.path.realpath(__file__))
 # Preliminary work to initialize path to SALOME Python modules
 def __initialize():
 
-  sys.path[:0] = [ 'BIN_KERNEL_INSTALL_DIR' ]
-  os.environ['ABSOLUTE_APPLI_PATH'] = 'KERNEL_INSTALL_DIR'
+  sys.path[:0] = [ r'BIN_KERNEL_INSTALL_DIR' ]  # to get salomeContext
   
   # define folder to store omniorb config (initially in virtual application folder)
   try:
@@ -678,9 +810,9 @@ def _showDoc(modules):
         if os.path.isfile(docfile):
           out, err = subprocess.Popen(["xdg-open", docfile]).communicate()
         else:
-          print "Online documentation is not accessible for module:", module
+          print ("Online documentation is not accessible for module:", module)
       else:
-        print module+"_ROOT_DIR not found!"
+        print (module+"_ROOT_DIR not found!")
 
 def main(args):
   # Identify application path then locate configuration files
@@ -691,11 +823,6 @@ def main(args):
     usage()
     sys.exit(0)
 
-  #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 SalomeContext which parses configFileNames to initialize environment
   try:
@@ -710,30 +837,9 @@ def main(args):
 
     # Logger level error
     context.getLogger().setLevel(40)
-
-    # here your local standalone environment
-
-    if len(args) >1 and args[0]=='doc':
-        _showDoc(args[1:])
-        return
-
-    # Start SALOME, parsing command line arguments
-    out, err, status = context.runSalome(args)
-    sys.exit(status)
-
-  except SalomeContextException, e:
-    import logging
-    logging.getLogger("salome").error(e)
-    sys.exit(1)
-#
-
-if __name__ == "__main__":
-  args = sys.argv[1:]
-  main(args)
-#
 """
-    
-withProfile3 =  """\
+
+launcher_header3="""\
 #! /usr/bin/env python3
 
 ################################################################
@@ -744,7 +850,7 @@ withProfile3 =  """\
 import os
 import sys
 import subprocess
-
+import os.path
 
 # Add the pwdPath to able to run the launcher after unpacking a package
 # Used only in case of a salomeTools package
@@ -753,8 +859,7 @@ out_dir_Path=os.path.dirname(os.path.realpath(__file__))
 # Preliminary work to initialize path to SALOME Python modules
 def __initialize():
 
-  sys.path[:0] = [ 'BIN_KERNEL_INSTALL_DIR' ]
-  os.environ['ABSOLUTE_APPLI_PATH'] = 'KERNEL_INSTALL_DIR'
+  sys.path[:0] = [ r'BIN_KERNEL_INSTALL_DIR' ]
   
   # define folder to store omniorb config (initially in virtual application folder)
   try:
@@ -811,9 +916,30 @@ def main(args):
 
     # Logger level error
     context.getLogger().setLevel(40)
+"""
+
+launcher_tail_py2="""\
+    #[hook to integrate in launcher additionnal user modules]
+    
+    # Load all files extra.env.d/*.py and call the module's init routine]
+
+    extradir=out_dir_Path + r"/extra.env.d"
 
-    # here your local standalone environment
+    if os.path.exists(extradir):
+        import imp
+        sys.path.insert(0, os.path.join(os.getcwd(), extradir))
+        for filename in sorted(
+            filter(lambda x: os.path.isfile(os.path.join(extradir, x)),
+                   os.listdir(extradir))):
 
+            if filename.endswith(".py"):
+                f = os.path.join(extradir, filename)
+                module_name = os.path.splitext(os.path.basename(f))[0]
+                fp, path, desc = imp.find_module(module_name)
+                module = imp.load_module(module_name, fp, path, desc)
+                module.init(context, out_dir_Path)
+
+    #[manage salome doc command]
     if len(args) >1 and args[0]=='doc':
         _showDoc(args[1:])
         return
@@ -822,15 +948,82 @@ def main(args):
     out, err, status = context.runSalome(args)
     sys.exit(status)
 
-  except SalomeContextException as e:
+  except SalomeContextException, e:
     import logging
     logging.getLogger("salome").error(e)
     sys.exit(1)
 #
+# salomeContext only prepend variables, we use our own appendPath when required
+def appendPath(name, value, separator=os.pathsep):
+    if value == '':
+      return
+
+    value = os.path.expandvars(value) # expand environment variables
+    env = os.getenv(name, None)
+    if env is None:
+      os.environ[name] = value
+    else:
+      os.environ[name] = env + separator + value
+
 
 if __name__ == "__main__":
   args = sys.argv[1:]
   main(args)
 #
 """
+
+launcher_tail_py3="""\
+    #[hook to integrate in launcher additionnal user modules]
     
+    # Load all files extra.env.d/*.py and call the module's init routine]
+
+    extradir=out_dir_Path + r"/extra.env.d"
+
+    if os.path.exists(extradir):
+        import imp
+        sys.path.insert(0, os.path.join(os.getcwd(), extradir))
+        for filename in sorted(
+            filter(lambda x: os.path.isfile(os.path.join(extradir, x)),
+                   os.listdir(extradir))):
+
+            if filename.endswith(".py"):
+                f = os.path.join(extradir, filename)
+                module_name = os.path.splitext(os.path.basename(f))[0]
+                fp, path, desc = imp.find_module(module_name)
+                module = imp.load_module(module_name, fp, path, desc)
+                module.init(context, out_dir_Path)
+
+    #[manage salome doc command]
+    if len(args) >1 and args[0]=='doc':
+        _showDoc(args[1:])
+        return
+
+    # Start SALOME, parsing command line arguments
+    out, err, status = context.runSalome(args)
+    sys.exit(status)
+
+  except SalomeContextException as e:
+    import logging
+    logging.getLogger("salome").error(e)
+    sys.exit(1)
+# salomeContext only prepend variables, we use our own appendPath when required
+def appendPath(name, value, separator=os.pathsep):
+    if value == '':
+      return
+
+    value = os.path.expandvars(value) # expand environment variables
+    env = os.getenv(name, None)
+    if env is None:
+      os.environ[name] = value
+    else:
+      os.environ[name] = env + separator + value
+
+
+if __name__ == "__main__":
+  args = sys.argv[1:]
+  main(args)
+#
+"""
+    
+