Salome HOME
5031451be55cd2a9786347a9568d6c723bd0cbf8
[tools/eficas.git] / Noyau / N_ETAPE.py
1 #@ MODIF N_ETAPE Noyau  DATE 12/10/2011   AUTEUR COURTOIS M.COURTOIS 
2 # -*- coding: iso-8859-1 -*-
3 # RESPONSABLE COURTOIS M.COURTOIS
4 #            CONFIGURATION MANAGEMENT OF EDF VERSION
5 # ======================================================================
6 # COPYRIGHT (C) 1991 - 2011  EDF R&D                  WWW.CODE-ASTER.ORG
7 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
8 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
9 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
10 # (AT YOUR OPTION) ANY LATER VERSION.
11 #
12 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
13 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
14 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
15 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
16 #
17 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
18 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
19 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
20 #
21 #
22 # ======================================================================
23
24
25 """
26     Ce module contient la classe ETAPE qui sert a verifier et a executer
27     une commande
28 """
29
30 # Modules Python
31 import types,sys,string,os
32 import linecache
33 import traceback
34 from copy import copy
35
36 # Modules EFICAS
37 import N_MCCOMPO
38 from N_Exception import AsException
39 import N_utils
40 from N_utils import AsType
41 from N_ASSD import ASSD
42 from N_info import message, SUPERV
43
44 class ETAPE(N_MCCOMPO.MCCOMPO):
45    """
46       Cette classe herite de MCCOMPO car ETAPE est un OBJECT composite
47
48    """
49    nature = "OPERATEUR"
50
51    # L'attribut de classe codex est utilise pour rattacher le module de calcul eventuel (voir Build)
52    # On le met a None pour indiquer qu'il n'y a pas de module de calcul rattache
53    codex=None
54
55    def __init__(self,oper=None,reuse=None,args={}):
56       """
57          Attributs :
58
59           - definition : objet portant les attributs de definition d'une etape de type operateur. Il
60                          est initialise par l'argument oper.
61
62           - reuse : indique le concept d'entree reutilise. Il se trouvera donc en sortie
63                     si les conditions d'execution de l'operateur l'autorise
64
65           - valeur : arguments d'entree de type mot-cle=valeur. Initialise avec l'argument args.
66
67       """
68       self.definition=oper
69       self.reuse=reuse
70       self.valeur=args
71       self.nettoiargs()
72       self.parent=CONTEXT.get_current_step()
73       self.etape = self
74       self.nom=oper.nom
75       self.idracine=oper.label
76       self.appel=N_utils.callee_where()
77       self.mc_globaux={}
78       self.sd=None
79       self.actif=1
80       self.make_register()
81
82    def make_register(self):
83       """
84          Initialise les attributs jdc, id, niveau et realise les
85          enregistrements necessaires
86       """
87       if self.parent :
88          self.jdc = self.parent.get_jdc_root()
89          self.id=self.parent.register(self)
90          self.niveau=None
91       else:
92          self.jdc = self.parent =None
93          self.id=None
94          self.niveau=None
95
96    def nettoiargs(self):
97       """
98          Cette methode a pour fonction de retirer tous les arguments egaux a None
99          de la liste des arguments. Ils sont supposes non presents et donc retires.
100       """
101       for k in self.valeur.keys():
102          if self.valeur[k] == None:del self.valeur[k]
103
104    def McBuild(self):
105       """
106          Demande la construction des sous-objets et les stocke dans l'attribut
107          mc_liste.
108       """
109       self.mc_liste=self.build_mc()
110
111    def Build_sd(self,nom):
112       """
113          Construit le concept produit de l'operateur. Deux cas
114          peuvent se presenter :
115
116            - le parent n'est pas defini. Dans ce cas, l'etape prend en charge la creation
117              et le nommage du concept.
118
119            - le parent est defini. Dans ce cas, l'etape demande au parent la creation et
120              le nommage du concept.
121
122       """
123       message.debug(SUPERV, "Build_sd %s", self.nom)
124       self.sdnom=nom
125       try:
126          if self.parent:
127             sd= self.parent.create_sdprod(self,nom)
128             if type(self.definition.op_init) == types.FunctionType:
129                apply(self.definition.op_init,(self,self.parent.g_context))
130          else:
131             sd=self.get_sd_prod()
132             # On n'utilise pas self.definition.op_init car self.parent
133             # n'existe pas
134             if sd != None and self.reuse == None:
135                # On ne nomme le concept que dans le cas de non reutilisation
136                # d un concept
137                sd.set_name(nom)
138       except AsException,e:
139          raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
140                               'fichier : ',self.appel[1],e)
141       except EOFError:
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       self.Execute()
150       return sd
151
152    def Execute(self):
153       """
154          Cette methode est un point d'entree prevu pour realiser une execution immediatement
155          apres avoir construit les mots cles et le concept produit.
156          Par defaut, elle ne fait rien. Elle doit etre surchargee dans une autre partie du programme.
157       """
158       return
159
160    def get_sd_prod(self):
161       """
162           Retourne le concept resultat de l'etape
163           Deux cas :
164                    - cas 1 : sd_prod de oper n'est pas une fonction
165                      il s'agit d'une sous classe de ASSD
166                      on construit le sd a partir de cette classe
167                      et on le retourne
168                    - cas 2 : il s'agit d'une fonction
169                      on l'evalue avec les mots-cles de l'etape (mc_liste)
170                      on construit le sd a partir de la classe obtenue
171                      et on le retourne
172       """
173       if type(self.definition.sd_prod) == types.FunctionType:
174         d=self.cree_dict_valeurs(self.mc_liste)
175         try:
176           sd_prod= apply(self.definition.sd_prod,(),d)
177         except EOFError:
178           raise
179         except:
180           if CONTEXT.debug: traceback.print_exc()
181           l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],
182                                        sys.exc_info()[2])
183           raise AsException("impossible d affecter un type au resultat",
184                              string.join(l[2:]))
185           #         sys.exc_info()[0],sys.exc_info()[1],)
186       else:
187         sd_prod=self.definition.sd_prod
188       # on teste maintenant si la SD est reutilisee ou s'il faut la creer
189       if self.definition.reentrant != 'n' and self.reuse:
190         # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale.
191         # Elle sera traitee ulterieurement.
192         self.sd=self.reuse
193       else:
194         self.sd= sd_prod(etape=self)
195         # Si l'operateur est obligatoirement reentrant et reuse n'a pas ete specifie, c'est une erreur.
196         # On ne fait rien ici. L'erreur sera traiter par la suite.
197       # precaution
198       if self.sd is not None and not isinstance(self.sd, ASSD):
199          raise AsException("""
200 Impossible de typer le resultat !
201 Causes possibles :
202    Utilisateur : Soit la valeur fournie derriere "reuse" est incorrecte,
203                  soit il y a une "," a la fin d'une commande precedente.
204    Developpeur : La fonction "sd_prod" retourne un type invalide.""")
205       return self.sd
206
207    def get_type_produit(self):
208       try:
209           return self.get_type_produit_brut()
210       except:
211           return None
212
213    def get_type_produit_brut(self):
214       """
215           Retourne le type du concept resultat de l'etape
216           Deux cas :
217             - cas 1 : sd_prod de oper n'est pas une fonction
218               il s'agit d'une sous classe de ASSD
219               on retourne le nom de la classe
220             - cas 2 : il s'agit d'une fonction
221               on l'evalue avec les mots-cles de l'etape (mc_liste)
222               et on retourne son resultat
223       """
224       if type(self.definition.sd_prod) == types.FunctionType:
225         d=self.cree_dict_valeurs(self.mc_liste)
226         sd_prod= apply(self.definition.sd_prod,(),d)
227       else:
228         sd_prod=self.definition.sd_prod
229       return sd_prod
230
231    def get_etape(self):
232       """
233          Retourne l'etape a laquelle appartient self
234          Un objet de la categorie etape doit retourner self pour indiquer que
235          l'etape a ete trouvee
236          XXX fait double emploi avec self.etape ????
237       """
238       return self
239
240    def supprime(self):
241       """
242          Methode qui supprime toutes les references arrieres afin que l'objet puisse
243          etre correctement detruit par le garbage collector
244       """
245       N_MCCOMPO.MCCOMPO.supprime(self)
246       self.jdc = None
247       self.appel = None
248       for name in dir(self):
249          if name.startswith( '_cache_' ):
250              setattr(self, name, None)
251       if self.sd:
252          self.sd.supprime()
253
254    def isactif(self):
255       """
256          Indique si l'etape est active (1) ou inactive (0)
257       """
258       return self.actif
259
260    def set_current_step(self):
261       """
262           Methode utilisee pour que l etape self se declare etape
263           courante. Utilise par les macros
264       """
265       message.debug(SUPERV, "call etape.set_current_step", stack_id=-1)
266       cs= CONTEXT.get_current_step()
267       if self.parent != cs :
268          raise AsException("L'etape courante", cs.nom, cs,
269                            "devrait etre le parent de", self.nom, self)
270       else :
271          CONTEXT.unset_current_step()
272          CONTEXT.set_current_step(self)
273
274    def reset_current_step(self):
275       """
276             Methode utilisee par l'etape self qui remet son etape parent comme
277             etape courante
278       """
279       cs= CONTEXT.get_current_step()
280       if self != cs :
281          raise AsException("L'etape courante", cs.nom, cs,
282                            "devrait etre", self.nom, self)
283       else :
284          CONTEXT.unset_current_step()
285          CONTEXT.set_current_step(self.parent)
286
287    def issubstep(self,etape):
288       """
289           Cette methode retourne un entier indiquant si etape est une
290           sous etape de self ou non
291           1 = oui
292           0 = non
293           Une étape simple n'a pas de sous etape
294       """
295       return 0
296
297    def get_file(self,unite=None,fic_origine=''):
298       """
299          Retourne le nom du fichier associe a l unite logique unite (entier)
300          ainsi que le source contenu dans le fichier
301       """
302       if self.jdc : return self.jdc.get_file(unite=unite,fic_origine=fic_origine)
303       else :
304          file = None
305          if unite != None:
306             if os.path.exists("fort."+str(unite)):
307                file= "fort."+str(unite)
308          if file == None :
309             raise AsException("Impossible de trouver le fichier correspondant a l unite %s" % unite)
310          if not os.path.exists(file):
311             raise AsException("%s n'est pas un fichier existant" % unite)
312          fproc=open(file,'r')
313          text=string.replace(fproc.read(),'\r\n','\n')
314          fproc.close()
315          linecache.cache[file]=0,0,string.split(text,'\n'),file
316          return file,text
317
318    def accept(self,visitor):
319       """
320          Cette methode permet de parcourir l'arborescence des objets
321          en utilisant le pattern VISITEUR
322       """
323       visitor.visitETAPE(self)
324
325    def update_context(self,d):
326       """
327           Cette methode doit updater le contexte fournit par
328           l'appelant en argument (d) en fonction de sa definition
329       """
330       if type(self.definition.op_init) == types.FunctionType:
331         apply(self.definition.op_init,(self,d))
332       if self.sd:
333         d[self.sd.nom]=self.sd
334
335    def copy(self):
336       """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
337           et sans sd
338       """
339       etape = copy(self)
340       etape.sd = None
341       etape.state = 'modified'
342       etape.reuse = None
343       etape.sdnom = None
344       etape.etape=etape
345       etape.mc_liste=[]
346       for objet in self.mc_liste:
347         new_obj = objet.copy()
348         new_obj.reparent(etape)
349         etape.mc_liste.append(new_obj)
350       return etape
351
352    def copy_reuse(self,old_etape):
353       """ Méthode qui copie le reuse d'une autre étape.
354       """
355       if hasattr(old_etape,"reuse") :
356         self.reuse = old_etape.reuse
357
358    def copy_sdnom(self,old_etape):
359       """ Méthode qui copie le sdnom d'une autre étape.
360       """
361       if hasattr(old_etape,"sdnom") :
362         self.sdnom = old_etape.sdnom
363
364    def reparent(self,parent):
365      """
366          Cette methode sert a reinitialiser la parente de l'objet
367      """
368      self.parent=parent
369      self.jdc=parent.get_jdc_root()
370      self.etape=self
371      for mocle in self.mc_liste:
372         mocle.reparent(self)
373      if self.sd and self.reuse == None :
374         self.sd.jdc=self.jdc
375
376    def get_cmd(self,nomcmd):
377       """
378           Méthode pour recuperer la definition d'une commande
379           donnee par son nom dans les catalogues declares
380           au niveau du jdc
381           Appele par un ops d'une macro en Python
382       """
383       return self.jdc.get_cmd(nomcmd)
384
385    def copy_intern(self,etape):
386       """
387           Méthode permettant lors du processus de recopie de copier
388           les elements internes d'une etape dans une autre
389       """
390       return
391
392    def full_copy(self,parent=None):
393        """
394           Méthode permettant d'effectuer une copie complète
395           d'une étape (y compris concept produit, éléments internes)
396           Si l'argument parent est fourni, la nouvelle étape
397           aura cet objet comme parent.
398        """
399        new_etape = self.copy()
400        new_etape.copy_reuse(self)
401        new_etape.copy_sdnom(self)
402        if parent: new_etape.reparent(parent)
403        if self.sd :
404           new_sd = self.sd.__class__(etape=new_etape)
405           new_etape.sd = new_sd
406           if self.reuse == None :
407              new_etape.parent.NommerSdprod(new_sd,self.sd.nom)
408           else :
409              new_sd.set_name(self.sd.nom)
410        new_etape.copy_intern(self)
411        return new_etape
412
413    def reset_jdc(self,new_jdc):
414        """
415           Reinitialise le nommage du concept de l'etape lors d'un changement de jdc
416        """
417        if self.sd and self.reuse == None :
418            self.parent.NommerSdprod(self.sd,self.sd.nom)
419
420
421    def is_include(self):
422       """Permet savoir si on a affaire à la commande INCLUDE
423       car le comportement de ces macros est particulier.
424       """
425       return self.nom.startswith('INCLUDE')
426
427    def sd_accessible(self):
428       """Dit si on peut acceder aux "valeurs" (jeveux) de l'ASSD produite par l'étape.
429       """
430       if CONTEXT.debug: print '`- ETAPE sd_accessible :', self.nom
431       return self.parent.sd_accessible()
432
433    def get_concept(self, nomsd):
434       """
435           Méthode pour recuperer un concept à partir de son nom
436       """
437       # pourrait être appelée par une commande fortran faisant appel à des fonctions python
438       # on passe la main au parent
439       return self.parent.get_concept(nomsd)