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