Salome HOME
AY a ajouté l'interception de l'exception levée lorsque la chaine passée
[tools/eficas.git] / Noyau / N_ETAPE.py
1 #@ MODIF N_ETAPE Noyau  DATE 03/09/2002   AUTEUR GNICOLAS G.NICOLAS 
2 #            CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR   
8 # (AT YOUR OPTION) ANY LATER VERSION.                                 
9 #
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT 
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF          
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU    
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.                            
14 #
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE   
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,       
17 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.      
18 #                                                                       
19 #                                                                       
20 # ======================================================================
21 """ 
22     Ce module contient la classe ETAPE qui sert à vérifier et à exécuter
23     une commande
24 """
25
26 # Modules Python
27 import types,sys,string,os
28 import linecache
29 import traceback
30 from copy import copy
31
32 # Modules EFICAS
33 import N_MCCOMPO
34 from N_Exception import AsException
35 import N_utils
36 from N_utils import AsType
37
38 class ETAPE(N_MCCOMPO.MCCOMPO):
39    """
40       Cette classe hérite de MCCOMPO car ETAPE est un OBJECT composite
41
42    """
43    nature = "OPERATEUR"
44
45    # L'attribut de classe codex est utilisé pour rattacher le module de calcul éventuel (voir Build)
46    # On le met à None pour indiquer qu'il n'y a pas de module de calcul rattaché
47    codex=None
48
49    def __init__(self,oper=None,reuse=None,args={}):
50       """
51          Attributs :
52
53           - definition : objet portant les attributs de définition d'une étape de type opérateur. Il
54                          est initialisé par l'argument oper.
55
56           - reuse : indique le concept d'entrée réutilisé. Il se trouvera donc en sortie
57                     si les conditions d'exécution de l'opérateur l'autorise
58
59           - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé avec l'argument args.
60
61       """
62       self.definition=oper
63       self.reuse=reuse
64       self.valeur=args
65       self.nettoiargs()
66       self.parent=CONTEXT.get_current_step()
67       self.etape = self
68       self.nom=oper.nom
69       self.idracine=oper.label
70       self.appel=N_utils.callee_where()
71       self.mc_globaux={}
72       self.sd=None
73       self.actif=1
74       self.make_register()
75
76    def make_register(self):
77       """
78          Initialise les attributs jdc, id, niveau et réalise les 
79          enregistrements nécessaires
80       """
81       if self.parent :
82          self.jdc = self.parent.get_jdc_root()
83          self.id=self.parent.register(self)
84          self.niveau=None
85       else:
86          self.jdc = self.parent =None
87          self.id=None
88          self.niveau=None
89
90    def nettoiargs(self):
91       """
92          Cette methode a pour fonction de retirer tous les arguments egaux à None
93          de la liste des arguments. Ils sont supposés non présents et donc retirés.
94       """
95       for k in self.valeur.keys():
96          if self.valeur[k] == None:del self.valeur[k]
97
98    def McBuild(self):
99       """
100          Demande la construction des sous-objets et les stocke dans l'attribut
101          mc_liste.
102       """
103       self.mc_liste=self.build_mc()
104
105    def Build_sd(self,nom):
106       """
107          Construit le concept produit de l'opérateur. Deux cas 
108          peuvent se présenter :
109         
110          - le parent n'est pas défini. Dans ce cas, l'étape prend en charge la création 
111            et le nommage du concept.
112
113          - le parent est défini. Dans ce cas, l'étape demande au parent la création et 
114            le nommage du concept.
115
116       """
117       if not self.isactif():return
118       self.sdnom=nom
119       try:
120          if self.parent:
121             sd= self.parent.create_sdprod(self,nom)
122             if type(self.definition.op_init) == types.FunctionType: 
123                apply(self.definition.op_init,(self,self.parent.g_context))
124          else:
125             sd=self.get_sd_prod()
126             # On n'utilise pas self.definition.op_init car self.parent 
127             # n'existe pas
128             if sd != None and self.reuse == None:
129                # On ne nomme le concept que dans le cas de non reutilisation 
130                # d un concept
131                sd.nom=nom
132          if self.jdc and self.jdc.par_lot == "NON" :
133             self.Execute()
134          return sd
135       except AsException,e:
136          raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
137                               'fichier : ',self.appel[1],e)
138       except EOFError:
139          # XXX Normalement le contexte courant doit etre le parent.
140          # Il n'y a pas de raison de remettre le contexte au parent
141          #self.reset_current_step()
142          raise
143       except :
144          l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2])
145          raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
146                            'fichier : ',self.appel[1]+'\n',
147                             string.join(l))
148
149    def Execute(self):
150       """
151          Cette methode est prevue pour faire une execution dans le cas
152          ou par_lot == 'NON'
153          Par defaut, elle ne fait rien
154       """
155       return
156
157    def get_sd_prod(self):
158       """
159           Retourne le concept résultat de l'étape
160           Deux cas :
161                    cas 1 : sd_prod de oper n'est pas une fonction
162                            il s'agit d'une sous classe de ASSD
163                            on construit le sd à partir de cette classe
164                            et on le retourne
165                    cas 2 : il s'agit d'une fonction
166                            on l'évalue avec les mots-clés de l'étape (mc_liste)
167                            on construit le sd à partir de la classe obtenue
168                            et on le retourne
169       """
170       if type(self.definition.sd_prod) == types.FunctionType:
171         d=self.cree_dict_valeurs(self.mc_liste)
172         try:
173           sd_prod= apply(self.definition.sd_prod,(),d)
174         except EOFError:
175           raise
176         except:
177           if CONTEXT.debug: traceback.print_exc()
178           l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],
179                                        sys.exc_info()[2])
180           raise AsException("impossible d affecter un type au resultat",
181                              string.join(l[2:]))
182           #         sys.exc_info()[0],sys.exc_info()[1],)
183       else:
184         sd_prod=self.definition.sd_prod
185       # on teste maintenant si la SD est réutilisée ou s'il faut la créer
186       if self.reuse:
187         # Il est preferable de traiter cette erreur ultérieurement : ce n'est pas une erreur fatale
188         #if AsType(self.reuse) != sd_prod:
189         #  raise AsException("type de concept reutilise incompatible avec type produit")
190         self.sd=self.reuse
191       else:
192         self.sd= sd_prod(etape=self)
193         # Si reuse n'a pas ete donné, c'est une erreur. Ne pas corriger afin de la detecter ensuite
194         #if self.definition.reentrant == 'o':
195         #  self.reuse = self.sd
196       return self.sd
197
198    def get_type_produit(self):
199       """
200           Retourne le type du concept résultat de l'étape
201           Deux cas :
202            cas 1 : sd_prod de oper n'est pas une fonction
203                    il s'agit d'une sous classe de ASSD
204                    on retourne le nom de la classe
205            cas 2 : il s'agit d'une fonction
206                     on l'évalue avec les mots-clés de l'étape (mc_liste)
207                    et on retourne son résultat
208       """
209       if type(self.definition.sd_prod) == types.FunctionType:
210         d=self.cree_dict_valeurs(self.mc_liste)
211         try:
212           sd_prod= apply(self.definition.sd_prod,(),d)
213         except:
214           #traceback.print_exc()
215           return None
216       else:
217         sd_prod=self.definition.sd_prod
218       return sd_prod
219
220    def get_etape(self):
221       """
222          Retourne l'étape à laquelle appartient self
223          Un objet de la catégorie etape doit retourner self pour indiquer que
224          l'étape a été trouvée
225          XXX fait double emploi avec self.etape ????
226       """
227       return self
228
229    def supprime(self):
230       """
231          Méthode qui supprime toutes les références arrières afin que l'objet puisse
232          etre correctement détruit par le garbage collector
233       """
234       N_MCCOMPO.MCCOMPO.supprime(self)
235       self.jdc=None
236       self.appel=None
237       if self.sd : self.sd.supprime()
238
239    def isactif(self):
240       """ 
241          Indique si l'étape est active (1) ou inactive (0)
242       """
243       return self.actif
244
245    def set_current_step(self):
246       """
247           Methode utilisee pour que l etape self se declare etape
248           courante. Utilise par les macros
249       """
250       #print "set_current_step ",self.nom
251       #traceback.print_stack(limit=3,file=sys.stdout)
252       cs= CONTEXT.get_current_step()
253       if self.parent != cs :
254          raise "L'étape courante %s devrait etre le parent de self : %s" % (cs,self)
255       else :
256          CONTEXT.unset_current_step()
257          CONTEXT.set_current_step(self)
258
259    def reset_current_step(self):
260       """ 
261             Methode utilisee par l'etape self qui remet son etape parent comme 
262              etape courante 
263       """
264       #print "reset_current_step ",self.nom
265       #traceback.print_stack(limit=3,file=sys.stdout)
266       cs= CONTEXT.get_current_step()
267       if self != cs :
268          raise "L'étape courante %s devrait etre self : %s" % (cs,self)
269       else :
270          CONTEXT.unset_current_step()
271          CONTEXT.set_current_step(self.parent)
272
273    def issubstep(self,etape):
274       """ 
275           Cette methode retourne un entier indiquant si etape est une
276           sous etape de self ou non
277           1 = oui
278           0 = non
279           Une étape simple n'a pas de sous etape
280       """
281       return 0
282
283    def get_file(self,unite=None,fic_origine=''):
284       """ 
285          Retourne le nom du fichier associe a l unite logique unite (entier)
286          ainsi que le source contenu dans le fichier
287       """
288       if self.jdc : return self.jdc.get_file(unite=unite,fic_origine=fic_origine)
289       else :
290          file = None
291          if unite != None:
292             if os.path.exists("fort."+str(unite)):
293                file= "fort."+str(unite)
294          if file == None : 
295             raise AsException("Impossible de trouver le fichier correspondant a l unite %s" % unite)
296          if not os.path.exists(file): 
297             raise AsException("%s n'est pas un fichier existant" % unite)
298          fproc=open(file,'r')
299          text=string.replace(fproc.read(),'\r\n','\n')
300          fproc.close()
301          linecache.cache[file]=0,0,string.split(text,'\n'),file
302          return file,text
303
304    def accept(self,visitor):
305       """
306          Cette methode permet de parcourir l'arborescence des objets
307          en utilisant le pattern VISITEUR
308       """
309       visitor.visitETAPE(self)
310
311    def update_context(self,d):
312       """
313           Cette methode doit updater le contexte fournit par
314           l'appelant en argument (d) en fonction de sa definition
315       """
316       if type(self.definition.op_init) == types.FunctionType:
317         apply(self.definition.op_init,(self,d))
318       if self.sd:
319         d[self.sd.nom]=self.sd
320
321    def copy(self):
322       """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
323           et sans sd 
324       """
325       etape = copy(self)
326       etape.sd = None
327       etape.state = 'modified'
328       etape.reuse = None
329       etape.sdnom = None
330       etape.etape=etape
331       etape.mc_liste=[]
332       for objet in self.mc_liste:
333         new_obj = objet.copy()
334         new_obj.reparent(etape)
335         etape.mc_liste.append(new_obj)
336       return etape
337
338    def copy_reuse(self,old_etape):
339       """ Méthode qui copie le reuse d'une autre étape. 
340       """
341       if hasattr(old_etape,"reuse") :
342         self.reuse = old_etape.reuse
343
344    def copy_sdnom(self,old_etape):
345       """ Méthode qui copie le sdnom d'une autre étape. 
346       """
347       if hasattr(old_etape,"sdnom") :
348         self.sdnom = old_etape.sdnom
349
350    def get_sd_utilisees(self):
351       """ 
352           Retourne la liste des concepts qui sont utilisés à l'intérieur d'une commande
353           ( comme valorisation d'un MCS) 
354       """
355       l=[]
356       for child in self.mc_liste:
357         l.extend(child.get_sd_utilisees())
358       return l
359
360    def reparent(self,parent):
361      """
362          Cette methode sert a reinitialiser la parente de l'objet
363      """
364      self.parent=parent
365      self.jdc=parent.get_jdc_root()
366      self.etape=self
367      for mocle in self.mc_liste:
368         mocle.reparent(self)