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