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