Salome HOME
Simplification du launcher:
[tools/sat.git] / src / fileEnviron.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
21 bat_header="""@echo off
22
23 rem The following variables are used only in case of a sat package
24 set out_dir_Path=%~dp0
25 set PRODUCT_OUT_DIR=%out_dir_Path%
26 set prereq_install_Path=%out_dir_Path%\PREREQUISITES\INSTALL
27 set prereq_build_Path=%out_dir_Path%\PREREQUISITES\BUILD
28 """
29
30
31 bash_header="""#!/bin/bash
32 ##########################################################################
33 #
34 #### cleandup ###
35 # cleanup a path (first parameter) from duplicated entries;
36 # second parameter is the separator
37 cleandup() {
38 out_var=`echo $1 | awk -v sep=$2 '{                      \\
39      na = split($1,a,sep);                               \\
40      k=0;                                                \\
41      for(i=0;i<=na;i++) {                                \\
42        found=0;                                          \\
43        for(j=0;j<k;j++) {                                \\
44          if(a[i]==aa[j])                                 \\
45          {                                               \\
46            found=1;                                      \\
47            break;                                        \\
48          };                                              \\
49        };                                                \\
50        if(found==0) {                                    \\
51          aa[k++]=a[i];                                   \\
52        };                                                \\
53      };                                                  \\
54      ORS=sep;                                            \\
55      for(i=0;i<k;i++) {                                  \\
56        print aa[i];                                      \\
57      }                                                   \\
58    }' | sed -e 's|\\(.*\\)$1|\\1|g' -e 's|^[:;]||' -e 's|[:;]$||'`
59 echo $out_var
60 }
61 ### clean ###
62 clean ()
63 {
64 xenv=`printenv $1`
65 out_var=`cleandup $xenv $2`
66 export $1=$out_var
67 }
68
69 # The 3 following variables are used only in case of a sat package
70 export out_dir_Path=$(cd $(dirname ${BASH_SOURCE[0]});pwd)
71 export PRODUCT_OUT_DIR=${out_dir_Path}
72 export PRODUCT_ROOT_DIR=${PRODUCT_OUT_DIR}
73
74 ###########################################################################
75 """
76
77 cfg_header='''[SALOME Configuration]
78 '''
79
80 Launcher_header='''# a generated SALOME Configuration file using python syntax
81 '''
82
83 def get_file_environ(output, shell, environ=None):
84     """Instantiate correct FileEnvironment sub-class.
85     
86     :param output file: the output file stream.
87     :param shell str: the type of shell syntax to use.
88     :param environ dict: a potential additional environment.
89     """
90     if shell == "bash":
91         return BashFileEnviron(output, environ)
92     if shell == "bat":
93         return BatFileEnviron(output, environ)
94     if shell == "cfgForPy":
95         return LauncherFileEnviron(output, environ)
96     if shell == "cfg":
97         return ContextFileEnviron(output, environ)
98     raise Exception("FileEnviron: Unknown shell = %s" % shell)
99
100 class FileEnviron:
101     """Base class for shell environment
102     """
103     def __init__(self, output, environ=None):
104         """Initialization
105         
106         :param output file: the output file stream.
107         :param environ dict: a potential additional environment.
108         """
109         self._do_init(output, environ)
110
111     def _do_init(self, output, environ=None):
112         """Initialization
113         
114         :param output file: the output file stream.
115         :param environ dict: a potential additional environment.
116         """
117         self.output = output
118         self.toclean = []
119         if environ is not None:
120             self.environ = environ
121         else:
122             self.environ = os.environ
123
124     def add_line(self, number):
125         """Add some empty lines in the shell file
126         
127         :param number int: the number of lines to add
128         """
129         self.output.write("\n" * number)
130
131     def add_comment(self, comment):
132         """Add a comment in the shell file
133         
134         :param comment str: the comment to add
135         """
136         self.output.write("# %s\n" % comment)
137
138     def add_echo(self, text):
139         """Add a "echo" in the shell file
140         
141         :param text str: the text to echo
142         """
143         self.output.write('echo %s"\n' % text)
144
145     def add_warning(self, warning):
146         """Add a warning "echo" in the shell file
147         
148         :param warning str: the text to echo
149         """
150         self.output.write('echo "WARNING %s"\n' % warning)
151
152     def append_value(self, key, value, sep=os.pathsep):
153         '''append value to key using sep
154         
155         :param key str: the environment variable to append
156         :param value str: the value to append to key
157         :param sep str: the separator string
158         '''
159         self.set(key, self.get(key) + sep + value)
160         if (key, sep) not in self.toclean:
161             self.toclean.append((key, sep))
162
163     def append(self, key, value, sep=os.pathsep):
164         '''Same as append_value but the value argument can be a list
165         
166         :param key str: the environment variable to append
167         :param value str or list: the value(s) to append to key
168         :param sep str: the separator string
169         '''
170         if isinstance(value, list):
171             self.append_value(key, sep.join(value), sep)
172         else:
173             self.append_value(key, value, sep)
174
175     def prepend_value(self, key, value, sep=os.pathsep):
176         '''prepend value to key using sep
177         
178         :param key str: the environment variable to prepend
179         :param value str: the value to prepend to key
180         :param sep str: the separator string
181         '''
182         self.set(key, value + sep + self.get(key))
183         if (key, sep) not in self.toclean:
184             self.toclean.append((key, sep))
185
186     def prepend(self, key, value, sep=os.pathsep):
187         '''Same as prepend_value but the value argument can be a list
188         
189         :param key str: the environment variable to prepend
190         :param value str or list: the value(s) to prepend to key
191         :param sep str: the separator string
192         '''
193         if isinstance(value, list):
194             self.prepend_value(key, sep.join(value), sep)
195         else:
196             self.prepend_value(key, value, sep)
197
198     def is_defined(self, key):
199         '''Check if the key exists in the environment
200         
201         :param key str: the environment variable to check
202         '''
203         return (key in self.environ)
204
205     def set(self, key, value):
206         '''Set the environment variable "key" to value "value"
207         
208         :param key str: the environment variable to set
209         :param value str: the value
210         '''
211         raise NotImplementedError("set is not implement for this shell!")
212
213     def get(self, key):
214         '''Get the value of the environment variable "key"
215         
216         :param key str: the environment variable
217         '''
218         return '${%s}' % key
219
220     def command_value(self, key, command):
221         '''Get the value given by the system command "command" 
222            and put it in the environment variable key.
223            Has to be overwritten in the derived classes
224            This can be seen as a virtual method
225         
226         :param key str: the environment variable
227         :param command str: the command to execute
228         '''
229         raise NotImplementedError("command_value is not implement "
230                                   "for this shell!")
231
232     def finish(self, required=True):
233         """Add a final instruction in the out file (in case of file generation)
234         
235         :param required bool: Do nothing if required is False
236         """
237         for (key, sep) in self.toclean:
238             if sep != ' ':
239                 self.output.write('clean %s "%s"\n' % (key, sep))
240
241 class BashFileEnviron(FileEnviron):
242     """Class for bash shell.
243     """
244     def __init__(self, output, environ=None):
245         """Initialization
246         
247         :param output file: the output file stream.
248         :param environ dict: a potential additional environment.
249         """
250         self._do_init(output, environ)
251         self.output.write(bash_header)
252
253     def set(self, key, value):
254         '''Set the environment variable "key" to value "value"
255         
256         :param key str: the environment variable to set
257         :param value str: the value
258         '''
259         self.output.write('export %s="%s"\n' % (key, value))
260         self.environ[key] = value
261
262     def command_value(self, key, command):
263         '''Get the value given by the system command "command" 
264            and put it in the environment variable key.
265            Has to be overwritten in the derived classes
266            This can be seen as a virtual method
267         
268         :param key str: the environment variable
269         :param command str: the command to execute
270         '''
271         self.output.write('export %s=$(%s)\n' % (key, command))
272
273     def finish(self, required=True):
274         """Add a final instruction in the out file (in case of file generation)
275         
276         :param required bool: Do nothing if required is False
277         """
278         if not required:
279             return
280         FileEnviron.finish(self, required)
281         
282 class BatFileEnviron(FileEnviron):
283     """for Windows batch shell.
284     """
285     def __init__(self, output, environ=None):
286         """Initialization
287         
288         :param output file: the output file stream.
289         :param environ dict: a potential additional environment.
290         """
291         self._do_init(output, environ)
292         self.output.write(bat_header)
293
294     def add_comment(self, comment):
295         """Add a comment in the shell file
296         
297         :param comment str: the comment to add
298         """
299         self.output.write("rem %s\n" % comment)
300     
301     def get(self, key):
302         '''Get the value of the environment variable "key"
303         
304         :param key str: the environment variable
305         '''
306         return '%%%s%%' % key
307     
308     def set(self, key, value):
309         '''Set the environment variable "key" to value "value"
310         
311         :param key str: the environment variable to set
312         :param value str: the value
313         '''
314         self.output.write('set %s=%s\n' % (key, value))
315         self.environ[key] = value
316
317     def command_value(self, key, command):
318         '''Get the value given by the system command "command" 
319            and put it in the environment variable key.
320            Has to be overwritten in the derived classes
321            This can be seen as a virtual method
322         
323         :param key str: the environment variable
324         :param command str: the command to execute
325         '''
326         self.output.write('%s > tmp.txt\n' % (command))
327         self.output.write('set /p %s =< tmp.txt\n' % (key))
328
329     def finish(self, required=True):
330         """Add a final instruction in the out file (in case of file generation)
331            In the particular windows case, do nothing
332         
333         :param required bool: Do nothing if required is False
334         """
335         return
336
337 class ContextFileEnviron(FileEnviron):
338     """Class for a salome context configuration file.
339     """
340     def __init__(self, output, environ=None):
341         """Initialization
342         
343         :param output file: the output file stream.
344         :param environ dict: a potential additional environment.
345         """
346         self._do_init(output, environ)
347         self.output.write(cfg_header)
348
349     def set(self, key, value):
350         '''Set the environment variable "key" to value "value"
351         
352         :param key str: the environment variable to set
353         :param value str: the value
354         '''
355         self.output.write('%s="%s"\n' % (key, value))
356         self.environ[key] = value
357
358     def get(self, key):
359         '''Get the value of the environment variable "key"
360         
361         :param key str: the environment variable
362         '''
363         return '%({0})s'.format(key)
364
365     def command_value(self, key, command):
366         '''Get the value given by the system command "command" 
367            and put it in the environment variable key.
368            Has to be overwritten in the derived classes
369            This can be seen as a virtual method
370         
371         :param key str: the environment variable
372         :param command str: the command to execute
373         '''
374         raise NotImplementedError("command_value is not implement "
375                                   "for salome context files!")
376
377     def add_echo(self, text):
378         """Add a comment
379         
380         :param text str: the comment to add
381         """
382         self.add_comment(text)
383
384     def add_warning(self, warning):
385         """Add a warning
386         
387         :param text str: the warning to add
388         """
389         self.add_comment("WARNING %s"  % warning)
390
391     def prepend_value(self, key, value, sep=os.pathsep):
392         '''prepend value to key using sep
393         
394         :param key str: the environment variable to prepend
395         :param value str: the value to prepend to key
396         :param sep str: the separator string
397         '''
398         self.output.write('ADD_TO_%s: %s\n' % (key, value))
399
400     def append_value(self, key, value, sep=os.pathsep):
401         '''append value to key using sep
402         
403         :param key str: the environment variable to append
404         :param value str: the value to append to key
405         :param sep str: the separator string
406         '''
407         self.prepend_value(key, value)
408
409     def finish(self, required=True):
410         """Add a final instruction in the out file (in case of file generation)
411         
412         :param required bool: Do nothing if required is False
413         """
414         return
415
416 def special_path_separator(name):
417     """TCLLIBPATH, TKLIBPATH, PV_PLUGIN_PATH environments variables need
418        some exotic path separator.
419        This function gives the separator regarding the name of the variable
420        to append or prepend.
421        
422     :param name str: The name of the variable to find the separator
423     """
424     special_blanks_keys=["TCLLIBPATH", "TKLIBPATH"]
425     special_semicolon_keys=["PV_PLUGIN_PATH"]
426     res=os.pathsep
427     if name in special_blanks_keys: res=" "
428     if name in special_semicolon_keys: res=";"
429     return res
430
431 class LauncherFileEnviron:
432     """Class to generate a launcher file script 
433        (in python syntax) SalomeContext API
434     """
435     def __init__(self, output, environ=None):
436         """Initialization
437         
438         :param output file: the output file stream.
439         :param environ dict: a potential additional environment.
440         """
441         self.output = output
442         self.toclean = []
443         if environ is not None:
444             self.environ = environ
445         else:
446             self.environ = os.environ
447         # Initialize some variables
448         if not "PATH" in self.environ.keys():
449             self.environ["PATH"]=""
450         if not "LD_LIBRARY_PATH" in self.environ.keys():
451             self.environ["LD_LIBRARY_PATH"]=""
452         if not "PYTHONPATH" in self.environ.keys():
453             self.environ["PYTHONPATH"]=""
454         if not "TCLLIBPATH" in self.environ.keys():
455             self.environ["TCLLIBPATH"]=""
456         if not "TKLIBPATH" in self.environ.keys():
457             self.environ["TKLIBPATH"]=""
458
459         # four whitespaces for first indentation in a python script
460         self.indent="    "
461         self.prefix="context."
462         self.setVarEnv="setVariable"
463         
464         self.begin=self.indent+self.prefix
465         self.output.write(Launcher_header)
466         self.specialKeys={"PATH": "Path",
467                           "LD_LIBRARY_PATH": "LdLibraryPath",
468                           "PYTHONPATH": "PythonPath"}
469
470     def change_to_launcher(self, value):
471         """
472         """
473         res=value
474         return res
475
476     def add_line(self, number):
477         """Add some empty lines in the launcher file
478         
479         :param number int: the number of lines to add
480         """
481         self.output.write("\n" * number)
482
483     def add_echo(self, text):
484         """Add a comment
485         
486         :param text str: the comment to add
487         """
488         self.output.write('# %s"\n' % text)
489
490     def add_warning(self, warning):
491         """Add a warning
492         
493         :param text str: the warning to add
494         """
495         self.output.write('# "WARNING %s"\n' % warning)
496
497     def append_value(self, key, value, sep=":"):
498         '''append value to key using sep
499         
500         :param key str: the environment variable to append
501         :param value str: the value to append to key
502         :param sep str: the separator string
503         '''
504         if self.is_defined(key) :
505             self.add(key, value)
506         else :
507             self.set(key, value)
508
509     def append(self, key, value, sep=":"):
510         '''Same as append_value but the value argument can be a list
511         
512         :param key str: the environment variable to append
513         :param value str or list: the value(s) to append to key
514         :param sep str: the separator string
515         '''
516         if isinstance(value, list):
517             self.append_value(key, sep.join(value), sep)
518         else:
519             self.append_value(key, value, sep)
520
521     def prepend_value(self, key, value, sep=":"):
522         '''prepend value to key using sep
523         
524         :param key str: the environment variable to prepend
525         :param value str: the value to prepend to key
526         :param sep str: the separator string
527         '''
528         if self.is_defined(key) :
529             self.add(key, value)
530         else :
531             self.set(key, value)
532
533     def prepend(self, key, value, sep=":"):
534         '''Same as prepend_value but the value argument can be a list
535         
536         :param key str: the environment variable to prepend
537         :param value str or list: the value(s) to prepend to key
538         :param sep str: the separator string
539         '''
540         if isinstance(value, list):
541             self.prepend_value(key, sep.join(value), sep)
542         else:
543             self.prepend_value(key, value, sep)
544
545     def is_defined(self, key):
546         '''Check if the key exists in the environment
547         
548         :param key str: the environment variable to check
549         '''
550         return key in self.environ.keys()
551
552     def get(self, key):
553         '''Get the value of the environment variable "key"
554         
555         :param key str: the environment variable
556         '''
557         return '${%s}' % key
558
559     def set(self, key, value):
560         '''Set the environment variable "key" to value "value"
561         
562         :param key str: the environment variable to set
563         :param value str: the value
564         '''
565         self.output.write(self.begin+self.setVarEnv+
566                           '(r"%s", r"%s", overwrite=True)\n' % 
567                           (key, self.change_to_launcher(value)))
568         self.environ[key] = value
569     
570     def add(self, key, value):
571         '''prepend value to key using sep
572         
573         :param key str: the environment variable to prepend
574         :param value str: the value to prepend to key
575         '''     
576         if key in self.specialKeys.keys():
577             self.output.write(self.begin+'addTo%s(r"%s")\n' % 
578                               (self.specialKeys[key],
579                                self.change_to_launcher(value)))
580             self.environ[key]+=":"+value
581             return
582         sep=special_path_separator(key)
583         self.output.write(self.indent+
584                           '#temporary solution!!! have to be defined in API a '
585                           '?dangerous? addToSpecial(r"%s", r"%s")\n' % 
586                           (key, value))
587         #pathsep not precised because do not know future os launch?
588         self.output.write(self.begin+'addToSpecial(r"%s", r"%s")\n' 
589                           % (key, self.change_to_launcher(value)))
590         self.environ[key]+=sep+value #here yes we know os for current execution
591
592     def command_value(self, key, command):
593         '''Get the value given by the system command "command" 
594            and put it in the environment variable key.
595         
596         :param key str: the environment variable
597         :param command str: the command to execute
598         '''
599         self.output.write(self.indent+'#`%s`\n' % command)
600
601         import shlex, subprocess
602         args = shlex.split(command)
603         res=subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
604         out, __ = res.communicate()
605         self.output.write(self.begin+
606                           self.setVarEnv+
607                           '(r"%s", r"%s", overwrite=True)\n' % (key, out))
608
609     def add_comment(self, comment):
610         # Special comment in case of the distène licence
611         if comment=="DISTENE license":
612             self.output.write(self.indent+
613                               "#"+
614                               self.prefix+
615                               self.setVarEnv+
616                               '(r"%s", r"%s", overwrite=True)\n' % 
617                               ('DISTENE_LICENSE_FILE', 
618                                self.change_to_launcher(
619                                             'Use global envvar: DLIM8VAR')))
620             self.output.write(self.indent+
621                               "#"+
622                               self.prefix+
623                               self.setVarEnv+
624                               '(r"%s", r"%s", overwrite=True)\n' % 
625                               ('DLIM8VAR', 
626                                self.change_to_launcher(
627                                                 '<your licence>')))
628             return
629         if "setting environ for" in comment:
630             self.output.write(self.indent+"#[%s]\n" % 
631                               comment.split("setting environ for ")[1])
632             return
633
634         self.output.write(self.indent+"# %s\n" % comment)
635
636     def finish(self, required=True):
637         """Add a final instruction in the out file (in case of file generation)
638            In the particular launcher case, do nothing
639         
640         :param required bool: Do nothing if required is False
641         """
642         return
643
644 class ScreenEnviron(FileEnviron):
645     def __init__(self, output, environ=None):
646         self._do_init(output, environ)
647         self.defined = {}
648
649     def add_line(self, number):
650         pass
651
652     def add_comment(self, comment):
653         pass
654
655     def add_echo(self, text):
656         pass
657
658     def add_warning(self, warning):
659         pass
660
661     def write(self, command, name, value, sign="="):
662         import src
663         self.output.write("  %s%s %s %s %s\n" % \
664             (src.printcolors.printcLabel(command),
665              " " * (12 - len(command)),
666              src.printcolors.printcInfo(name), sign, value))
667
668     def is_defined(self, name):
669         return self.defined.has_key(name)
670
671     def get(self, name):
672         return "${%s}" % name
673
674     def set(self, name, value):
675         self.write("set", name, value)
676         self.defined[name] = value
677
678     def prepend(self, name, value, sep=":"):
679         if isinstance(value, list):
680             value = sep.join(value)
681         value = value + sep + self.get(name)
682         self.write("prepend", name, value)
683
684     def append(self, name, value, sep=":"):
685         if isinstance(value, list):
686             value = sep.join(value)
687         value = self.get(name) + sep + value
688         self.write("append", name, value)
689
690     def command_value(self, key, command):
691         pass
692
693     def run_env_script(self, module, script):
694         self.write("load", script, "", sign="")
695
696 # The SALOME launcher template 
697 withProfile =  """#! /usr/bin/env python
698
699 ################################################################
700 # WARNING: this file is automatically generated by SalomeTools #
701 # WARNING: and so could be overwritten at any time.            #
702 ################################################################
703
704 import os
705 import sys
706
707
708 # Add the pwdPath to able to run the launcher after unpacking a package
709 # Used only in case of a salomeTools package
710 out_dir_Path=os.path.abspath(os.path.dirname(__file__))
711
712 # Preliminary work to initialize path to SALOME Python modules
713 def __initialize():
714
715   sys.path[:0] = [ 'BIN_KERNEL_INSTALL_DIR' ]
716   os.environ['ABSOLUTE_APPLI_PATH'] = 'KERNEL_INSTALL_DIR'
717   
718   # define folder to store omniorb config (initially in virtual application folder)
719   try:
720     from salomeContextUtils import setOmniOrbUserPath
721     setOmniOrbUserPath()
722   except Exception, e:
723     print e
724     sys.exit(1)
725 # End of preliminary work
726
727 def main(args):
728   # Identify application path then locate configuration files
729   __initialize()
730
731   if args == ['--help']:
732     from salomeContext import usage
733     usage()
734     sys.exit(0)
735
736   #from salomeContextUtils import getConfigFileNames
737   #configFileNames, args, unexisting = getConfigFileNames( args, checkExistence=True )
738   #if len(unexisting) > 0:
739   #  print "ERROR: unexisting configuration file(s): " + ', '.join(unexisting)
740   #  sys.exit(1)
741
742   # Create a SalomeContext which parses configFileNames to initialize environment
743   try:
744     from salomeContext import SalomeContext, SalomeContextException
745     SalomeContext.addToSpecial=addToSpecial
746     context = SalomeContext(None)
747     
748     # Here set specific variables, if needed
749     # context.addToPath('mypath')
750     # context.addToLdLibraryPath('myldlibrarypath')
751     # context.addToPythonPath('mypythonpath')
752     # context.setVariable('myvarname', 'value')
753
754     # Logger level error
755     context.getLogger().setLevel(40)
756
757     context.setVariable(r"PRODUCT_ROOT_DIR", out_dir_Path, overwrite=True)
758     # here your local standalone environment
759
760     # Start SALOME, parsing command line arguments
761     context.runSalome(args)
762     #print 'Thank you for using SALOME!'
763
764     # Logger level info
765     context.getLogger().setLevel(20)
766
767   except SalomeContextException, e:
768     import logging
769     logging.getLogger("salome").error(e)
770     sys.exit(1)
771 #
772 def addToSpecial(self, name, value, pathSep=None):
773   "add special dangerous cases: TCLLIBPATH PV_PLUGIN_PATH etc..."
774   #http://computer-programming-forum.com/57-tcl/1dfddc136afccb94.htm
775   #TCLLIBPATH: Tcl treats the contents of that variable as a list. Be happy, for you can now use drive letters on windows.
776   if value == '':
777     return
778   
779   specialBlanksKeys=["TCLLIBPATH", "TKLIBPATH"]
780   specialSemicolonKeys=["PV_PLUGIN_PATH"]
781   res=os.pathsep
782   if name in specialBlanksKeys: res=" "
783   if name in specialSemicolonKeys: res=";"
784   
785   if pathSep==None:
786     sep=res
787   else:
788     sep=pathSep
789   value = os.path.expandvars(value) # expand environment variables
790   self.getLogger().debug("Add to %s: %s", name, value)
791   env = os.getenv(name, None)
792   if env is None:
793     os.environ[name] = value
794   else:
795     os.environ[name] = value + sep + env #explicitely or not special path separator ?whitespace, semicolon?
796
797 if __name__ == "__main__":
798   args = sys.argv[1:]
799   main(args)
800 #
801 """
802