Salome HOME
dde08f5b508a397ff31ff813fae0773dcc5dc7ec
[tools/eficas.git] / Noyau / N_ETAPE.py
1 #@ MODIF N_ETAPE Noyau  DATE 10/05/2006   AUTEUR MCOURTOI M.COURTOIS 
2 # -*- coding: iso-8859-1 -*-
3 #            CONFIGURATION MANAGEMENT OF EDF VERSION
4 # ======================================================================
5 # COPYRIGHT (C) 1991 - 2002  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
23
24 """ 
25     Ce module contient la classe ETAPE qui sert à vérifier et à exécuter
26     une commande
27 """
28
29 # Modules Python
30 import types,sys,string,os
31 import linecache
32 import traceback
33 from copy import copy
34
35 # Modules EFICAS
36 import N_MCCOMPO
37 from N_Exception import AsException
38 import N_utils
39 from N_utils import AsType
40
41 class ETAPE(N_MCCOMPO.MCCOMPO):
42    """
43       Cette classe hérite de MCCOMPO car ETAPE est un OBJECT composite
44
45    """
46    nature = "OPERATEUR"
47
48    # L'attribut de classe codex est utilisé pour rattacher le module de calcul éventuel (voir Build)
49    # On le met à None pour indiquer qu'il n'y a pas de module de calcul rattaché
50    codex=None
51
52    def __init__(self,oper=None,reuse=None,args={}):
53       """
54          Attributs :
55
56           - definition : objet portant les attributs de définition d'une étape de type opérateur. Il
57                          est initialisé par l'argument oper.
58
59           - reuse : indique le concept d'entrée réutilisé. Il se trouvera donc en sortie
60                     si les conditions d'exécution de l'opérateur l'autorise
61
62           - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé avec l'argument args.
63
64       """
65       self.definition=oper
66       self.reuse=reuse
67       self.valeur=args
68       self.nettoiargs()
69       self.parent=CONTEXT.get_current_step()
70       self.etape = self
71       self.nom=oper.nom
72       self.idracine=oper.label
73       self.appel=N_utils.callee_where()
74       self.mc_globaux={}
75       self.sd=None
76       self.actif=1
77       self.make_register()
78
79    def make_register(self):
80       """
81          Initialise les attributs jdc, id, niveau et réalise les 
82          enregistrements nécessaires
83       """
84       if self.parent :
85          self.jdc = self.parent.get_jdc_root()
86          self.id=self.parent.register(self)
87          self.niveau=None
88       else:
89          self.jdc = self.parent =None
90          self.id=None
91          self.niveau=None
92
93    def nettoiargs(self):
94       """
95          Cette methode a pour fonction de retirer tous les arguments egaux à None
96          de la liste des arguments. Ils sont supposés non présents et donc retirés.
97       """
98       for k in self.valeur.keys():
99          if self.valeur[k] == None:del self.valeur[k]
100
101    def McBuild(self):
102       """
103          Demande la construction des sous-objets et les stocke dans l'attribut
104          mc_liste.
105       """
106       self.mc_liste=self.build_mc()
107
108    def Build_sd(self,nom):
109       """
110          Construit le concept produit de l'opérateur. Deux cas 
111          peuvent se présenter :
112         
113          - le parent n'est pas défini. Dans ce cas, l'étape prend en charge la création 
114            et le nommage du concept.
115
116          - le parent est défini. Dans ce cas, l'étape demande au parent la création et 
117            le nommage du concept.
118
119       """
120       self.sdnom=nom
121       try:
122          if self.parent:
123             sd= self.parent.create_sdprod(self,nom)
124             if type(self.definition.op_init) == types.FunctionType: 
125                apply(self.definition.op_init,(self,self.parent.g_context))
126          else:
127             sd=self.get_sd_prod()
128             # On n'utilise pas self.definition.op_init car self.parent 
129             # n'existe pas
130             if sd != None and self.reuse == None:
131                # On ne nomme le concept que dans le cas de non reutilisation 
132                # d un concept
133                sd.nom=nom
134       except AsException,e:
135          raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
136                               'fichier : ',self.appel[1],e)
137       except EOFError:
138          raise
139       except :
140          l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2])
141          raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
142                            'fichier : ',self.appel[1]+'\n',
143                             string.join(l))
144
145       self.Execute()
146       return sd
147
148    def Execute(self):
149       """
150          Cette methode est un point d'entree prevu pour realiser une execution immediatement
151          apres avoir construit les mots cles et le concept produit.
152          Par defaut, elle ne fait rien. Elle doit etre surchargee dans une autre partie du programme.
153       """
154       return
155
156    def get_sd_prod(self):
157       """
158           Retourne le concept résultat de l'étape
159           Deux cas :
160                    cas 1 : sd_prod de oper n'est pas une fonction
161                            il s'agit d'une sous classe de ASSD
162                            on construit le sd à partir de cette classe
163                            et on le retourne
164                    cas 2 : il s'agit d'une fonction
165                            on l'évalue avec les mots-clés de l'étape (mc_liste)
166                            on construit le sd à partir de la classe obtenue
167                            et on le retourne
168       """
169       if type(self.definition.sd_prod) == types.FunctionType:
170         d=self.cree_dict_valeurs(self.mc_liste)
171         try:
172           sd_prod= apply(self.definition.sd_prod,(),d)
173         except EOFError:
174           raise
175         except:
176           if CONTEXT.debug: traceback.print_exc()
177           l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],
178                                        sys.exc_info()[2])
179           raise AsException("impossible d affecter un type au resultat",
180                              string.join(l[2:]))
181           #         sys.exc_info()[0],sys.exc_info()[1],)
182       else:
183         sd_prod=self.definition.sd_prod
184       # on teste maintenant si la SD est réutilisée ou s'il faut la créer
185       if self.definition.reentrant != 'n' and self.reuse:
186         # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale.
187         # Elle sera traitee ulterieurement.
188         self.sd=self.reuse
189       else:
190         self.sd= sd_prod(etape=self)
191         # Si l'operateur est obligatoirement reentrant et reuse n'a pas ete specifie, c'est une erreur. 
192         # On ne fait rien ici. L'erreur sera traiter par la suite.
193       return self.sd
194
195    def get_type_produit(self):
196       try:
197           return self.get_type_produit_brut()
198       except:
199           return None
200
201    def get_type_produit_brut(self):
202       """
203           Retourne le type du concept résultat de l'étape
204           Deux cas :
205            cas 1 : sd_prod de oper n'est pas une fonction
206                    il s'agit d'une sous classe de ASSD
207                    on retourne le nom de la classe
208            cas 2 : il s'agit d'une fonction
209                     on l'évalue avec les mots-clés de l'étape (mc_liste)
210                    et on retourne son résultat
211       """
212       if type(self.definition.sd_prod) == types.FunctionType:
213         d=self.cree_dict_valeurs(self.mc_liste)
214         sd_prod= apply(self.definition.sd_prod,(),d)
215       else:
216         sd_prod=self.definition.sd_prod
217       return sd_prod
218
219    def get_etape(self):
220       """
221          Retourne l'étape à laquelle appartient self
222          Un objet de la catégorie etape doit retourner self pour indiquer que
223          l'étape a été trouvée
224          XXX fait double emploi avec self.etape ????
225       """
226       return self
227
228    def supprime(self):
229       """
230          Méthode qui supprime toutes les références arrières afin que l'objet puisse
231          etre correctement détruit par le garbage collector
232       """
233       N_MCCOMPO.MCCOMPO.supprime(self)
234       self.jdc=None
235       self.appel=None
236       if self.sd : self.sd.supprime()
237
238    def isactif(self):
239       """ 
240          Indique si l'étape est active (1) ou inactive (0)
241       """
242       return self.actif
243
244    def set_current_step(self):
245       """
246           Methode utilisee pour que l etape self se declare etape
247           courante. Utilise par les macros
248       """
249       #print "set_current_step ",self.nom
250       #traceback.print_stack(limit=3,file=sys.stdout)
251       cs= CONTEXT.get_current_step()
252       if self.parent != cs :
253          raise "L'étape courante %s devrait etre le parent de self : %s" % (cs,self)
254       else :
255          CONTEXT.unset_current_step()
256          CONTEXT.set_current_step(self)
257
258    def reset_current_step(self):
259       """ 
260             Methode utilisee par l'etape self qui remet son etape parent comme 
261              etape courante 
262       """
263       #print "reset_current_step ",self.nom
264       #traceback.print_stack(limit=3,file=sys.stdout)
265       cs= CONTEXT.get_current_step()
266       if self != cs :
267          raise "L'étape courante %s devrait etre self : %s" % (cs,self)
268       else :
269          CONTEXT.unset_current_step()
270          CONTEXT.set_current_step(self.parent)
271
272    def issubstep(self,etape):
273       """ 
274           Cette methode retourne un entier indiquant si etape est une
275           sous etape de self ou non
276           1 = oui
277           0 = non
278           Une étape simple n'a pas de sous etape
279       """
280       return 0
281
282    def get_file(self,unite=None,fic_origine=''):
283       """ 
284          Retourne le nom du fichier associe a l unite logique unite (entier)
285          ainsi que le source contenu dans le fichier
286       """
287       if self.jdc : return self.jdc.get_file(unite=unite,fic_origine=fic_origine)
288       else :
289          file = None
290          if unite != None:
291             if os.path.exists("fort."+str(unite)):
292                file= "fort."+str(unite)
293          if file == None : 
294             raise AsException("Impossible de trouver le fichier correspondant a l unite %s" % unite)
295          if not os.path.exists(file): 
296             raise AsException("%s n'est pas un fichier existant" % unite)
297          fproc=open(file,'r')
298          text=string.replace(fproc.read(),'\r\n','\n')
299          fproc.close()
300          linecache.cache[file]=0,0,string.split(text,'\n'),file
301          return file,text
302
303    def accept(self,visitor):
304       """
305          Cette methode permet de parcourir l'arborescence des objets
306          en utilisant le pattern VISITEUR
307       """
308       visitor.visitETAPE(self)
309
310    def update_context(self,d):
311       """
312           Cette methode doit updater le contexte fournit par
313           l'appelant en argument (d) en fonction de sa definition
314       """
315       if type(self.definition.op_init) == types.FunctionType:
316         apply(self.definition.op_init,(self,d))
317       if self.sd:
318         d[self.sd.nom]=self.sd
319
320    def copy(self):
321       """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
322           et sans sd 
323       """
324       etape = copy(self)
325       etape.sd = None
326       etape.state = 'modified'
327       etape.reuse = None
328       etape.sdnom = None
329       etape.etape=etape
330       etape.mc_liste=[]
331       for objet in self.mc_liste:
332         new_obj = objet.copy()
333         new_obj.reparent(etape)
334         etape.mc_liste.append(new_obj)
335       return etape
336
337    def copy_reuse(self,old_etape):
338       """ Méthode qui copie le reuse d'une autre étape. 
339       """
340       if hasattr(old_etape,"reuse") :
341         self.reuse = old_etape.reuse
342
343    def copy_sdnom(self,old_etape):
344       """ Méthode qui copie le sdnom d'une autre étape. 
345       """
346       if hasattr(old_etape,"sdnom") :
347         self.sdnom = old_etape.sdnom
348
349    def reparent(self,parent):
350      """
351          Cette methode sert a reinitialiser la parente de l'objet
352      """
353      self.parent=parent
354      self.jdc=parent.get_jdc_root()
355      self.etape=self
356      for mocle in self.mc_liste:
357         mocle.reparent(self)
358      if self.sd and self.reuse == None :
359         self.sd.jdc=self.jdc
360
361    def get_cmd(self,nomcmd):
362       """
363           Méthode pour recuperer la definition d'une commande
364           donnee par son nom dans les catalogues declares
365           au niveau du jdc
366           Appele par un ops d'une macro en Python
367       """
368       return self.jdc.get_cmd(nomcmd)
369
370    def copy_intern(self,etape):
371       """
372           Méthode permettant lors du processus de recopie de copier
373           les elements internes d'une etape dans une autre
374       """
375       return
376
377    def full_copy(self,parent=None):
378        """
379           Méthode permettant d'effectuer une copie complète
380           d'une étape (y compris concept produit, éléments internes)
381           Si l'argument parent est fourni, la nouvelle étape
382           aura cet objet comme parent.
383        """
384        new_etape = self.copy()
385        new_etape.copy_reuse(self)
386        new_etape.copy_sdnom(self)
387        if parent: new_etape.reparent(parent)
388        if self.sd :
389           new_sd = self.sd.__class__(etape=new_etape)
390           new_etape.sd = new_sd
391           if self.reuse == None :
392              new_etape.parent.NommerSdprod(new_sd,self.sd.nom)
393           else :
394              new_sd.nom = self.sd.nom
395        new_etape.copy_intern(self)
396        return new_etape
397
398    def reset_jdc(self,new_jdc):
399        """
400           Reinitialise le nommage du concept de l'etape lors d'un changement de jdc
401        """
402        if self.sd and self.reuse == None :
403            self.parent.NommerSdprod(self.sd,self.sd.nom)
404