]> SALOME platform Git repositories - tools/eficas.git/blob - Aster/Cata/Utilitai/System.py
Salome HOME
Modif V6_4_°
[tools/eficas.git] / Aster / Cata / Utilitai / System.py
1 #@ MODIF System Utilitai  DATE 29/08/2006   AUTEUR MCOURTOI M.COURTOIS 
2 # -*- coding: iso-8859-1 -*-
3 #            CONFIGURATION MANAGEMENT OF EDF VERSION
4 # ======================================================================
5 # COPYRIGHT (C) 1991 - 2006  EDF R&D                  WWW.CODE-ASTER.ORG
6 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY  
7 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY  
8 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR     
9 # (AT YOUR OPTION) ANY LATER VERSION.                                                  
10 #                                                                       
11 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT   
12 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF            
13 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU      
14 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.                              
15 #                                                                       
16 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE     
17 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,         
18 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.        
19 # ======================================================================
20
21
22 """Ce module définit la classe `SYSTEM` et la fonction `ExecCommand`
23 qui est présente uniquement pour commodité pour les Macros.
24
25 La classe SYSTEM est semblable à celle utilisée dans ASTK_SERV.
26 """
27
28 __all__ = ["SYSTEM", "ExecCommand"]
29
30 import sys
31 import os
32 import popen2
33 import re
34 from sets import Set
35 from types import FileType
36
37 # ----- differ messages translation
38 def _(mesg):
39    return mesg
40
41 #-------------------------------------------------------------------------------
42 def _exitcode(status, default=0):
43    """Extrait le code retour du status. Retourne `default` si le process
44    n'a pas fini pas exit.
45    """
46    iret = default
47    if os.WIFEXITED(status):
48       iret = os.WEXITSTATUS(status)
49    return iret
50
51 #-------------------------------------------------------------------------------
52 #-------------------------------------------------------------------------------
53 #-------------------------------------------------------------------------------
54 class SYSTEM:
55    """Class to encapsultate "system" commands (this a simplified version of
56    ASTER_SYSTEM class defined in ASTK_SERV part).
57    """
58    # this value should be set during installation step.
59    MaxCmdLen = 1024
60    # line length -9
61    _LineLen = 80-9
62    
63 #-------------------------------------------------------------------------------
64    def __init__(self, **kargs):
65       """Initialization.
66       Optionnal arguments : silent, verbose, debug, cc_files, maxcmdlen.
67       """
68       self.verbose   = kargs.get('verbose', True)
69       self.debug     = kargs.get('debug', False)
70       self.cc_files  = kargs.get('cc_files', None)
71       if kargs.has_key('maxcmdlen'):
72          self.MaxCmdLen = kargs['maxcmdlen']
73
74 #-------------------------------------------------------------------------------
75    def _mess(self, msg, cod=''):
76       """Just print a message
77       """
78       self._print('%-18s %s' % (cod, msg))
79
80 #-------------------------------------------------------------------------------
81    def _print(self, *args, **kargs):
82       """print replacement.
83       Optionnal argument :
84          term  : line terminator (default to os.linesep).
85       """
86       term = kargs.get('term', os.linesep)
87       files = Set([sys.stdout])
88       if self.cc_files:
89          files.add(self.cc_files)
90       for f in files:
91          if type(f) is FileType:
92             txt = ' '.join(['%s'%a for a in args])
93             f.write(txt.replace(os.linesep+' ', os.linesep)+term)
94             f.flush()
95          else:
96             print _('FileType object expected : %s / %s') % (type(f), repr(f))
97
98 #-------------------------------------------------------------------------------
99    def VerbStart(self, cmd, verbose=None):
100       """Start message in verbose mode
101       """
102       Lm = self._LineLen
103       if verbose == None:
104          verbose = self.verbose
105       if verbose:
106          pcmd = cmd
107          if len(cmd) > Lm-2 or cmd.count('\n') > 0:
108             pcmd = pcmd+'\n'+' '*Lm
109          self._print(('%-'+str(Lm)+'s') % (pcmd,), term='')
110
111 #-------------------------------------------------------------------------------
112    def VerbEnd(self, iret, output='', verbose=None):
113       """Ends message in verbose mode
114       """
115       if verbose == None:
116          verbose = self.verbose
117       if verbose:
118          if iret == 0:
119             self._print('[  OK  ]')
120          else:
121             self._print(_('[FAILED]'))
122             self._print(_('Exit code : %d') % iret)
123          if (iret != 0 or self.debug) and output:
124             self._print(output)
125
126 #-------------------------------------------------------------------------------
127    def VerbIgnore(self, verbose=None):
128       """Ends message in verbose mode
129       """
130       if verbose == None:
131          verbose = self.verbose
132       if verbose:
133          self._print(_('[ SKIP ]'))
134
135 #-------------------------------------------------------------------------------
136    def Shell(self, cmd, bg=False, verbose=None, follow_output=False,
137                    alt_comment=None, interact=False):
138       """Execute a command shell
139          cmd      : command
140          bg       : put command in background if True
141          verbose  : print status messages during execution if True
142          follow_output : follow interactively output of command
143          alt_comment : print this "alternative comment" instead of "cmd"
144          interact : allow the user to interact with the process
145             (don't close stdin). bg=True implies interact=False.
146       Return :
147          iret     : exit code if bg = False,
148                     process id if bg = True
149          output   : output lines (as string)
150       """
151       if not alt_comment:
152          alt_comment = cmd
153       if verbose == None:
154          verbose = self.verbose
155       if bg:
156          interact = False
157       if len(cmd) > self.MaxCmdLen:
158          self._mess((_('length of command shell greater '\
159                'than %d characters.') % self.MaxCmdLen), _('<A>_ALARM'))
160       if self.debug:
161          self._print('<DBG> <local_shell>', cmd)
162          self._print('<DBG> <local_shell> background mode : ', bg)
163       # exec
164       self.VerbStart(alt_comment, verbose=verbose)
165       if follow_output and verbose:
166          self._print(_('\nCommand output :'))
167       # run interactive command
168       if interact:
169          iret = os.system(cmd)
170          return _exitcode(iret), ''
171       # use popen to manipulate stdout/stderr
172       output = []
173       p = popen2.Popen4(cmd)
174       p.tochild.close()
175       if not bg:
176          if not follow_output:
177             output = p.fromchild.readlines()
178          else:
179             while p.poll() == -1:
180                output.append(p.fromchild.readline())
181                # \n already here...
182                self._print(output[-1], term='')
183             # to be sure to empty the buffer
184             end = p.fromchild.readlines()
185             self._print(''.join(end))
186             output.extend(end)
187          iret = _exitcode(p.wait())
188       else:
189          iret = 0
190       p.fromchild.close()
191       output = ''.join(output)
192
193       # repeat header message
194       if follow_output:
195          self.VerbStart(alt_comment, verbose=verbose)
196       mat = re.search('EXIT_CODE=([0-9]+)', output)
197       if mat:
198          iret = int(mat.group(1))
199       self.VerbEnd(iret, output, verbose=verbose)
200       if bg:
201          iret = p.pid
202          if verbose:
203             self._print(_('Process ID : '), iret)
204       return iret, output
205
206 #-------------------------------------------------------------------------------
207 # Juste par commodité.
208 system = SYSTEM()
209 ExecCommand = system.Shell
210
211
212 #-------------------------------------------------------------------------------
213 #-------------------------------------------------------------------------------
214 #-------------------------------------------------------------------------------
215 if __name__ == '__main__':
216    iret, output = ExecCommand('ls', alt_comment='Lancement de la commande...')
217