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