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