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