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.
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.
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.
22 # ======================================================================
26 Ce module contient la classe ETAPE qui sert a verifier et a executer
31 import types,sys,string,os
38 from N_Exception import AsException
40 from N_utils import AsType
41 from N_ASSD import ASSD
42 from N_info import message, SUPERV
44 class ETAPE(N_MCCOMPO.MCCOMPO):
46 Cette classe herite de MCCOMPO car ETAPE est un OBJECT composite
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
55 def __init__(self,oper=None,reuse=None,args={}):
59 - definition : objet portant les attributs de definition d'une etape de type operateur. Il
60 est initialise par l'argument oper.
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
65 - valeur : arguments d'entree de type mot-cle=valeur. Initialise avec l'argument args.
72 self.parent=CONTEXT.get_current_step()
75 self.idracine=oper.label
76 self.appel=N_utils.callee_where()
82 def make_register(self):
84 Initialise les attributs jdc, id, niveau et realise les
85 enregistrements necessaires
88 self.jdc = self.parent.get_jdc_root()
89 self.id=self.parent.register(self)
92 self.jdc = self.parent =None
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.
101 for k in self.valeur.keys():
102 if self.valeur[k] == None:del self.valeur[k]
106 Demande la construction des sous-objets et les stocke dans l'attribut
109 self.mc_liste=self.build_mc()
111 def Build_sd(self,nom):
113 Construit le concept produit de l'operateur. Deux cas
114 peuvent se presenter :
116 - le parent n'est pas defini. Dans ce cas, l'etape prend en charge la creation
117 et le nommage du concept.
119 - le parent est defini. Dans ce cas, l'etape demande au parent la creation et
120 le nommage du concept.
123 message.debug(SUPERV, "Build_sd %s", self.nom)
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))
131 sd=self.get_sd_prod()
132 # On n'utilise pas self.definition.op_init car self.parent
134 if sd != None and self.reuse == None:
135 # On ne nomme le concept que dans le cas de non reutilisation
138 except AsException,e:
139 raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
140 'fichier : ',self.appel[1],e)
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',
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.
160 def get_sd_prod(self):
162 Retourne le concept resultat de l'etape
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
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
173 if type(self.definition.sd_prod) == types.FunctionType:
174 d=self.cree_dict_valeurs(self.mc_liste)
176 sd_prod= apply(self.definition.sd_prod,(),d)
180 if CONTEXT.debug: traceback.print_exc()
181 l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],
183 raise AsException("impossible d affecter un type au resultat",
185 # sys.exc_info()[0],sys.exc_info()[1],)
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.
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.
198 if self.sd is not None and not isinstance(self.sd, ASSD):
199 raise AsException("""
200 Impossible de typer le resultat !
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.""")
207 def get_type_produit(self):
209 return self.get_type_produit_brut()
213 def get_type_produit_brut(self):
215 Retourne le type du concept resultat de l'etape
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
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)
228 sd_prod=self.definition.sd_prod
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 ????
242 Methode qui supprime toutes les references arrieres afin que l'objet puisse
243 etre correctement detruit par le garbage collector
245 N_MCCOMPO.MCCOMPO.supprime(self)
248 for name in dir(self):
249 if name.startswith( '_cache_' ):
250 setattr(self, name, None)
256 Indique si l'etape est active (1) ou inactive (0)
260 def set_current_step(self):
262 Methode utilisee pour que l etape self se declare etape
263 courante. Utilise par les macros
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)
271 CONTEXT.unset_current_step()
272 CONTEXT.set_current_step(self)
274 def reset_current_step(self):
276 Methode utilisee par l'etape self qui remet son etape parent comme
279 cs= CONTEXT.get_current_step()
281 raise AsException("L'etape courante", cs.nom, cs,
282 "devrait etre", self.nom, self)
284 CONTEXT.unset_current_step()
285 CONTEXT.set_current_step(self.parent)
287 def issubstep(self,etape):
289 Cette methode retourne un entier indiquant si etape est une
290 sous etape de self ou non
293 Une étape simple n'a pas de sous etape
297 def get_file(self,unite=None,fic_origine=''):
299 Retourne le nom du fichier associe a l unite logique unite (entier)
300 ainsi que le source contenu dans le fichier
302 if self.jdc : return self.jdc.get_file(unite=unite,fic_origine=fic_origine)
306 if os.path.exists("fort."+str(unite)):
307 file= "fort."+str(unite)
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)
313 text=string.replace(fproc.read(),'\r\n','\n')
315 linecache.cache[file]=0,0,string.split(text,'\n'),file
318 def accept(self,visitor):
320 Cette methode permet de parcourir l'arborescence des objets
321 en utilisant le pattern VISITEUR
323 visitor.visitETAPE(self)
325 def update_context(self,d):
327 Cette methode doit updater le contexte fournit par
328 l'appelant en argument (d) en fonction de sa definition
330 if type(self.definition.op_init) == types.FunctionType:
331 apply(self.definition.op_init,(self,d))
333 d[self.sd.nom]=self.sd
336 """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
341 etape.state = 'modified'
346 for objet in self.mc_liste:
347 new_obj = objet.copy()
348 new_obj.reparent(etape)
349 etape.mc_liste.append(new_obj)
352 def copy_reuse(self,old_etape):
353 """ Méthode qui copie le reuse d'une autre étape.
355 if hasattr(old_etape,"reuse") :
356 self.reuse = old_etape.reuse
358 def copy_sdnom(self,old_etape):
359 """ Méthode qui copie le sdnom d'une autre étape.
361 if hasattr(old_etape,"sdnom") :
362 self.sdnom = old_etape.sdnom
364 def reparent(self,parent):
366 Cette methode sert a reinitialiser la parente de l'objet
369 self.jdc=parent.get_jdc_root()
371 for mocle in self.mc_liste:
373 if self.sd and self.reuse == None :
376 def get_cmd(self,nomcmd):
378 Méthode pour recuperer la definition d'une commande
379 donnee par son nom dans les catalogues declares
381 Appele par un ops d'une macro en Python
383 return self.jdc.get_cmd(nomcmd)
385 def copy_intern(self,etape):
387 Méthode permettant lors du processus de recopie de copier
388 les elements internes d'une etape dans une autre
392 def full_copy(self,parent=None):
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.
399 new_etape = self.copy()
400 new_etape.copy_reuse(self)
401 new_etape.copy_sdnom(self)
402 if parent: new_etape.reparent(parent)
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)
409 new_sd.set_name(self.sd.nom)
410 new_etape.copy_intern(self)
413 def reset_jdc(self,new_jdc):
415 Reinitialise le nommage du concept de l'etape lors d'un changement de jdc
417 if self.sd and self.reuse == None :
418 self.parent.NommerSdprod(self.sd,self.sd.nom)
421 def is_include(self):
422 """Permet savoir si on a affaire à la commande INCLUDE
423 car le comportement de ces macros est particulier.
425 return self.nom.startswith('INCLUDE')
427 def sd_accessible(self):
428 """Dit si on peut acceder aux "valeurs" (jeveux) de l'ASSD produite par l'étape.
430 if CONTEXT.debug: print '`- ETAPE sd_accessible :', self.nom
431 return self.parent.sd_accessible()
433 def get_concept(self, nomsd):
435 Méthode pour recuperer un concept à partir de son nom
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)