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