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