Salome HOME
CCAR: merge du developpement realise dans la branche BR_PN_VAL
[tools/eficas.git] / Noyau / N_ETAPE.py
1 #@ MODIF N_ETAPE Noyau  DATE 26/09/2003   AUTEUR DURAND C.DURAND 
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       except AsException,e:
133          raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
134                               'fichier : ',self.appel[1],e)
135       except EOFError:
136          raise
137       except :
138          l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2])
139          raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
140                            'fichier : ',self.appel[1]+'\n',
141                             string.join(l))
142
143       self.Execute()
144       return sd
145
146    def Execute(self):
147       """
148          Cette methode est un point d'entree prevu pour realiser une execution immediatement
149          apres avoir construit les mots cles et le concept produit.
150          Par defaut, elle ne fait rien. Elle doit etre surchargee dans une autre partie du programme.
151       """
152       return
153
154    def get_sd_prod(self):
155       """
156           Retourne le concept résultat de l'étape
157           Deux cas :
158                    cas 1 : sd_prod de oper n'est pas une fonction
159                            il s'agit d'une sous classe de ASSD
160                            on construit le sd à partir de cette classe
161                            et on le retourne
162                    cas 2 : il s'agit d'une fonction
163                            on l'évalue avec les mots-clés de l'étape (mc_liste)
164                            on construit le sd à partir de la classe obtenue
165                            et on le retourne
166       """
167       if type(self.definition.sd_prod) == types.FunctionType:
168         d=self.cree_dict_valeurs(self.mc_liste)
169         try:
170           sd_prod= apply(self.definition.sd_prod,(),d)
171         except EOFError:
172           raise
173         except:
174           if CONTEXT.debug: traceback.print_exc()
175           l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],
176                                        sys.exc_info()[2])
177           raise AsException("impossible d affecter un type au resultat",
178                              string.join(l[2:]))
179           #         sys.exc_info()[0],sys.exc_info()[1],)
180       else:
181         sd_prod=self.definition.sd_prod
182       # on teste maintenant si la SD est réutilisée ou s'il faut la créer
183       if self.definition.reentrant != 'n' and self.reuse:
184         # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale.
185         # Elle sera traitee ulterieurement.
186         self.sd=self.reuse
187       else:
188         self.sd= sd_prod(etape=self)
189         # Si l'operateur est obligatoirement reentrant et reuse n'a pas ete specifie, c'est une erreur. 
190         # On ne fait rien ici. L'erreur sera traiter par la suite.
191       return self.sd
192
193    def get_type_produit(self):
194       """
195           Retourne le type du concept résultat de l'étape
196           Deux cas :
197            cas 1 : sd_prod de oper n'est pas une fonction
198                    il s'agit d'une sous classe de ASSD
199                    on retourne le nom de la classe
200            cas 2 : il s'agit d'une fonction
201                     on l'évalue avec les mots-clés de l'étape (mc_liste)
202                    et on retourne son résultat
203       """
204       if type(self.definition.sd_prod) == types.FunctionType:
205         d=self.cree_dict_valeurs(self.mc_liste)
206         try:
207           sd_prod= apply(self.definition.sd_prod,(),d)
208         except:
209           #traceback.print_exc()
210           return None
211       else:
212         sd_prod=self.definition.sd_prod
213       return sd_prod
214
215    def get_etape(self):
216       """
217          Retourne l'étape à laquelle appartient self
218          Un objet de la catégorie etape doit retourner self pour indiquer que
219          l'étape a été trouvée
220          XXX fait double emploi avec self.etape ????
221       """
222       return self
223
224    def supprime(self):
225       """
226          Méthode qui supprime toutes les références arrières afin que l'objet puisse
227          etre correctement détruit par le garbage collector
228       """
229       N_MCCOMPO.MCCOMPO.supprime(self)
230       self.jdc=None
231       self.appel=None
232       if self.sd : self.sd.supprime()
233
234    def isactif(self):
235       """ 
236          Indique si l'étape est active (1) ou inactive (0)
237       """
238       return self.actif
239
240    def set_current_step(self):
241       """
242           Methode utilisee pour que l etape self se declare etape
243           courante. Utilise par les macros
244       """
245       #print "set_current_step ",self.nom
246       #traceback.print_stack(limit=3,file=sys.stdout)
247       cs= CONTEXT.get_current_step()
248       if self.parent != cs :
249          raise "L'étape courante %s devrait etre le parent de self : %s" % (cs,self)
250       else :
251          CONTEXT.unset_current_step()
252          CONTEXT.set_current_step(self)
253
254    def reset_current_step(self):
255       """ 
256             Methode utilisee par l'etape self qui remet son etape parent comme 
257              etape courante 
258       """
259       #print "reset_current_step ",self.nom
260       #traceback.print_stack(limit=3,file=sys.stdout)
261       cs= CONTEXT.get_current_step()
262       if self != cs :
263          raise "L'étape courante %s devrait etre self : %s" % (cs,self)
264       else :
265          CONTEXT.unset_current_step()
266          CONTEXT.set_current_step(self.parent)
267
268    def issubstep(self,etape):
269       """ 
270           Cette methode retourne un entier indiquant si etape est une
271           sous etape de self ou non
272           1 = oui
273           0 = non
274           Une étape simple n'a pas de sous etape
275       """
276       return 0
277
278    def get_file(self,unite=None,fic_origine=''):
279       """ 
280          Retourne le nom du fichier associe a l unite logique unite (entier)
281          ainsi que le source contenu dans le fichier
282       """
283       if self.jdc : return self.jdc.get_file(unite=unite,fic_origine=fic_origine)
284       else :
285          file = None
286          if unite != None:
287             if os.path.exists("fort."+str(unite)):
288                file= "fort."+str(unite)
289          if file == None : 
290             raise AsException("Impossible de trouver le fichier correspondant a l unite %s" % unite)
291          if not os.path.exists(file): 
292             raise AsException("%s n'est pas un fichier existant" % unite)
293          fproc=open(file,'r')
294          text=string.replace(fproc.read(),'\r\n','\n')
295          fproc.close()
296          linecache.cache[file]=0,0,string.split(text,'\n'),file
297          return file,text
298
299    def accept(self,visitor):
300       """
301          Cette methode permet de parcourir l'arborescence des objets
302          en utilisant le pattern VISITEUR
303       """
304       visitor.visitETAPE(self)
305
306    def update_context(self,d):
307       """
308           Cette methode doit updater le contexte fournit par
309           l'appelant en argument (d) en fonction de sa definition
310       """
311       if type(self.definition.op_init) == types.FunctionType:
312         apply(self.definition.op_init,(self,d))
313       if self.sd:
314         d[self.sd.nom]=self.sd
315
316    def copy(self):
317       """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
318           et sans sd 
319       """
320       etape = copy(self)
321       etape.sd = None
322       etape.state = 'modified'
323       etape.reuse = None
324       etape.sdnom = None
325       etape.etape=etape
326       etape.mc_liste=[]
327       for objet in self.mc_liste:
328         new_obj = objet.copy()
329         new_obj.reparent(etape)
330         etape.mc_liste.append(new_obj)
331       return etape
332
333    def copy_reuse(self,old_etape):
334       """ Méthode qui copie le reuse d'une autre étape. 
335       """
336       if hasattr(old_etape,"reuse") :
337         self.reuse = old_etape.reuse
338
339    def copy_sdnom(self,old_etape):
340       """ Méthode qui copie le sdnom d'une autre étape. 
341       """
342       if hasattr(old_etape,"sdnom") :
343         self.sdnom = old_etape.sdnom
344
345    def get_sd_utilisees(self):
346       """ 
347           Retourne la liste des concepts qui sont utilisés à l'intérieur d'une commande
348           ( comme valorisation d'un MCS) 
349       """
350       l=[]
351       for child in self.mc_liste:
352         l.extend(child.get_sd_utilisees())
353       return l
354
355    def reparent(self,parent):
356      """
357          Cette methode sert a reinitialiser la parente de l'objet
358      """
359      self.parent=parent
360      self.jdc=parent.get_jdc_root()
361      self.etape=self
362      for mocle in self.mc_liste:
363         mocle.reparent(self)