Salome HOME
f4816e7e239f18dcef76c7523e2dff72c84f1fae
[tools/sat.git] / src / environment.py
1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3 #  Copyright (C) 2010-2013  CEA/DEN
4 #
5 #  This library is free software; you can redistribute it and/or
6 #  modify it under the terms of the GNU Lesser General Public
7 #  License as published by the Free Software Foundation; either
8 #  version 2.1 of the License.
9 #
10 #  This library is distributed in the hope that it will be useful,
11 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 #  Lesser General Public License for more details.
14 #
15 #  You should have received a copy of the GNU Lesser General Public
16 #  License along with this library; if not, write to the Free Software
17 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18
19 import os
20 import subprocess
21 import string
22 import sys
23
24 import src
25 import src.debug as DBG
26 import pprint as PP
27
28
29 class Environ:
30     """\
31     Class to manage the environment context
32     """
33     def __init__(self, environ=None):
34         """Initialization. If the environ argument is passed, the environment
35            will be add to it, else it is the external environment.
36            
37         :param environ dict:  
38         """
39         if environ is not None:
40             self.environ = environ
41         else:
42             self.environ = os.environ
43
44     def __repr__(self):
45         """easy non exhaustive quick resume for debug print"""
46         return "%s(\n%s\n)" % (self.__class__.__name__, PP.pformat(self.environ))
47
48     def _expandvars(self, value):
49         """\
50         replace some $VARIABLE into its actual value in the environment
51         
52         :param value str: the string to be replaced
53         :return: the replaced variable
54         :rtype: str
55         """
56         if "$" in value:
57             # The string.Template class is a string class 
58             # for supporting $-substitutions
59             zt = string.Template(value)
60             try:
61                 value = zt.substitute(self.environ)
62             except KeyError as exc:
63                 raise src.SatException(_("Missing definition "
64                                          "in environment: %s") % str(exc))
65         return value
66
67     def append_value(self, key, value, sep=os.pathsep):
68         """\
69         append value to key using sep,
70         if value contains ":" or ";" then raise error
71
72         :param key str: the environment variable to append
73         :param value str: the value to append to key
74         :param sep str: the separator string
75         """
76         for c in [";", ":"]: # windows or linux path separators
77           if c in value:
78             raise Exception("Environ append key '%s' value '%s' contains forbidden character '%s'" % (key, value, c))
79         # check if the key is already in the environment
80         if key in self.environ:
81             value_list = self.environ[key].split(sep)
82             # Check if the value is already in the key value or not
83             if not value in value_list:
84                 value_list.append(value)
85             else:
86                 value_list.append(value_list.pop(value_list.index(value)))
87             self.set(key, sep.join(value_list))
88         else:
89             self.set(key, value)
90
91     def append(self, key, value, sep=os.pathsep):
92         """\
93         Same as append_value but the value argument can be a list
94         
95         :param key str: the environment variable to append
96         :param value str or list: the value(s) to append to key
97         :param sep str: the separator string
98         """
99         if isinstance(value, list):
100             for v in value:
101                 self.append_value(key, v, sep)
102         else:
103             self.append_value(key, value, sep)
104
105     def prepend_value(self, key, value, sep=os.pathsep):
106         """\
107         prepend value to key using sep,
108         if value contains ":" or ";" then raise error
109         
110         :param key str: the environment variable to prepend
111         :param value str: the value to prepend to key
112         :param sep str: the separator string
113         """
114         for c in [";", ":"]: # windows or linux path separators
115           if c in value:
116             raise Exception("Environ prepend key '%s' value '%s' contains forbidden character '%s'" % (key, value, c))
117         # check if the key is already in the environment
118         if key in self.environ:
119             value_list = self.environ[key].split(sep)
120             if not value in value_list:
121                 value_list.insert(0, value)
122             else:
123                 value_list.insert(0, value_list.pop(value_list.index(value)))
124             self.set(key, sep.join(value_list))
125         else:
126             self.set(key, value)
127
128     def prepend(self, key, value, sep=os.pathsep):
129         """\
130         Same as prepend_value but the value argument can be a list
131         
132         :param key str: the environment variable to prepend
133         :param value str or list: the value(s) to prepend to key
134         :param sep str: the separator string
135         """
136         if isinstance(value, list):
137             for v in reversed(value): # prepend list, first item at last to stay first
138                 self.prepend_value(key, v, sep)
139         else:
140             self.prepend_value(key, value, sep)
141
142     def is_defined(self, key):
143         """\
144         Check if the key exists in the environment
145         
146         :param key str: the environment variable to check
147         """
148         return key in self.environ.keys()
149
150     def set(self, key, value):
151         """\
152         Set the environment variable "key" to value "value"
153         
154         :param key str: the environment variable to set
155         :param value str: the value
156         """
157         self.environ[key] = self._expandvars(value)
158
159     def get(self, key):
160         """\
161         Get the value of the environment variable "key"
162         
163         :param key str: the environment variable
164         """
165         if key in self.environ:
166             return self.environ[key]
167         else:
168             return ""
169
170     def get_value(self, key):
171         """\
172         Get the value of the environment variable "key"
173         This method is added for API compatibility with FileEnviron class
174         
175         :param key str: the environment variable
176         """
177         return self.get(key)
178
179     def command_value(self, key, command):
180         """\
181         Get the value given by the system command "command" 
182         and put it in the environment variable key
183         
184         :param key str: the environment variable
185         :param command str: the command to execute
186         """
187         value = subprocess.Popen(command,
188                                  shell=True,
189                                  stdout=subprocess.PIPE,
190                                  env=self.environ).communicate()[0]
191         self.environ[key] = value
192
193
194 class SalomeEnviron:
195     """\
196     Class to manage the environment of SALOME.
197     """
198     def __init__(self,
199                  cfg,
200                  environ,
201                  forBuild=False,
202                  for_package=None,
203                  enable_simple_env_script = True):
204         """\
205         Initialization.
206
207         :param cfg Config: the global config
208         :param environ Environ: the Environ instance where 
209                                 to store the environment variables
210         :param forBuild bool: If true, it is a launch environment, 
211                               else a build one
212         :param for_package str: If not None, produce a relative environment 
213                                 designed for a package. 
214         """
215         self.environ = environ
216         self.cfg = cfg
217         self.forBuild = forBuild
218         self.for_package = for_package
219         self.enable_simple_env_script = enable_simple_env_script
220         self.silent = False
221         self.has_python = False
222
223     def __repr__(self):
224         """easy almost exhaustive quick resume for debug print"""
225         res = {
226           "environ" : self.environ,
227           "forBuild" : self.forBuild,
228           "for_package" : self.for_package,
229         }
230         return "%s(\n%s\n)" % (self.__class__.__name__, PP.pformat(res))
231
232     def append(self, key, value, sep=os.pathsep):
233         """\
234         append value to key using sep
235         
236         :param key str: the environment variable to append
237         :param value str: the value to append to key
238         :param sep str: the separator string
239         """
240         return self.environ.append(key, value, sep)
241
242     def prepend(self, key, value, sep=os.pathsep):
243         """\
244         prepend value to key using sep
245         
246         :param key str: the environment variable to prepend
247         :param value str: the value to prepend to key
248         :param sep str: the separator string
249         """
250         return self.environ.prepend(key, value, sep)
251
252     def is_defined(self, key):
253         """\
254         Check if the key exists in the environment
255         
256         :param key str: the environment variable to check
257         """
258         return self.environ.is_defined(key)
259
260     def get(self, key):
261         """\
262         Get the value of the environment variable "key"
263         
264         :param key str: the environment variable
265         """
266         return self.environ.get(key)
267
268     def get_value(self, key):
269         """\
270         Get the real value of the environment variable "key"
271         This method is added for API compatibility with FileEnviron class
272         
273         :param key str: the environment variable
274         """
275         if key in self.environ:
276             return self.environ[key]
277         else:
278             return ""
279
280     def set(self, key, value):
281         """\
282         Set the environment variable "key" to value "value"
283         
284         :param key str: the environment variable to set
285         :param value str: the value
286         """
287         # check if value needs to be evaluated
288         if value is not None and value.startswith("`") and value.endswith("`"):
289             res = subprocess.Popen("echo %s" % value,
290                                    shell=True,
291                                    stdout=subprocess.PIPE).communicate()
292             value = res[0].strip()
293
294         return self.environ.set(key, value)
295
296     def dump(self, out):
297         """\
298         Write the environment to out
299         
300         :param out file: the stream where to write the environment
301         """
302         for k in self.environ.environ.keys():
303             try:
304                 value = self.get(k)
305             except:
306                 value = "?"
307             out.write("%s=%s\n" % (k, value))
308
309     def add_line(self, nb_line):
310         """\
311         Add empty lines to the out stream (in case of file generation)
312         
313         :param nb_line int: the number of empty lines to add
314         """
315         if 'add_line' in dir(self.environ):
316             self.environ.add_line(nb_line)
317
318     def add_comment(self, comment):
319         """\
320         Add a commentary to the out stream (in case of file generation)
321         
322         :param comment str: the commentary to add
323         """
324         if 'add_comment' in dir(self.environ):
325             self.environ.add_comment(comment)
326
327     def add_warning(self, warning):
328         """\
329         Add a warning to the out stream (in case of file generation)
330         
331         :param warning str: the warning to add
332         """
333         if 'add_warning' in dir(self.environ):
334             self.environ.add_warning(warning)
335
336     def finish(self, required):
337         """\
338         Add a final instruction in the out file (in case of file generation)
339         
340         :param required bool: Do nothing if required is False
341         """
342         if 'finish' in dir(self.environ):
343             self.environ.add_line(1)
344             # what for ?
345             # self.environ.add_comment("clean all the path")
346             self.environ.finish(required)
347
348     def set_python_libdirs(self):
349         """Set some generic variables for python library paths"""
350         ver = self.get('PYTHON_VERSION')
351         self.set('PYTHON_LIBDIR0', os.path.join('lib',
352                                                 'python' + ver,
353                                                 'site-packages'))
354         self.set('PYTHON_LIBDIR1', os.path.join('lib64',
355                                                 'python' + ver,
356                                                 'site-packages'))
357           
358         self.python_lib0 = self.get('PYTHON_LIBDIR0')
359         self.python_lib1 = self.get('PYTHON_LIBDIR1')
360         self.has_python = True
361
362     def get_names(self, lProducts):
363         """\
364         Get the products name to add in SALOME_MODULES environment variable
365         It is the name of the product, except in the case where the is a 
366         component name. And it has to be in SALOME_MODULES variable only 
367         if the product has the property has_salome_hui = "yes"
368         
369         :param lProducts list: List of products to potentially add
370         """
371         lProdHasGui = [p for p in lProducts if 'properties' in 
372             src.product.get_product_config(self.cfg, p) and
373             'has_salome_gui' in 
374             src.product.get_product_config(self.cfg, p).properties and
375             src.product.get_product_config(self.cfg,
376                                            p).properties.has_salome_gui=='yes']
377         lProdName = []
378         for ProdName in lProdHasGui:
379             pi = src.product.get_product_config(self.cfg, ProdName)
380             if 'component_name' in pi:
381                 lProdName.append(pi.component_name)
382             else:
383                 lProdName.append(ProdName)
384         return lProdName
385
386     def set_application_env(self, logger):
387         """\
388         Sets the environment defined in the APPLICATION file.
389         
390         :param logger Logger: The logger instance to display messages
391         """
392         
393         if self.for_package:
394            self.set("PRODUCT_ROOT_DIR", "out_dir_Path")
395         else:
396            self.cfg.APPLICATION.environ.PRODUCT_ROOT_DIR = src.pyconf.Reference(self.cfg, src.pyconf.DOLLAR, "workdir")
397
398         # these sensitive variables are reset to avoid bad environment interactions
399         self.add_line(1)
400         self.add_comment("reset these sensitive variables to avoid bad environment interactions")
401         self.add_comment("comment these to lines if you wish a different behaviour")
402         self.set("LD_LIBRARY_PATH", "")
403         self.set("PYTHONPATH", "")
404         self.add_line(1)
405
406         # Set the variables defined in the "environ" section
407         if 'environ' in self.cfg.APPLICATION:
408             # we write PRODUCT environment it in order to conform to 
409             # parseConfigFile.py
410             self.add_comment("PRODUCT environment") 
411             self.load_cfg_environment(self.cfg.APPLICATION.environ)
412             if self.forBuild and "build" in self.cfg.APPLICATION.environ:
413                 self.load_cfg_environment(self.cfg.APPLICATION.environ.build)
414             if not self.forBuild and "launch" in self.cfg.APPLICATION.environ:
415                 self.load_cfg_environment(self.cfg.APPLICATION.environ.launch)
416             self.add_line(1)
417
418
419     def set_salome_minimal_product_env(self, product_info, logger):
420         """\
421         Sets the minimal environment for a SALOME product.
422         xxx_ROOT_DIR and xxx_SRC_DIR
423         
424         :param product_info Config: The product description
425         :param logger Logger: The logger instance to display messages        
426         """
427         # set root dir
428         DBG.write("set_salome_minimal_product_env", product_info)
429         root_dir = product_info.name + "_ROOT_DIR"
430         if not self.is_defined(root_dir):
431             if 'install_dir' in product_info and product_info.install_dir:
432                 self.set(root_dir, product_info.install_dir)
433             elif not self.silent:
434                 logger.write("  " + _("No install_dir for product %s\n") %
435                               product_info.name, 5)
436         
437         source_in_package = src.get_property_in_product_cfg(product_info,
438                                                            "sources_in_package")
439         if not self.for_package or source_in_package == "yes":
440             # set source dir, unless no source dir
441             if not src.product.product_is_fixed(product_info):
442                 src_dir = product_info.name + "_SRC_DIR"
443                 if not self.is_defined(src_dir):
444                     if not self.for_package:
445                         self.set(src_dir, product_info.source_dir)
446                     else:
447                         self.set(src_dir, os.path.join("out_dir_Path",
448                                                        "SOURCES",
449                                                        product_info.name))
450
451     def set_salome_generic_product_env(self, pi):
452         """\
453         Sets the generic environment for a SALOME product.
454         
455         :param pi Config: The product description
456         """
457         # Construct XXX_ROOT_DIR
458         env_root_dir = self.get(pi.name + "_ROOT_DIR")
459         l_binpath_libpath = []
460
461         # create additional ROOT_DIR for CPP components
462         if 'component_name' in pi:
463             compo_name = pi.component_name
464             if compo_name + "CPP" == pi.name:
465                 compo_root_dir = compo_name + "_ROOT_DIR"
466                 envcompo_root_dir = os.path.join(
467                             self.cfg.TOOLS.common.install_root, compo_name )
468                 self.set(compo_root_dir ,  envcompo_root_dir)
469                 bin_path = os.path.join(envcompo_root_dir, 'bin', 'salome')
470                 lib_path = os.path.join(envcompo_root_dir, 'lib', 'salome')
471                 l_binpath_libpath.append( (bin_path, lib_path) )
472
473
474         if src.get_property_in_product_cfg(pi, "fhs"):
475             lib_path = os.path.join(env_root_dir, 'lib')
476             bin_path = os.path.join(env_root_dir, 'bin')
477             if self.has_python:
478             # if the application doesn't include python, we don't need these two lines
479                 pylib1_path = os.path.join(env_root_dir, self.python_lib0)
480                 pylib2_path = os.path.join(env_root_dir, self.python_lib1)
481         else:
482             lib_path = os.path.join(env_root_dir, 'lib', 'salome')
483             bin_path = os.path.join(env_root_dir, 'bin', 'salome')
484             if self.has_python:
485             # if the application doesn't include python, we don't need these two lines
486                 pylib1_path = os.path.join(env_root_dir, self.python_lib0, 'salome')
487                 pylib2_path = os.path.join(env_root_dir, self.python_lib1, 'salome')
488
489         # Construct the paths to prepend to PATH and LD_LIBRARY_PATH and 
490         # PYTHONPATH
491         l_binpath_libpath.append( (bin_path, lib_path) )
492
493         for bin_path, lib_path in l_binpath_libpath:
494             if not self.forBuild:
495                 self.prepend('PATH', bin_path)
496                 if src.architecture.is_windows():
497                     self.prepend('PATH', lib_path)
498                 else :
499                     self.prepend('LD_LIBRARY_PATH', lib_path)
500
501             l = [ bin_path, lib_path ]
502             if self.has_python:
503                 l.append(pylib1_path)
504                 l.append(pylib2_path)
505
506             self.prepend('PYTHONPATH', l)
507
508     def set_cpp_env(self, product_info):
509         """\
510         Sets the generic environment for a SALOME cpp product.
511         
512         :param product_info Config: The product description
513         """
514         # Construct XXX_ROOT_DIR
515         env_root_dir = self.get(product_info.name + "_ROOT_DIR")
516         l_binpath_libpath = []
517
518         # Construct the paths to prepend to PATH and LD_LIBRARY_PATH and 
519         # PYTHONPATH
520         bin_path = os.path.join(env_root_dir, 'bin')
521         lib_path = os.path.join(env_root_dir, 'lib')
522         l_binpath_libpath.append( (bin_path, lib_path) )
523
524         for bin_path, lib_path in l_binpath_libpath:
525             if not self.forBuild:
526                 self.prepend('PATH', bin_path)
527                 if src.architecture.is_windows():
528                     self.prepend('PATH', lib_path)
529                 else :
530                     self.prepend('LD_LIBRARY_PATH', lib_path)
531
532             l = [ bin_path, lib_path ]
533             if self.has_python:
534                 l.append(os.path.join(env_root_dir, self.python_lib0))
535                 l.append(os.path.join(env_root_dir, self.python_lib1))
536             self.prepend('PYTHONPATH', l)
537
538     def load_cfg_environment(self, cfg_env):
539         """\
540         Loads environment defined in cfg_env 
541         
542         :param cfg_env Config: A config containing an environment    
543         """
544         # Loop on cfg_env values
545         for env_def in cfg_env:
546             val = cfg_env[env_def]
547             
548             # if it is env_script, do not do anything (reserved keyword)
549             if env_def == "env_script":
550                 continue
551             
552             # if it is a dict, do not do anything
553             if isinstance(val, src.pyconf.Mapping):
554                 continue
555
556             # if it is a list, loop on its values
557             if isinstance(val, src.pyconf.Sequence):
558                 # transform into list of strings
559                 l_val = []
560                 for item in val:
561                     l_val.append(item)
562                 val = l_val
563
564             # "_" means that the value must be prepended
565             if env_def.startswith("_"):
566                 # separator exception for PV_PLUGIN_PATH
567                 if env_def[1:] == 'PV_PLUGIN_PATH':
568                     self.prepend(env_def[1:], val, ';')
569                 else:
570                     self.prepend(env_def[1:], val)
571             elif env_def.endswith("_"):
572                 # separator exception for PV_PLUGIN_PATH
573                 if env_def[:-1] == 'PV_PLUGIN_PATH':
574                     self.append(env_def[:-1], val, ';')
575                 else:
576                     self.append(env_def[:-1], val)
577             else:
578                 self.set(env_def, val)
579
580     def set_a_product(self, product, logger):
581         """\
582         Sets the environment of a product. 
583         
584         :param product str: The product name
585         :param logger Logger: The logger instance to display messages
586         """
587
588         # Get the informations corresponding to the product
589         pi = src.product.get_product_config(self.cfg, product)
590         
591         # skip compile time products at run time 
592         if not self.forBuild:
593             if src.product.product_is_compile_time(pi):
594                 return
595
596         # skip mesa products (if any) at run time, 
597         # unless use_mesa property was activated
598         if not self.forBuild:
599             if not ("APPLICATION" in self.cfg  and
600                     "properties" in self.cfg.APPLICATION  and
601                     "use_mesa" in self.cfg.APPLICATION.properties  and
602                     self.cfg.APPLICATION.properties.use_mesa == "yes") :
603                 if ("properties" in pi and
604                     "is_mesa" in pi.properties  and
605                     pi.properties.is_mesa == "yes") :
606                     logger.write(_("Skip mesa product %s\n") % pi.name, 4)
607                     return
608                
609         
610         if self.for_package:
611             pi.install_dir = os.path.join("out_dir_Path",
612                                           self.for_package,
613                                           pi.name)
614
615         if not self.silent:
616             logger.write(_("Setting environment for %s\n") % product, 4)
617
618         self.add_line(1)
619         self.add_comment('setting environ for ' + product)
620             
621         # Do not define environment if the product is native
622         if src.product.product_is_native(pi):
623             if src.product.product_has_env_script(pi):
624                 self.run_env_script(pi, native=True)
625             return
626                
627         # Set an additional environment for SALOME products
628         if src.product.product_is_salome(pi):
629             # set environment using definition of the product
630             self.set_salome_minimal_product_env(pi, logger)
631             self.set_salome_generic_product_env(pi)
632         
633         # use variable LICENCE_FILE to communicate the licence file name to the environment script
634         licence_file_name = src.product.product_has_licence(pi, self.cfg.PATHS.LICENCEPATH)
635         if licence_file_name:
636             logger.write("licence file found for product %s : %s\n" % (pi.name, licence_file_name), 5) 
637             self.set("LICENCE_FILE", licence_file_name)
638
639         if src.product.product_is_cpp(pi):
640             # set a specific environment for cpp modules
641             self.set_salome_minimal_product_env(pi, logger)
642             self.set_cpp_env(pi)
643             
644             if src.product.product_is_generated(pi):
645                 if "component_name" in pi:
646                     # hack the source and install directories in order to point  
647                     # on the generated product source install directories
648                     install_dir_save = pi.install_dir
649                     source_dir_save = pi.source_dir
650                     name_save = pi.name
651                     pi.install_dir = os.path.join(self.cfg.APPLICATION.workdir,
652                                                   "INSTALL",
653                                                   pi.component_name)
654                     if self.for_package:
655                         pi.install_dir = os.path.join("out_dir_Path",
656                                                       self.for_package,
657                                                       pi.component_name)
658                     pi.source_dir = os.path.join(self.cfg.APPLICATION.workdir,
659                                                   "GENERATED",
660                                                   pi.component_name)
661                     pi.name = pi.component_name
662                     self.set_salome_minimal_product_env(pi, logger)
663                     self.set_salome_generic_product_env(pi)
664                     
665                     # Put original values
666                     pi.install_dir = install_dir_save
667                     pi.source_dir = source_dir_save
668                     pi.name = name_save
669         
670         # Put the environment define in the configuration of the product
671         if "environ" in pi:
672             self.load_cfg_environment(pi.environ)
673             if self.forBuild and "build" in pi.environ:
674                 self.load_cfg_environment(pi.environ.build)
675             if not self.forBuild and "launch" in pi.environ:
676                 self.load_cfg_environment(pi.environ.launch)
677             # if product_info defines a env_scripts, load it
678             if 'env_script' in pi.environ:
679                 self.run_env_script(pi, logger)
680
681         
682             
683
684     def run_env_script(self, product_info, logger=None, native=False):
685         """\
686         Runs an environment script. 
687         
688         :param product_info Config: The product description
689         :param logger Logger: The logger instance to display messages
690         :param native Boolean: if True load set_native_env instead of set_env
691         """
692         env_script = product_info.environ.env_script
693         # Check that the script exists
694         if not os.path.exists(env_script):
695             raise src.SatException(_("Environment script not found: %s") % 
696                                    env_script)
697
698         if not self.silent and logger is not None:
699             logger.write("  ** load %s\n" % env_script, 4)
700
701         # import the script and run the set_env function
702         try:
703             import imp
704             pyproduct = imp.load_source(product_info.name + "_env_script",
705                                         env_script)
706             if not native:
707                 if self.forBuild and "set_env_build" in dir(pyproduct):
708                     pyproduct.set_env_build(self,
709                                             product_info.install_dir,
710                                             product_info.version)
711                 elif (not self.forBuild) and "set_env_launch" in dir(pyproduct):
712                     pyproduct.set_env_launch(self,
713                                             product_info.install_dir,
714                                             product_info.version)
715                 else:
716                     # at least this one is mandatory,
717                     # if set_env_build and set_env_build are not defined
718                     pyproduct.set_env(self,
719                                       product_info.install_dir,
720                                       product_info.version)
721             else:
722                 # not mandatory, if set_nativ_env not defined, we do nothing
723                 if "set_nativ_env" in dir(pyproduct):
724                     pyproduct.set_nativ_env(self)
725         except:
726             __, exceptionValue, exceptionTraceback = sys.exc_info()
727             print(exceptionValue)
728             import traceback
729             traceback.print_tb(exceptionTraceback)
730             traceback.print_exc()
731
732     def run_simple_env_script(self, script_path, logger=None):
733         """\
734         Runs an environment script. Same as run_env_script, but with a 
735         script path as parameter.
736         
737         :param script_path str: a path to an environment script
738         :param logger Logger: The logger instance to display messages
739         """
740         if not self.enable_simple_env_script:
741             return
742         # Check that the script exists
743         if not os.path.exists(script_path):
744             raise src.SatException(_("Environment script not found: %s") % 
745                                    script_path)
746
747         if not self.silent and logger is not None:
748             logger.write("  ** load %s\n" % script_path, 4)
749
750         script_basename = os.path.basename(script_path)
751         if script_basename.endswith(".py"):
752             script_basename = script_basename[:-len(".py")]
753
754         # import the script and run the set_env function
755         try:
756             import imp
757             pyproduct = imp.load_source(script_basename + "_env_script",
758                                         script_path)
759             pyproduct.load_env(self)
760         except:
761             __, exceptionValue, exceptionTraceback = sys.exc_info()
762             print(exceptionValue)
763             import traceback
764             traceback.print_tb(exceptionTraceback)
765             traceback.print_exc()
766
767     def set_products(self, logger, src_root=None):
768         """\
769         Sets the environment for all the products. 
770         
771         :param logger Logger: The logger instance to display messages
772         :param src_root src: the application working directory
773         """
774         self.add_line(1)
775         self.add_comment('setting environ for all products')
776
777         # Make sure that the python lib dirs are set after python
778         if "Python" in self.cfg.APPLICATION.products:
779             self.set_a_product("Python", logger)
780             self.set_python_libdirs()
781
782         # The loop on the products
783         for product in self.cfg.APPLICATION.products.keys():
784             if product == "Python":
785                 continue
786             self.set_a_product(product, logger)
787             self.finish(False)
788  
789     def set_full_environ(self, logger, env_info):
790         """\
791         Sets the full environment for products 
792         specified in env_info dictionary. 
793         
794         :param logger Logger: The logger instance to display messages
795         :param env_info list: the list of products
796         """
797         DBG.write("set_full_environ for", env_info)
798         # DBG.write("set_full_environ config", self.cfg.APPLICATION.environ, True)
799
800         # set product environ
801         self.set_application_env(logger)
802
803         if "Python" in env_info:
804             self.set_a_product("Python", logger)
805             self.set_python_libdirs()
806
807         # set products
808         for product in env_info:
809             if product == "Python":
810                 continue
811             self.set_a_product(product, logger)
812
813 class FileEnvWriter:
814     """\
815     Class to dump the environment to a file.
816     """
817     def __init__(self, config, logger, out_dir, src_root, env_info=None):
818         """\
819         Initialization.
820
821         :param cfg Config: the global config
822         :param logger Logger: The logger instance to display messages
823         :param out_dir str: The directory path where t put the output files
824         :param src_root str: The application working directory
825         :param env_info str: The list of products to add in the files.
826         """
827         self.config = config
828         self.logger = logger
829         self.out_dir = out_dir
830         self.src_root= src_root
831         self.silent = True
832         self.env_info = env_info
833
834     def write_env_file(self, filename, forBuild, shell, for_package = None):
835         """\
836         Create an environment file.
837         
838         :param filename str: the file path
839         :param forBuild bool: if true, the build environment
840         :param shell str: the type of file wanted (.sh, .bat)
841         :return: The path to the generated file
842         :rtype: str
843         """
844         if not self.silent:
845             self.logger.write(_("Create environment file %s\n") % 
846                               src.printcolors.printcLabel(filename), 3)
847
848         # create then env object
849         env_file = open(os.path.join(self.out_dir, filename), "w")
850         tmp = src.fileEnviron.get_file_environ(env_file,
851                                                shell,
852                                                {})
853         env = SalomeEnviron(self.config, tmp, forBuild, for_package=for_package)
854         env.silent = self.silent
855
856         # Set the environment
857         if self.env_info is not None:
858             env.set_full_environ(self.logger, self.env_info)
859         else:
860             # set env from the APPLICATION
861             env.set_application_env(self.logger)
862             
863             # The list of products to launch
864             lProductsName = env.get_names(self.config.APPLICATION.products.keys())
865             env.set( "SALOME_MODULES",    ','.join(lProductsName))
866             
867             # set the products
868             env.set_products(self.logger,
869                             src_root=self.src_root)
870
871         # add cleanup and close
872         env.finish(True)
873         env_file.close()
874
875         return env_file.name
876    
877     def write_cfgForPy_file(self,
878                             filename,
879                             additional_env = {},
880                             for_package = None,
881                             with_commercial = True):
882         """\
883         Append to current opened aFile a cfgForPy 
884         environment (SALOME python launcher).
885            
886         :param filename str: the file path
887         :param additional_env dict: a dictionary of additional variables 
888                                     to add to the environment
889         :param for_package str: If not None, produce a relative environment 
890                                 designed for a package. 
891         """
892         if not self.silent:
893             self.logger.write(_("Create configuration file %s\n") % 
894                               src.printcolors.printcLabel(filename.name), 3)
895
896         # create then env object
897         tmp = src.fileEnviron.get_file_environ(filename, "cfgForPy", {})
898         # DBG.write("fileEnviron.get_file_environ %s" % filename, tmp, True)
899
900         # environment for launch
901         env = SalomeEnviron(self.config,
902                             tmp,
903                             forBuild=False,
904                             for_package=for_package,
905                             enable_simple_env_script = with_commercial)
906         env.silent = self.silent
907
908         DBG.write("write_cfgForPy_file", self.config.APPLICATION.environ)
909
910         if self.env_info is not None:
911             env.set_full_environ(self.logger, self.env_info)
912             DBG.write("set_full_environ", self.env_info)
913
914         else:
915             # set env from PRODUCT
916             env.set_application_env(self.logger)
917
918             # The list of products to launch
919             lProductsName = env.get_names(self.config.APPLICATION.products.keys())
920             env.set("SALOME_MODULES", ','.join(lProductsName))
921
922             # set the products
923             env.set_products(self.logger, src_root=self.src_root)
924
925         # Add the additional environment if it is not empty
926         if len(additional_env) != 0:
927             for variable in additional_env:
928                 env.set(variable, additional_env[variable])
929
930         # add cleanup and close
931         env.finish(True)
932
933 class Shell:
934     """\
935     Definition of a Shell.
936     """
937     def __init__(self, name, extension):
938         """\
939         Initialization.
940
941         :param name str: the shell name
942         :param extension str: the shell extension
943         """
944         self.name = name
945         self.extension = extension
946
947 def load_environment(config, build, logger):
948     """\
949     Loads the environment (used to run the tests, for example).
950     
951     :param config Config: the global config
952     :param build bool: build environement if True
953     :param logger Logger: The logger instance to display messages
954     """
955     environ = SalomeEnviron(config, Environ(os.environ), build)
956     environ.set_application_env(logger)
957     environ.set_products(logger)
958     environ.finish(True)