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